bitwarden_auth/login/login_client.rs
1use bitwarden_core::Client;
2
3/// Client for authenticating Bitwarden users.
4///
5/// Handles unauthenticated operations to obtain access tokens from the Identity API.
6/// After successful authentication, use the returned tokens to create an authenticated core client.
7///
8/// # Lifecycle
9///
10/// 1. Create `LoginClient` via `AuthClient`
11/// 2. Call login method
12/// 3. Use returned tokens with authenticated core client
13///
14/// # Password Login Example
15///
16/// ```rust,no_run
17/// # use bitwarden_auth::{AuthClient, login::login_via_password::PasswordLoginRequest};
18/// # use bitwarden_auth::login::models::{LoginRequest, LoginDeviceRequest, LoginResponse};
19/// # use bitwarden_core::{Client, DeviceType};
20/// # async fn example(email: String, password: String) -> Result<(), Box<dyn std::error::Error>> {
21/// // Create auth client
22/// let client = Client::new(None);
23/// let auth_client = AuthClient::new(client);
24///
25/// // Create login client, sharing the same backing client
26/// let login_client = auth_client.login();
27///
28/// // Get user's KDF config
29/// let prelogin = login_client.get_password_prelogin(email.clone()).await?;
30///
31/// // Login with credentials
32/// let response = login_client.login_via_password(PasswordLoginRequest {
33/// login_request: LoginRequest {
34/// client_id: "connector".to_string(),
35/// device: LoginDeviceRequest {
36/// device_type: DeviceType::SDK,
37/// device_identifier: "device-id".to_string(),
38/// device_name: "My Device".to_string(),
39/// device_push_token: None,
40/// },
41/// },
42/// email,
43/// password,
44/// prelogin_response: prelogin,
45/// }).await?;
46///
47/// // Use tokens from response for authenticated requests
48/// match response {
49/// LoginResponse::Authenticated(success) => {
50/// let access_token = success.access_token;
51/// // Use access_token for authenticated requests
52/// }
53/// }
54/// # Ok(())
55/// # }
56/// ```
57#[bitwarden_ffi::wasm_object]
58pub struct LoginClient {
59 pub(crate) client: Client,
60}
61
62impl LoginClient {
63 /// Creates a new `LoginClient` with the given client.
64 ///
65 /// # Note
66 ///
67 /// This method is `pub(crate)` because `LoginClient` instances should be obtained through
68 /// the AuthClient. Direct instantiation is internal to the crate.
69 pub(crate) fn new(client: Client) -> Self {
70 Self { client }
71 }
72}
73
74#[cfg(test)]
75mod tests {
76 use super::*;
77
78 #[test]
79 fn test_login_client_creation() {
80 let client = Client::new(None);
81 let login_client = LoginClient::new(client);
82
83 // Verify the internal client exists (type check)
84 let _client = &login_client.client;
85 // The fact that this compiles and doesn't panic means the client was created successfully
86 }
87}