ragb/backend/src/authorization.rs
sinavir 899fe7f45c chore(backend): Refactor a bit authorization
Use a middleware for cof membership checking
2024-10-12 17:37:11 +02:00

77 lines
2.2 KiB
Rust

use crate::model::DB;
use axum::{
extract::{Request, State},
http::StatusCode,
middleware::Next,
response::Response,
};
use axum_extra::{headers, typed_header::TypedHeader};
use jsonwebtoken::{decode, Algorithm, DecodingKey, Validation};
use serde::{Deserialize, Serialize};
#[derive(Debug, Serialize, Deserialize)]
struct Claims {
sub: String,
scope: String,
user: String,
is_cof: bool,
}
#[derive(Eq, PartialEq, Hash, Debug, Serialize, Deserialize, Clone)]
pub struct User {
name: String,
pub is_cof: bool,
}
fn check_token(token: &str, jwt: &str) -> Option<User> {
let decoded_token = decode::<Claims>(
&token,
&DecodingKey::from_secret(jwt.as_bytes()),
&Validation::new(Algorithm::HS256),
);
match decoded_token {
Ok(token_data) => {
let user = token_data.claims.user;
let is_cof =token_data.claims.is_cof;
if token_data.claims.scope == "modify" {
tracing::info!("Successful auth {user:?}");
Some(User { name: user, is_cof })
} else {
tracing::debug!("Failed auth: {user:?} don't have modify scope");
None
}
}
Err(err) => {tracing::debug!("Failed decoding token: {err:?}"); None},
}
}
pub async fn jwt_middleware(
State(state): State<DB>,
TypedHeader(auth): TypedHeader<headers::Authorization<headers::authorization::Bearer>>,
mut request: Request,
next: Next,
) -> Result<Response, StatusCode> {
let token = auth.token();
if let Some(user) = check_token(token, &state.static_state.jwt_key) {
request.extensions_mut().insert(user);
Ok(next.run(request).await)
} else {
Err(StatusCode::FORBIDDEN)
}
}
pub async fn jwt_middleware_cof(
State(state): State<DB>,
TypedHeader(auth): TypedHeader<headers::Authorization<headers::authorization::Bearer>>,
mut request: Request,
next: Next,
) -> Result<Response, StatusCode> {
let token = auth.token();
if let Some(user) = check_token(token, &state.static_state.jwt_key) {
if user.is_cof {
request.extensions_mut().insert(user);
return Ok(next.run(request).await)
};
};
Err(StatusCode::FORBIDDEN)
}