firebase_rs_sdk/auth/
token_provider.rs

1//#![cfg(feature = "firestore")]
2use std::sync::atomic::{AtomicBool, Ordering};
3use std::sync::Arc;
4
5use crate::auth::error::AuthError;
6use crate::auth::Auth;
7use crate::firestore::{
8    internal_error, unauthenticated, unavailable, FirestoreError, FirestoreResult,
9};
10use crate::firestore::{TokenProvider, TokenProviderArc};
11
12pub struct AuthTokenProvider {
13    auth: Arc<Auth>,
14    force_refresh: AtomicBool,
15}
16
17impl AuthTokenProvider {
18    /// Creates a Firestore-compatible token provider backed by Firebase Auth.
19    pub fn new(auth: Arc<Auth>) -> Self {
20        Self {
21            auth,
22            force_refresh: AtomicBool::new(false),
23        }
24    }
25
26    /// Converts the provider into an `Arc` for Datastore integration.
27    pub fn into_arc(self) -> TokenProviderArc {
28        Arc::new(self)
29    }
30}
31
32impl Clone for AuthTokenProvider {
33    fn clone(&self) -> Self {
34        Self {
35            auth: self.auth.clone(),
36            force_refresh: AtomicBool::new(self.force_refresh.load(Ordering::SeqCst)),
37        }
38    }
39}
40
41#[cfg_attr(target_arch = "wasm32", async_trait::async_trait(?Send))]
42#[cfg_attr(not(target_arch = "wasm32"), async_trait::async_trait)]
43impl TokenProvider for AuthTokenProvider {
44    async fn get_token(&self) -> FirestoreResult<Option<String>> {
45        let force_refresh = self.force_refresh.swap(false, Ordering::SeqCst);
46        self.auth
47            .get_token(force_refresh)
48            .await
49            .map_err(map_auth_error)
50    }
51
52    fn invalidate_token(&self) {
53        self.force_refresh.store(true, Ordering::SeqCst);
54    }
55}
56
57fn map_auth_error(error: AuthError) -> FirestoreError {
58    match error {
59        AuthError::InvalidCredential(message) => unauthenticated(message),
60        AuthError::Network(message) => unavailable(message),
61        AuthError::Firebase(firebase_error) => unauthenticated(firebase_error.message),
62        AuthError::App(app_error) => internal_error(app_error.to_string()),
63        AuthError::NotImplemented(feature) => {
64            internal_error(format!("{feature} is not implemented"))
65        }
66        AuthError::MultiFactorRequired(err) => unauthenticated(err.to_string()),
67        AuthError::MultiFactor(err) => unauthenticated(err.to_string()),
68    }
69}
70
71/// Convenience helper that wraps an `Auth` instance into a token provider arc.
72pub fn auth_token_provider_arc(auth: Arc<Auth>) -> TokenProviderArc {
73    AuthTokenProvider::new(auth).into_arc()
74}