jwt implementation and login, not working yet
This commit is contained in:
55
server/src/auth/logic/jwt.rs
Normal file
55
server/src/auth/logic/jwt.rs
Normal file
@@ -0,0 +1,55 @@
|
||||
// src/auth/jwt.rs
|
||||
use jsonwebtoken::{encode, decode, Header, EncodingKey, DecodingKey, Validation};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use time::{Duration, OffsetDateTime};
|
||||
use uuid::Uuid;
|
||||
use std::sync::OnceLock;
|
||||
use crate::auth::models::AuthError;
|
||||
|
||||
static KEYS: OnceLock<Keys> = OnceLock::new();
|
||||
|
||||
struct Keys {
|
||||
encoding: EncodingKey,
|
||||
decoding: DecodingKey,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||
pub struct Claims {
|
||||
pub sub: Uuid, // User ID
|
||||
pub exp: i64, // Expiration time
|
||||
pub role: String, // User role
|
||||
}
|
||||
|
||||
pub fn init_jwt() -> Result<(), AuthError> {
|
||||
let secret = std::env::var("JWT_SECRET")
|
||||
.map_err(|_| AuthError::ConfigError("JWT_SECRET must be set".to_string()))?;
|
||||
|
||||
KEYS.set(Keys {
|
||||
encoding: EncodingKey::from_secret(secret.as_bytes()),
|
||||
decoding: DecodingKey::from_secret(secret.as_bytes()),
|
||||
}).map_err(|_| AuthError::ConfigError("Failed to initialize JWT keys".to_string()))?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn generate_token(user_id: Uuid, role: &str) -> Result<String, AuthError> {
|
||||
let keys = KEYS.get().ok_or(AuthError::ConfigError("JWT not initialized".to_string()))?;
|
||||
|
||||
let exp = OffsetDateTime::now_utc() + Duration::hours(24);
|
||||
let claims = Claims {
|
||||
sub: user_id,
|
||||
exp: exp.unix_timestamp(),
|
||||
role: role.to_string(),
|
||||
};
|
||||
|
||||
encode(&Header::default(), &claims, &keys.encoding)
|
||||
.map_err(|e| AuthError::JwtError(e.to_string()))
|
||||
}
|
||||
|
||||
pub fn validate_token(token: &str) -> Result<Claims, AuthError> {
|
||||
let keys = KEYS.get().ok_or(AuthError::ConfigError("JWT not initialized".to_string()))?;
|
||||
|
||||
decode::<Claims>(token, &keys.decoding, &Validation::default())
|
||||
.map(|data| data.claims)
|
||||
.map_err(|e| AuthError::JwtError(e.to_string()))
|
||||
}
|
||||
22
server/src/auth/logic/middleware.rs
Normal file
22
server/src/auth/logic/middleware.rs
Normal file
@@ -0,0 +1,22 @@
|
||||
// src/auth/middleware.rs
|
||||
use tonic::{metadata::MetadataValue, service::Interceptor, Status};
|
||||
use crate::auth::{logic::jwt, models::AuthError};
|
||||
|
||||
pub struct AuthInterceptor;
|
||||
|
||||
impl Interceptor for AuthInterceptor {
|
||||
fn call(&mut self, mut request: tonic::Request<()>) -> Result<tonic::Request<()>, Status> {
|
||||
let metadata = request.metadata();
|
||||
let token = metadata.get("authorization")
|
||||
.and_then(|v| v.to_str().ok())
|
||||
.and_then(|s| s.strip_prefix("Bearer "))
|
||||
.ok_or(Status::unauthenticated("Missing authorization header"))?;
|
||||
|
||||
let claims = jwt::validate_token(token)
|
||||
.map_err(|e| Status::unauthenticated(e.to_string()))?;
|
||||
|
||||
// Store claims in request extensions
|
||||
request.extensions_mut().insert(claims);
|
||||
Ok(request)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user