bitwarden_auth/login/login_client.rs
1use bitwarden_core::{Client, ClientSettings};
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, ClientSettings, 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/// // Configure client settings and create login client
28/// let settings = ClientSettings {
29/// identity_url: "https://identity.bitwarden.com".to_string(),
30/// api_url: "https://api.bitwarden.com".to_string(),
31/// user_agent: "MyApp/1.0".to_string(),
32/// device_type: DeviceType::SDK,
33/// device_identifier: None,
34/// bitwarden_client_version: None,
35/// bitwarden_package_type: None,
36/// };
37/// let login_client = auth_client.login(settings);
38///
39/// // Get user's KDF config
40/// let prelogin = login_client.get_password_prelogin(email.clone()).await?;
41///
42/// // Login with credentials
43/// let response = login_client.login_via_password(PasswordLoginRequest {
44/// login_request: LoginRequest {
45/// client_id: "connector".to_string(),
46/// device: LoginDeviceRequest {
47/// device_type: DeviceType::SDK,
48/// device_identifier: "device-id".to_string(),
49/// device_name: "My Device".to_string(),
50/// device_push_token: None,
51/// },
52/// },
53/// email,
54/// password,
55/// prelogin_response: prelogin,
56/// }).await?;
57///
58/// // Use tokens from response for authenticated requests
59/// match response {
60/// LoginResponse::Authenticated(success) => {
61/// let access_token = success.access_token;
62/// // Use access_token for authenticated requests
63/// }
64/// }
65/// # Ok(())
66/// # }
67/// ```
68#[cfg_attr(feature = "wasm", wasm_bindgen)]
69#[cfg_attr(feature = "uniffi", derive(uniffi::Object))]
70pub struct LoginClient {
71 pub(crate) client: Client,
72}
73
74impl LoginClient {
75 /// Creates a new `LoginClient` with the given client settings.
76 ///
77 /// # Note
78 ///
79 /// This method is `pub(crate)` because `LoginClient` instances should be obtained through
80 /// the AuthClient. Direct instantiation is internal to the crate.
81 pub(crate) fn new(settings: ClientSettings) -> Self {
82 let core_client = Client::new(Some(settings));
83
84 Self {
85 client: core_client,
86 }
87 }
88}
89
90#[cfg(test)]
91mod tests {
92 use super::*;
93
94 #[test]
95 fn test_login_client_creation() {
96 let client_settings = ClientSettings::default();
97 let login_client = LoginClient::new(client_settings);
98
99 // Verify the internal client exists (type check)
100 let _client = &login_client.client;
101 // The fact that this compiles and doesn't panic means the client was created successfully
102 }
103}