Skip to main content

aster_forge_auth/
provider.rs

1//! Explicit initialization of the upstream process-wide JWT crypto provider.
2
3use crate::{AuthError, Result};
4use std::sync::atomic::{AtomicBool, Ordering};
5
6// Only a successful explicit installation makes Forge JWT operations available. The upstream
7// provider is immutable once installed; this flag neither selects nor replaces that provider.
8static INITIALIZED: AtomicBool = AtomicBool::new(false);
9
10/// Installs the backend selected by this crate's Cargo features for the entire process.
11///
12/// Call exactly once from the product composition root before starting workers or making any
13/// JWT calls, including direct `jsonwebtoken` calls. Features are additive: another dependency
14/// may enable the other upstream backend, but this explicit selection remains deterministic.
15/// Custom providers and separate providers per signer/verifier are not supported.
16///
17/// # Errors
18/// Returns [`AuthError::CryptoProviderAlreadyInstalled`] if any caller has already initialized
19/// the upstream provider, including upstream automatic initialization. No provider is replaced
20/// or silently accepted. A duplicate call after Forge's successful initialization returns this
21/// error while existing JWT operations remain available. If another caller installed first,
22/// Forge stays unavailable; the product must treat that as a startup configuration failure.
23pub fn initialize_jwt_crypto_provider() -> Result<()> {
24    #[cfg(feature = "aws-lc-rs")]
25    let provider = &jsonwebtoken::crypto::aws_lc::DEFAULT_PROVIDER;
26    #[cfg(all(feature = "rust-crypto", not(feature = "aws-lc-rs")))]
27    let provider = &jsonwebtoken::crypto::rust_crypto::DEFAULT_PROVIDER;
28
29    #[cfg(any(feature = "aws-lc-rs", feature = "rust-crypto"))]
30    provider
31        .install_default()
32        .map_err(|_| AuthError::CryptoProviderAlreadyInstalled)?;
33
34    INITIALIZED.store(true, Ordering::Release);
35    Ok(())
36}
37
38pub(crate) fn ensure_initialized() -> Result<()> {
39    if INITIALIZED.load(Ordering::Acquire) {
40        Ok(())
41    } else {
42        Err(AuthError::CryptoProviderNotInitialized)
43    }
44}