Skip to main content

rs_firebase_admin_sdk/
lib.rs

1pub mod api_uri;
2pub mod auth;
3pub mod client;
4pub mod credentials;
5#[cfg(feature = "tokens")]
6pub mod jwt;
7pub mod util;
8
9use auth::FirebaseAuth;
10use client::ReqwestApiClient;
11use credentials::{GCPCredentialsError, emulator::EmulatorCredentials, get_project_id};
12use error_stack::{Report, ResultExt};
13use google_cloud_auth::credentials::Builder;
14pub use google_cloud_auth::credentials::{Credentials, CredentialsProvider};
15use std::sync::Arc;
16
17const FIREBASE_AUTH_SCOPES: [&str; 2] = [
18    "https://www.googleapis.com/auth/cloud-platform",
19    "https://www.googleapis.com/auth/userinfo.email",
20];
21
22#[derive(Debug, Clone, thiserror::Error)]
23#[error("Failed to create Firebase token validator")]
24pub struct FirebaseAppValidatorError;
25
26pub enum App {
27    Live {
28        credentials: Credentials,
29        project_id: String,
30    },
31    Emulated {
32        credentials: EmulatorCredentials,
33        url: String,
34    },
35}
36
37impl App {
38    pub async fn live() -> Result<Self, Report<GCPCredentialsError>> {
39        let credentials: Credentials = Builder::default()
40            .with_scopes(FIREBASE_AUTH_SCOPES)
41            .build_access_token_credentials()
42            .change_context(GCPCredentialsError)?
43            .into();
44
45        let project_id = get_project_id(&credentials)
46            .await
47            .change_context(GCPCredentialsError)?;
48
49        Ok(Self::Live {
50            credentials,
51            project_id,
52        })
53    }
54
55    pub fn live_with_project_id(project_id: String) -> Result<Self, Report<GCPCredentialsError>> {
56        let credentials: Credentials = Builder::default()
57            .with_scopes(FIREBASE_AUTH_SCOPES)
58            .build_access_token_credentials()
59            .change_context(GCPCredentialsError)?
60            .into();
61
62        Ok(Self::Live {
63            credentials,
64            project_id,
65        })
66    }
67
68    pub fn emulated(url: String) -> Self {
69        Self::Emulated {
70            credentials: EmulatorCredentials::default(),
71            url,
72        }
73    }
74
75    pub fn auth(&self) -> FirebaseAuth<ReqwestApiClient> {
76        match self {
77            Self::Live {
78                credentials,
79                project_id,
80            } => {
81                let client = ReqwestApiClient::new(reqwest::Client::new(), credentials.clone());
82
83                FirebaseAuth::live(project_id, client)
84            }
85            Self::Emulated { credentials, url } => {
86                let client =
87                    ReqwestApiClient::new(reqwest::Client::new(), credentials.clone().into());
88
89                FirebaseAuth::emulated(url.clone(), &credentials.project_id, client)
90            }
91        }
92    }
93
94    #[cfg(feature = "tokens")]
95    pub fn token_validator(
96        &self,
97    ) -> Result<Arc<dyn jwt::TokenValidator>, Report<FirebaseAppValidatorError>> {
98        match self {
99            Self::Live {
100                credentials: _,
101                project_id,
102            } => jwt::LiveValidator::new_jwt_validator(project_id.clone())
103                .change_context(FirebaseAppValidatorError)
104                .map(|s| Arc::new(s) as Arc<dyn jwt::TokenValidator>),
105            Self::Emulated {
106                credentials: _,
107                url: _,
108            } => Ok(Arc::new(jwt::EmulatorValidator) as Arc<dyn jwt::TokenValidator>),
109        }
110    }
111
112    #[cfg(feature = "tokens")]
113    pub fn cookie_validator(
114        &self,
115    ) -> Result<Arc<dyn jwt::TokenValidator>, Report<FirebaseAppValidatorError>> {
116        match self {
117            Self::Live {
118                credentials: _,
119                project_id,
120            } => jwt::LiveValidator::new_cookie_validator(project_id.clone())
121                .change_context(FirebaseAppValidatorError)
122                .map(|s| Arc::new(s) as Arc<dyn jwt::TokenValidator>),
123            Self::Emulated {
124                credentials: _,
125                url: _,
126            } => Ok(Arc::new(jwt::EmulatorValidator) as Arc<dyn jwt::TokenValidator>),
127        }
128    }
129}