use jsonwebtoken::{DecodingKey, EncodingKey, TokenData}; use once_cell::sync::Lazy; use serde::{de::DeserializeOwned, Serialize}; use super::Error; pub static JWT: Lazy = Lazy::new(|| { let secret = std::env::var("JWT_SECRET").expect("JWT_SECRET must be set"); JwtTranscoder::new(secret.as_bytes()) }); pub struct JwtTranscoder { encoding: EncodingKey, decoding: DecodingKey, header: jsonwebtoken::Header, validation: jsonwebtoken::Validation, } impl JwtTranscoder { fn new(secret: &[u8]) -> Self { Self { encoding: EncodingKey::from_secret(secret), decoding: DecodingKey::from_secret(secret), header: Default::default(), validation: Default::default(), } } pub fn encode(&self, claims: &T) -> Result where T: Serialize, { jsonwebtoken::encode(&self.header, claims, &self.encoding).map_err(Into::into) } pub fn decode(&self, token: &str) -> Result, Error> where T: DeserializeOwned, { jsonwebtoken::decode(token, &self.decoding, &self.validation).map_err(Into::into) } } #[cfg(test)] mod tests { use super::*; use crate::{ auth::AccessClaims, tests::{setup_test_env, TestResult}, }; #[test] fn test_jwt_encode_decode() -> TestResult { setup_test_env(); let claims = AccessClaims::issue(uuid::Uuid::new_v4()); let token = JWT.encode(&claims)?; let decoded = JWT.decode(&token)?.claims; assert_eq!(claims, decoded); Ok(()) } }