auth middleware + message history

This commit is contained in:
2025-06-08 21:29:06 +02:00
parent 4f03cde9b5
commit 368ae7209c
12 changed files with 888 additions and 57 deletions

View File

@@ -1,15 +1,22 @@
use std::sync::LazyLock;
use axum::{extract::State, http::StatusCode};
use axum::{
extract::{Request, State},
http::StatusCode,
middleware::Next,
response::Response,
};
use chrono::Utc;
use jsonwebtoken::{Algorithm, DecodingKey, EncodingKey, Header, Validation, decode, encode};
use serde::{Deserialize, Serialize};
use sqlx::{FromRow, Postgres};
use crate::state::AppState;
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Claims {
pub user_id: u32,
pub user_id: i64,
pub iat: usize,
pub exp: usize,
}
@@ -29,7 +36,7 @@ pub static AUTH_PUBLIC_KEY: LazyLock<DecodingKey> = LazyLock::new(|| {
});
impl Claims {
pub fn new(user_id: u32) -> Self {
pub fn new(user_id: i64) -> Self {
let now = (Utc::now().timestamp_millis() / 1000) as usize;
Self {
user_id,
@@ -40,16 +47,26 @@ impl Claims {
}
}
#[derive(Debug, Clone, FromRow)]
pub struct User {
id: i64,
}
pub async fn get_auth_token(State(state): State<AppState>) -> Result<String, StatusCode> {
let mut next_client_id = state.next_client_id.lock().await;
let claims = Claims::new(*next_client_id);
let Ok(user) = sqlx::query_as::<Postgres, User>("INSERT INTO users DEFAULT VALUES RETURNING *")
.fetch_one(&state.pg_pool)
.await
else {
return Err(StatusCode::INTERNAL_SERVER_ERROR);
};
*next_client_id += 1;
let claims = Claims::new(user.id);
encode(&Header::new(Algorithm::RS512), &claims, &AUTH_SECRET_KEY).map_err(|e| {
dbg!(&e);
StatusCode::INTERNAL_SERVER_ERROR
})
let Ok(token) = encode(&Header::new(Algorithm::RS512), &claims, &AUTH_SECRET_KEY) else {
return Err(StatusCode::INTERNAL_SERVER_ERROR);
};
Ok(token)
}
pub fn verify_token(token: &str) -> Option<Claims> {
@@ -57,9 +74,34 @@ pub fn verify_token(token: &str) -> Option<Claims> {
decode::<Claims>(token, key, &Validation::new(Algorithm::RS512))
.map(|token_data| token_data.claims)
.map_err(|e| {
println!("{e:?}");
e
})
.ok()
}
const AUTH_HEADER_PREFIX: &'static str = "Bearer ";
pub async fn authentication_middleware(
mut request: Request,
next: Next,
) -> Result<Response, StatusCode> {
let Some(Ok(auth_header)) = request
.headers()
.get(axum::http::header::AUTHORIZATION)
.map(|header| header.to_str())
else {
return Err(StatusCode::UNAUTHORIZED);
};
if auth_header.len() <= AUTH_HEADER_PREFIX.len() {
return Err(StatusCode::UNAUTHORIZED);
}
let token = auth_header.split_at(AUTH_HEADER_PREFIX.len()).1;
let Some(claims) = verify_token(token) else {
return Err(StatusCode::UNAUTHORIZED);
};
request.extensions_mut().insert(claims);
return Ok(next.run(request).await);
}