mod config;
mod discovery;
mod errors;
mod main;
pub(crate) mod provider;
mod storage;
mod types;
pub use config::{enabled_providers, get_google_client_id, is_provider_enabled, provider_info};
pub use main::{prepare_fedcm_nonce, prepare_oauth2_auth_request};
pub use provider::{ProviderInfo, ProviderName};
pub use types::{
AuthResponse, FedCMCallbackRequest, FedCMNonceResponse, OAuth2Account, OAuth2Mode, OAuth2State,
Provider, ProviderUserId, TokenType,
};
use crate::storage::CacheErrorConversion;
pub(crate) use config::OAUTH2_CSRF_COOKIE_NAME;
pub(crate) use errors::OAuth2Error;
pub(crate) use types::{StateParams, StoredToken};
pub(crate) use types::{oauth2_account_from_idinfo, oauth2_account_from_idinfo_and_userinfo};
#[cfg(test)]
pub(crate) use main::prepare_oauth2_auth_request_inner;
pub(crate) use main::{
csrf_checks, decode_state, delete_session_and_misc_token_from_store, get_idinfo_userinfo,
get_mode_from_stored_session, get_uid_from_stored_session_by_state_param, validate_fedcm_token,
validate_origin,
};
pub(crate) use storage::OAuth2Store;
pub(crate) use types::{AccountId, AccountSearchField};
fn require_env_if_trigger_set(trigger: &str, required: &[&str]) -> Result<(), errors::OAuth2Error> {
if std::env::var(trigger).is_ok() {
for var in required {
if std::env::var(var).is_err() {
return Err(errors::OAuth2Error::Validation(format!(
"{trigger} is set but {var} is missing"
)));
}
}
}
Ok(())
}
pub(crate) async fn init() -> Result<(), errors::OAuth2Error> {
if std::env::var("OAUTH2_GOOGLE_CLIENT_ID").is_err() {
return Err(errors::OAuth2Error::Validation(
"OAUTH2_GOOGLE_CLIENT_ID must be set".to_string(),
));
}
if std::env::var("OAUTH2_GOOGLE_CLIENT_SECRET").is_err() {
return Err(errors::OAuth2Error::Validation(
"OAUTH2_GOOGLE_CLIENT_SECRET must be set".to_string(),
));
}
if std::env::var("ORIGIN").is_err() {
return Err(errors::OAuth2Error::Validation(
"ORIGIN must be set".to_string(),
));
}
for kind in provider::ProviderKind::ALL {
if let Some((trigger, required)) = kind.optional_env_contract() {
require_env_if_trigger_set(trigger, required)?;
}
}
provider::validate_custom_slot_preset_shape().map_err(errors::OAuth2Error::Validation)?;
provider::validate_custom_slots().map_err(errors::OAuth2Error::Validation)?;
provider::validate_named_provider_strict_display_claims()
.map_err(errors::OAuth2Error::Validation)?;
provider::validate_named_provider_prompt().map_err(errors::OAuth2Error::Validation)?;
let _ = *config::OAUTH2_CSRF_COOKIE_NAME;
let _ = *config::OAUTH2_CSRF_COOKIE_MAX_AGE;
crate::storage::init()
.await
.map_err(errors::OAuth2Error::convert_storage_error)?;
OAuth2Store::init().await?;
Ok(())
}