rs_firebase_admin_sdk/
lib.rs1pub 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}