use std::sync::Arc;
use foundation_auth::shared::jwt::{
JwtAlgorithm, JwtSigningKey, JwtVerifier, JwtVerifierConfig, PublicKeySource,
};
use foundation_context::Ctx;
use foundation_db::core::storage_provider::QueryStore;
use crate::core::auth::ISSUER;
#[derive(Clone)]
pub struct KeychainContext {
db: Arc<dyn QueryStore>,
signing_key: Arc<JwtSigningKey>,
verifier: Arc<JwtVerifier>,
ctx: Ctx,
}
impl KeychainContext {
#[must_use]
pub fn new(db: Arc<dyn QueryStore>, ctx: Ctx) -> Self {
Self::with_signing_key(db, JwtSigningKey::generate_ed25519(), ctx)
}
#[must_use]
pub fn with_signing_key(db: Arc<dyn QueryStore>, signing_key: JwtSigningKey, ctx: Ctx) -> Self {
let verifier = build_verifier(&signing_key).expect("derive verifier from signing key");
Self {
db,
signing_key: Arc::new(signing_key),
verifier: Arc::new(verifier),
ctx,
}
}
#[must_use]
pub fn db(&self) -> &dyn QueryStore {
self.db.as_ref()
}
#[must_use]
pub fn signing_key(&self) -> &JwtSigningKey {
&self.signing_key
}
#[must_use]
pub fn verifier(&self) -> &JwtVerifier {
&self.verifier
}
#[must_use]
pub fn ctx(&self) -> &Ctx {
&self.ctx
}
}
fn build_verifier(
signing_key: &JwtSigningKey,
) -> Result<JwtVerifier, foundation_auth::shared::jwt::JwtError> {
let pem = signing_key.public_key_pem()?;
JwtVerifier::from_config(JwtVerifierConfig {
allowed_algorithms: vec![
JwtAlgorithm::EdDSA,
JwtAlgorithm::RS256,
JwtAlgorithm::ES256,
],
issuer: Some(ISSUER.to_string()),
audience: None,
key_id: None,
public_key: PublicKeySource::Pem(pem),
})
}