Added token validation
This commit is contained in:
@@ -1 +1,2 @@
|
|||||||
pub mod jwt;
|
pub mod jwt;
|
||||||
|
pub mod validation;
|
||||||
|
|||||||
84
backend/src/cookie/validation.rs
Normal file
84
backend/src/cookie/validation.rs
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use axum::{
|
||||||
|
Json,
|
||||||
|
body::Body,
|
||||||
|
extract::State,
|
||||||
|
http::{Request, StatusCode, header},
|
||||||
|
middleware::Next,
|
||||||
|
response::IntoResponse,
|
||||||
|
};
|
||||||
|
use axum_extra::extract::CookieJar;
|
||||||
|
use jsonwebtoken::DecodingKey;
|
||||||
|
use serde_json::json;
|
||||||
|
|
||||||
|
use crate::{AppState, cookie::jwt::decode_token, models::LoginModel};
|
||||||
|
|
||||||
|
pub async fn validate_token(
|
||||||
|
cookies: CookieJar,
|
||||||
|
State(data): State<Arc<AppState>>,
|
||||||
|
mut request: Request<Body>,
|
||||||
|
next: Next,
|
||||||
|
) -> Result<impl IntoResponse, (StatusCode, Json<serde_json::Value>)> {
|
||||||
|
let token = cookies
|
||||||
|
.get("token")
|
||||||
|
.map(|cookie| cookie.value().to_string())
|
||||||
|
.or_else(|| {
|
||||||
|
request
|
||||||
|
.headers()
|
||||||
|
.get(header::AUTHORIZATION)
|
||||||
|
.and_then(|header| header.to_str().ok())
|
||||||
|
.and_then(|value| {
|
||||||
|
if value.starts_with("Bearer ") {
|
||||||
|
Some(value[7..].to_owned())
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
let token = token.ok_or_else(|| {
|
||||||
|
let error = json!({
|
||||||
|
"status": "error",
|
||||||
|
"message": "Please provide a valid token"
|
||||||
|
});
|
||||||
|
(StatusCode::UNAUTHORIZED, Json(error))
|
||||||
|
})?;
|
||||||
|
|
||||||
|
let claims = decode_token(
|
||||||
|
token,
|
||||||
|
&DecodingKey::from_secret(data.env.token_secret.as_ref()),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let uuid = (&claims.subject).parse::<i64>().map_err(|_| {
|
||||||
|
let error = json!({
|
||||||
|
"status": "error",
|
||||||
|
"message": "Invalid user id"
|
||||||
|
});
|
||||||
|
(StatusCode::UNAUTHORIZED, Json(error))
|
||||||
|
})?;
|
||||||
|
|
||||||
|
let user = sqlx::query_as::<_, LoginModel>(r#"SELECT * FROM users WHERE id = $1"#)
|
||||||
|
.bind(uuid)
|
||||||
|
.fetch_optional(&data.db)
|
||||||
|
.await
|
||||||
|
.map_err(|e| {
|
||||||
|
let error = json!({
|
||||||
|
"status": "error",
|
||||||
|
"message": format!("Database error: {}", e)
|
||||||
|
});
|
||||||
|
(StatusCode::INTERNAL_SERVER_ERROR, Json(error))
|
||||||
|
})?;
|
||||||
|
|
||||||
|
let user = user.ok_or_else(|| {
|
||||||
|
let error = json!({
|
||||||
|
"status": "error",
|
||||||
|
"message": "Invalid user"
|
||||||
|
});
|
||||||
|
(StatusCode::UNAUTHORIZED, Json(error))
|
||||||
|
})?;
|
||||||
|
|
||||||
|
request.extensions_mut().insert(user);
|
||||||
|
Ok(next.run(request).await)
|
||||||
|
}
|
||||||
@@ -64,7 +64,7 @@ pub struct LoginScheme {
|
|||||||
pub pwd: String,
|
pub pwd: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Serialize, Debug, sqlx::FromRow)]
|
#[derive(Deserialize, Serialize, Debug, Clone, sqlx::FromRow)]
|
||||||
pub struct LoginModel {
|
pub struct LoginModel {
|
||||||
pub id: i16,
|
pub id: i16,
|
||||||
pub last_name: String,
|
pub last_name: String,
|
||||||
|
|||||||
Reference in New Issue
Block a user