use std::sync::Arc;
use super::LiveKeyRing;
use crate::{
Claims,
error::{AuthError, Result},
};
pub trait AccessTokenSigner: Send + Sync + std::fmt::Debug {
fn sign_access_token(&self, claims: &Claims) -> Result<String>;
}
#[derive(Debug, Clone)]
pub struct RingSigner {
ring: Arc<LiveKeyRing>,
max_lifetime_secs: u64,
}
impl RingSigner {
#[must_use]
pub const fn new(ring: Arc<LiveKeyRing>, max_lifetime_secs: u64) -> Self {
Self {
ring,
max_lifetime_secs,
}
}
}
impl AccessTokenSigner for RingSigner {
fn sign_access_token(&self, claims: &Claims) -> Result<String> {
let lifetime = claims.exp.saturating_sub(claims.iat);
if lifetime > self.max_lifetime_secs {
return Err(AuthError::ConfigError {
message: format!(
"refusing to sign an access token meant to live {lifetime}s: the \
first-party issuer keeps a retired key published for tokens of at most \
{}s",
self.max_lifetime_secs
),
});
}
self.ring.signing_ring(claims.iat)?.active().sign("at+jwt", claims)
}
}