bitwarden_core/auth/login/
prelogin.rs1use bitwarden_api_identity::models::{PreloginRequestModel, PreloginResponseModel};
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 = PreloginRequestModel::new(email);
18 let config = client.internal.get_api_configurations().await;
19 let result = config
20 .identity_client
21 .accounts_api()
22 .post_prelogin(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}