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