Skip to main content

bitwarden_core/auth/login/
prelogin.rs

1use bitwarden_api_identity::models::{PasswordPreloginRequestModel, PasswordPreloginResponseModel};
2use bitwarden_crypto::Kdf;
3use thiserror::Error;
4
5use crate::{ApiError, Client, MissingFieldError, require};
6
7#[allow(missing_docs)]
8#[derive(Debug, Error)]
9pub enum PreloginError {
10    #[error(transparent)]
11    Api(#[from] ApiError),
12    #[error(transparent)]
13    MissingField(#[from] MissingFieldError),
14}
15
16pub(crate) async fn prelogin(client: &Client, email: String) -> Result<Kdf, PreloginError> {
17    let request_model = PasswordPreloginRequestModel::new(email);
18    let config = client.internal.get_api_configurations();
19    let result = config
20        .identity_client
21        .accounts_api()
22        .post_password_prelogin(Some(request_model))
23        .await?;
24
25    Ok(parse_prelogin(result)?)
26}
27
28fn parse_prelogin(response: PasswordPreloginResponseModel) -> Result<Kdf, MissingFieldError> {
29    use std::num::NonZeroU32;
30
31    use bitwarden_api_identity::models::KdfType;
32
33    let kdf = require!(response.kdf);
34
35    Ok(match kdf {
36        KdfType::PBKDF2_SHA256 => Kdf::PBKDF2 {
37            iterations: NonZeroU32::new(require!(response.kdf_iterations) as u32)
38                .expect("Non-zero number"),
39        },
40        KdfType::Argon2id => Kdf::Argon2id {
41            iterations: NonZeroU32::new(require!(response.kdf_iterations) as u32)
42                .expect("Non-zero number"),
43            memory: NonZeroU32::new(require!(response.kdf_memory) as u32).expect("Non-zero number"),
44            parallelism: NonZeroU32::new(require!(response.kdf_parallelism) as u32)
45                .expect("Non-zero number"),
46        },
47        KdfType::__Unknown(_) => return Err(MissingFieldError("kdf")),
48    })
49}