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