From 37cf254c355903ff04ad5f7fa43fd12569472d8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20M=C3=BCller?= Date: Thu, 5 Feb 2026 11:00:00 +0000 Subject: [PATCH] Add JWT signing and verification --- src/auth/jwt.rs | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 src/auth/jwt.rs diff --git a/src/auth/jwt.rs b/src/auth/jwt.rs new file mode 100644 index 0000000..269aad9 --- /dev/null +++ b/src/auth/jwt.rs @@ -0,0 +1,35 @@ +use jsonwebtoken::{decode, encode, DecodingKey, EncodingKey, Header, Validation}; +use serde::{Deserialize, Serialize}; +use std::env; + +#[derive(Debug, Serialize, Deserialize)] +pub struct Claims { + pub sub: String, // user id + pub exp: usize, +} + +pub fn sign(user_id: &str) -> anyhow::Result { + let secret = env::var("JWT_SECRET")?; + let expiry: usize = env::var("JWT_EXPIRY_SECS") + .unwrap_or("3600".into()) + .parse()?; + let now = std::time::SystemTime::now() + .duration_since(std::time::UNIX_EPOCH)? + .as_secs() as usize; + let claims = Claims { sub: user_id.to_owned(), exp: now + expiry }; + Ok(encode( + &Header::default(), + &claims, + &EncodingKey::from_secret(secret.as_bytes()), + )?) +} + +pub fn verify(token: &str) -> anyhow::Result { + let secret = env::var("JWT_SECRET")?; + let data = decode::( + token, + &DecodingKey::from_secret(secret.as_bytes()), + &Validation::default(), + )?; + Ok(data.claims) +}