bitwarden_core/auth/login/
prelogin.rs

1use bitwarden_api_identity::{
2    apis::accounts_api::accounts_prelogin_post,
3    models::{PreloginRequestModel, PreloginResponseModel},
4};
5use bitwarden_crypto::Kdf;
6use thiserror::Error;
7
8use crate::{require, ApiError, Client, MissingFieldError};
9
10#[derive(Debug, Error)]
11pub enum PreloginError {
12    #[error(transparent)]
13    Api(#[from] ApiError),
14    #[error(transparent)]
15    MissingField(#[from] MissingFieldError),
16}
17
18pub(crate) async fn prelogin(client: &Client, email: String) -> Result<Kdf, PreloginError> {
19    let request_model = PreloginRequestModel::new(email);
20    let config = client.internal.get_api_configurations().await;
21    let result = accounts_prelogin_post(&config.identity, Some(request_model))
22        .await
23        .map_err(ApiError::from)?;
24
25    Ok(parse_prelogin(result)?)
26}
27
28fn parse_prelogin(response: PreloginResponseModel) -> Result<Kdf, MissingFieldError> {
29    use std::num::NonZeroU32;
30
31    use bitwarden_api_identity::models::KdfType;
32    use bitwarden_crypto::{
33        default_argon2_iterations, default_argon2_memory, default_argon2_parallelism,
34        default_pbkdf2_iterations,
35    };
36
37    let kdf = require!(response.kdf);
38
39    Ok(match kdf {
40        KdfType::PBKDF2_SHA256 => Kdf::PBKDF2 {
41            iterations: response
42                .kdf_iterations
43                .and_then(|e| NonZeroU32::new(e as u32))
44                .unwrap_or_else(default_pbkdf2_iterations),
45        },
46        KdfType::Argon2id => Kdf::Argon2id {
47            iterations: response
48                .kdf_iterations
49                .and_then(|e| NonZeroU32::new(e as u32))
50                .unwrap_or_else(default_argon2_iterations),
51            memory: response
52                .kdf_memory
53                .and_then(|e| NonZeroU32::new(e as u32))
54                .unwrap_or_else(default_argon2_memory),
55            parallelism: response
56                .kdf_parallelism
57                .and_then(|e| NonZeroU32::new(e as u32))
58                .unwrap_or_else(default_argon2_parallelism),
59        },
60    })
61}