use jsonwebtoken::{decode, encode, DecodingKey, EncodingKey, Header, Validation};
pub use jsonwebtoken::{
errors::{Error, ErrorKind},
TokenData,
};
use serde::{Deserialize, Serialize};
use std::time::{SystemTime, UNIX_EPOCH};
#[derive(Debug, Serialize, Deserialize)]
pub struct Claims {
iss: String,
sub: String,
aud: String,
exp: u64,
nbf: u64,
iat: u64,
}
impl Claims {
pub fn new(iss: String, sub: String, aud: String, exp: u64, nbf: u64) -> Self {
Self {
iss,
sub,
aud,
exp,
nbf,
iat: SystemTime::now()
.duration_since(UNIX_EPOCH)
.expect("Clock may have gone backwards")
.as_secs() as u64,
}
}
}
#[derive(Clone, Debug)]
pub struct JsonWebToken(String);
impl From<String> for JsonWebToken {
fn from(inner: String) -> Self {
JsonWebToken(inner)
}
}
impl std::fmt::Display for JsonWebToken {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.0)
}
}
impl JsonWebToken {
pub fn new(
issuer: String,
subject: String,
audience: String,
session_timeout: u64,
secret: &[u8],
) -> Result<Self, Error> {
let now = SystemTime::now()
.duration_since(UNIX_EPOCH)
.expect("Clock may have gone backwards")
.as_secs() as u64;
let claims = Claims::new(issuer, subject, audience, now + session_timeout, now);
let token = encode(&Header::default(), &claims, &EncodingKey::from_secret(secret))?;
Ok(Self(token))
}
pub fn validate(
&self,
issuer: String,
subject: String,
audience: String,
secret: &[u8],
) -> Result<TokenData<Claims>, Error> {
let mut validation = Validation {
iss: Some(issuer),
sub: Some(subject),
..Default::default()
};
validation.set_audience(&[audience]);
decode::<Claims>(&self.0, &DecodingKey::from_secret(secret), &validation)
}
}