pub mod api_uri;
pub mod auth;
pub mod client;
pub mod credentials;
#[cfg(feature = "tokens")]
pub mod jwt;
pub mod util;
use auth::FirebaseAuth;
use client::ReqwestApiClient;
use core::marker::PhantomData;
use credentials::{GCPCredentialsError, emulator::EmulatorCredentials, get_project_id};
use error_stack::{Report, ResultExt};
use google_cloud_auth::credentials::{AccessTokenCredentials, Builder};
pub use google_cloud_auth::credentials::{Credentials, CredentialsProvider};
const FIREBASE_AUTH_SCOPES: [&str; 2] = [
"https://www.googleapis.com/auth/cloud-platform",
"https://www.googleapis.com/auth/userinfo.email",
];
pub struct App<C> {
credentials: Credentials,
project_id: String,
_credentials_provider: PhantomData<C>,
}
impl App<EmulatorCredentials> {
pub fn emulated() -> Self {
let credentials = EmulatorCredentials::default();
Self {
project_id: credentials.project_id.clone(),
credentials: credentials.into(),
_credentials_provider: PhantomData,
}
}
pub fn auth(&self, emulator_url: String) -> FirebaseAuth<ReqwestApiClient> {
let client = ReqwestApiClient::new(reqwest::Client::new(), self.credentials.clone());
FirebaseAuth::emulated(emulator_url, &self.project_id, client)
}
#[cfg(feature = "tokens")]
pub fn id_token_verifier(&self) -> impl jwt::TokenValidator {
jwt::EmulatorValidator
}
}
impl App<AccessTokenCredentials> {
pub async fn live_with_project_id(
project_id: &str,
) -> Result<Self, Report<GCPCredentialsError>> {
let credentials: Credentials = Builder::default()
.with_scopes(FIREBASE_AUTH_SCOPES)
.build_access_token_credentials()
.change_context(GCPCredentialsError)?
.into();
Ok(Self {
credentials,
project_id: project_id.to_string(),
_credentials_provider: PhantomData,
})
}
pub async fn live() -> Result<Self, Report<GCPCredentialsError>> {
let credentials: Credentials = Builder::default()
.with_scopes(FIREBASE_AUTH_SCOPES)
.build_access_token_credentials()
.change_context(GCPCredentialsError)?
.into();
let project_id = get_project_id(&credentials)
.await
.change_context(GCPCredentialsError)?;
Ok(Self {
credentials,
project_id,
_credentials_provider: PhantomData,
})
}
pub fn auth(&self) -> FirebaseAuth<ReqwestApiClient> {
let client = ReqwestApiClient::new(reqwest::Client::new(), self.credentials.clone());
FirebaseAuth::live(&self.project_id, client)
}
#[cfg(feature = "tokens")]
pub async fn id_token_verifier(
&self,
) -> Result<impl jwt::TokenValidator, Report<credentials::GCPCredentialsError>> {
jwt::LiveValidator::new_jwt_validator(self.project_id.clone())
.change_context(credentials::GCPCredentialsError)
}
#[cfg(feature = "tokens")]
pub async fn cookie_token_verifier(
&self,
) -> Result<impl jwt::TokenValidator, Report<credentials::GCPCredentialsError>> {
jwt::LiveValidator::new_cookie_validator(self.project_id.clone())
.change_context(credentials::GCPCredentialsError)
}
}