use crate::claims::JwtClaims;
use crate::error::AuthError;
use jwt_simple::prelude::*;
#[derive(Clone)]
pub struct SigningKeys {
key_pair: RS256KeyPair,
public_key: RS256PublicKey,
}
impl SigningKeys {
pub fn generate() -> Result<Self, AuthError> {
let key_pair = RS256KeyPair::generate(4096).map_err(|e| AuthError::KeyGeneration(e.to_string()))?;
let public_key = key_pair.public_key();
Ok(Self { key_pair, public_key })
}
pub fn from_pem(pem: &str) -> Result<Self, AuthError> {
let key_pair = RS256KeyPair::from_pem(pem).map_err(|e| AuthError::KeyParsing(e.to_string()))?;
let public_key = key_pair.public_key();
Ok(Self { key_pair, public_key })
}
pub fn sign(&self, claims: &JwtClaims, duration: Duration) -> Result<String, AuthError> {
let jwt_claims = Claims::with_custom_claims(claims.clone(), duration).with_subject(&claims.sub);
self.key_pair.sign(jwt_claims).map_err(|e| AuthError::Signing(e.to_string()))
}
pub fn verify(&self, token: &str) -> Result<JwtClaims, AuthError> {
let result = self.public_key.verify_token::<JwtClaims>(token, None).map_err(|e| AuthError::Verification(e.to_string()))?;
let sub = result.subject.ok_or_else(|| AuthError::Verification("missing subject claim".into()))?;
let mut claims = result.custom;
claims.sub = sub;
Ok(claims)
}
pub fn public_key_pem(&self) -> Result<String, AuthError> { self.public_key.to_pem().map_err(|e| AuthError::KeyExport(e.to_string())) }
pub fn private_key_pem(&self) -> Result<String, AuthError> { self.key_pair.to_pem().map_err(|e| AuthError::KeyExport(e.to_string())) }
}
#[derive(Clone)]
pub enum JwtKeys {
Signing(SigningKeys),
VerifyOnly(RS256PublicKey),
}
impl JwtKeys {
pub fn verify(&self, token: &str) -> Result<JwtClaims, AuthError> {
match self {
JwtKeys::Signing(keys) => keys.verify(token),
JwtKeys::VerifyOnly(public_key) => {
let result = public_key.verify_token::<JwtClaims>(token, None).map_err(|e| AuthError::Verification(e.to_string()))?;
let sub = result.subject.ok_or_else(|| AuthError::Verification("missing subject claim".into()))?;
let mut claims = result.custom;
claims.sub = sub;
Ok(claims)
}
}
}
pub fn public_key_pem(&self) -> Result<String, AuthError> {
match self {
JwtKeys::Signing(keys) => keys.public_key_pem(),
JwtKeys::VerifyOnly(public_key) => public_key.to_pem().map_err(|e| AuthError::KeyExport(e.to_string())),
}
}
pub fn from_public_pem(pem: &str) -> Result<Self, AuthError> {
let public_key = RS256PublicKey::from_pem(pem).map_err(|e| AuthError::KeyParsing(e.to_string()))?;
Ok(JwtKeys::VerifyOnly(public_key))
}
}