use axum::extract::Request;
use chrono::{Duration, Utc};
use jsonwebtoken::errors::Error;
use jsonwebtoken::{DecodingKey, EncodingKey, Header, Validation};
use once_cell::sync::Lazy;
pub use claims::JWTClaims;
use token::Token;
mod claims;
mod token;
pub struct JWT;
impl JWT {
pub fn token(username: String) -> eyre::Result<Token> {
let exp = Utc::now() + Duration::seconds(JWT_CONFIG.get_expire());
let token = jsonwebtoken::encode(
&Header::default(),
&JWTClaims::new(
None,
exp.timestamp(),
Some(Utc::now().timestamp()),
None,
None,
Some(username),
),
&EncodingKey::from_secret(JWT_CONFIG.get_secret()),
)?;
Ok(Token::new(token, JWT_CONFIG.get_expire() + 60)) }
pub fn authorize(request: &Request) -> Result<JWTClaims, Error> {
let token_data = jsonwebtoken::decode::<JWTClaims>(
Token::parse_from_header(request.headers())?,
&DecodingKey::from_secret(JWT_CONFIG.get_secret()),
&Validation::default(),
)?;
Ok(token_data.claims)
}
}
struct JwtConfig {
secret: String,
expire: i64,
}
impl JwtConfig {
fn new(secret: String, expire: i64) -> Self {
Self { secret, expire }
}
fn get_secret(&self) -> &[u8] {
self.secret.as_bytes()
}
fn get_expire(&self) -> i64 {
self.expire
}
}
static JWT_CONFIG: Lazy<JwtConfig> = Lazy::new(|| {
let secret = std::env::var("JWT_SECRET").expect("JWT_SECRET must be set");
let expire = std::env::var("JWT_EXPIRE").expect("JWT_EXPIRE must be set");
JwtConfig::new(secret, expire.parse().unwrap_or(3600))
});