rs-firebase-admin-sdk 5.0.0

Firebase Admin SDK for Rust
Documentation
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 credentials::{GCPCredentialsError, emulator::EmulatorCredentials, get_project_id};
use error_stack::{Report, ResultExt};
use google_cloud_auth::credentials::Builder;
pub use google_cloud_auth::credentials::{Credentials, CredentialsProvider};
use std::sync::Arc;

const FIREBASE_AUTH_SCOPES: [&str; 2] = [
    "https://www.googleapis.com/auth/cloud-platform",
    "https://www.googleapis.com/auth/userinfo.email",
];

#[derive(Debug, Clone, thiserror::Error)]
#[error("Failed to create Firebase token validator")]
pub struct FirebaseAppValidatorError;

pub enum App {
    Live {
        credentials: Credentials,
        project_id: String,
    },
    Emulated {
        credentials: EmulatorCredentials,
        url: String,
    },
}

impl App {
    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::Live {
            credentials,
            project_id,
        })
    }

    pub fn live_with_project_id(project_id: String) -> Result<Self, Report<GCPCredentialsError>> {
        let credentials: Credentials = Builder::default()
            .with_scopes(FIREBASE_AUTH_SCOPES)
            .build_access_token_credentials()
            .change_context(GCPCredentialsError)?
            .into();

        Ok(Self::Live {
            credentials,
            project_id,
        })
    }

    pub fn emulated(url: String) -> Self {
        Self::Emulated {
            credentials: EmulatorCredentials::default(),
            url,
        }
    }

    pub fn auth(&self) -> FirebaseAuth<ReqwestApiClient> {
        match self {
            Self::Live {
                credentials,
                project_id,
            } => {
                let client = ReqwestApiClient::new(reqwest::Client::new(), credentials.clone());

                FirebaseAuth::live(project_id, client)
            }
            Self::Emulated { credentials, url } => {
                let client =
                    ReqwestApiClient::new(reqwest::Client::new(), credentials.clone().into());

                FirebaseAuth::emulated(url.clone(), &credentials.project_id, client)
            }
        }
    }

    #[cfg(feature = "tokens")]
    pub fn token_validator(
        &self,
    ) -> Result<Arc<dyn jwt::TokenValidator>, Report<FirebaseAppValidatorError>> {
        match self {
            Self::Live {
                credentials: _,
                project_id,
            } => jwt::LiveValidator::new_jwt_validator(project_id.clone())
                .change_context(FirebaseAppValidatorError)
                .map(|s| Arc::new(s) as Arc<dyn jwt::TokenValidator>),
            Self::Emulated {
                credentials: _,
                url: _,
            } => Ok(Arc::new(jwt::EmulatorValidator) as Arc<dyn jwt::TokenValidator>),
        }
    }

    #[cfg(feature = "tokens")]
    pub fn cookie_validator(
        &self,
    ) -> Result<Arc<dyn jwt::TokenValidator>, Report<FirebaseAppValidatorError>> {
        match self {
            Self::Live {
                credentials: _,
                project_id,
            } => jwt::LiveValidator::new_cookie_validator(project_id.clone())
                .change_context(FirebaseAppValidatorError)
                .map(|s| Arc::new(s) as Arc<dyn jwt::TokenValidator>),
            Self::Emulated {
                credentials: _,
                url: _,
            } => Ok(Arc::new(jwt::EmulatorValidator) as Arc<dyn jwt::TokenValidator>),
        }
    }
}