bitwarden_core/auth/login/
two_factor.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
use bitwarden_api_api::models::TwoFactorEmailRequestModel;
use bitwarden_crypto::HashPurpose;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use serde_repr::{Deserialize_repr, Serialize_repr};

use crate::{auth::determine_password_hash, error::Result, Client};

#[derive(Serialize, Deserialize, Debug, JsonSchema)]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
pub struct TwoFactorEmailRequest {
    /// User Password
    pub password: String,
    /// User email
    pub email: String,
}

pub(crate) async fn send_two_factor_email(
    client: &Client,
    input: &TwoFactorEmailRequest,
) -> Result<()> {
    // TODO: This should be resolved from the client
    let kdf = client.auth().prelogin(input.email.clone()).await?;

    let password_hash = determine_password_hash(
        &input.email,
        &kdf,
        &input.password,
        HashPurpose::ServerAuthorization,
    )?;

    let config = client.internal.get_api_configurations().await;
    bitwarden_api_api::apis::two_factor_api::two_factor_send_email_login_post(
        &config.api,
        Some(TwoFactorEmailRequestModel {
            master_password_hash: Some(password_hash),
            otp: None,
            auth_request_access_code: None,
            secret: None,
            email: input.email.to_owned(),
            auth_request_id: None,
            sso_email2_fa_session_token: None,
        }),
    )
    .await?;
    Ok(())
}

#[derive(Serialize_repr, Deserialize_repr, PartialEq, Debug, JsonSchema, Clone)]
#[repr(u8)]
pub enum TwoFactorProvider {
    Authenticator = 0,
    Email = 1,
    Duo = 2,
    Yubikey = 3,
    U2f = 4,
    Remember = 5,
    OrganizationDuo = 6,
    WebAuthn = 7,
}

#[derive(Serialize, Deserialize, Debug, JsonSchema)]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
pub struct TwoFactorRequest {
    /// Two-factor Token
    pub token: String,
    /// Two-factor provider
    pub provider: TwoFactorProvider,
    /// Two-factor remember
    pub remember: bool,
}