36 lines
1.1 KiB
Rust
36 lines
1.1 KiB
Rust
|
|
use axum::{
|
||
|
|
extract::FromRequestParts,
|
||
|
|
http::{request::Parts, StatusCode},
|
||
|
|
};
|
||
|
|
use axum::async_trait;
|
||
|
|
|
||
|
|
pub struct RequireAuth(pub crate::jwt::Claims);
|
||
|
|
|
||
|
|
#[async_trait]
|
||
|
|
impl<S> FromRequestParts<S> for RequireAuth
|
||
|
|
where
|
||
|
|
S: Send + Sync,
|
||
|
|
{
|
||
|
|
type Rejection = (StatusCode, &'static str);
|
||
|
|
|
||
|
|
async fn from_request_parts(parts: &mut Parts, _state: &S) -> Result<Self, Self::Rejection> {
|
||
|
|
let auth_header = parts
|
||
|
|
.headers
|
||
|
|
.get("Authorization")
|
||
|
|
.and_then(|value| value.to_str().ok())
|
||
|
|
.filter(|value| value.starts_with("Bearer "));
|
||
|
|
|
||
|
|
let token = match auth_header {
|
||
|
|
Some(header) => header.trim_start_matches("Bearer "),
|
||
|
|
None => return Err((StatusCode::UNAUTHORIZED, "Missing Bearer token")),
|
||
|
|
};
|
||
|
|
|
||
|
|
let jwt_secret = std::env::var("JWT_SECRET").expect("JWT_SECRET must be set");
|
||
|
|
|
||
|
|
match crate::jwt::verify_access_token(token, &jwt_secret) {
|
||
|
|
Ok(claims) => Ok(RequireAuth(claims)),
|
||
|
|
Err(_) => Err((StatusCode::UNAUTHORIZED, "Invalid or expired token")),
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|