deploy change, update token system, fix abuses and add admin verify
This commit is contained in:
@@ -1,4 +1,6 @@
|
||||
use crate::{api::ApiState, error::AppError};
|
||||
use axum::http::header::SET_COOKIE;
|
||||
use axum::http::HeaderMap;
|
||||
use axum::response::IntoResponse;
|
||||
use axum::{extract::State, routing::post, Json, Router};
|
||||
use serde::Deserialize;
|
||||
@@ -56,6 +58,13 @@ async fn auth_telegram_api(
|
||||
.auth_service
|
||||
.generate_auth_token(user.id, user.tg_id, &state.jwt_secret)?;
|
||||
|
||||
let mut headers = HeaderMap::new();
|
||||
let cookie = format!(
|
||||
"nrxp_token={}; HttpOnly; Secure; SameSite=Strict; Path=/; Max-Age=600",
|
||||
token
|
||||
);
|
||||
headers.insert(SET_COOKIE, cookie.parse().unwrap());
|
||||
|
||||
Ok(Json(json!({ "status": "success", "token": token })))
|
||||
}
|
||||
|
||||
|
||||
@@ -16,23 +16,32 @@ pub async fn auth_guard(
|
||||
let auth_header = req
|
||||
.headers()
|
||||
.get("Authorization")
|
||||
.and_then(|h| h.to_str().ok())
|
||||
.filter(|h| h.starts_with("Bearer "))
|
||||
.map(|h| &h[7..])
|
||||
.ok_or_else(|| AppError::Unauthorized("Access token required".into()))?;
|
||||
.and_then(|h| h.to_str().ok());
|
||||
|
||||
// 1. Получаем чистый токен (String)
|
||||
let token = if let Some(h) = auth_header {
|
||||
h.replace("Bearer ", "")
|
||||
} else {
|
||||
req.headers()
|
||||
.get("Cookie")
|
||||
.and_then(|c| c.to_str().ok())
|
||||
.and_then(|c| c.split("; ").find(|part| part.starts_with("nrxp_token=")))
|
||||
.map(|part| part.replace("nrxp_token=", ""))
|
||||
.ok_or_else(|| AppError::Unauthorized("Access token required".into()))?
|
||||
};
|
||||
|
||||
// 2. Декодируем токен, используя полученную выше переменную `token`
|
||||
// Передаем ссылку &token, так как jsonwebtoken ожидает &str
|
||||
let token_data = jsonwebtoken::decode::<super::service::Claims>(
|
||||
auth_header,
|
||||
&token,
|
||||
&jsonwebtoken::DecodingKey::from_secret(state.jwt_secret.as_bytes()),
|
||||
&jsonwebtoken::Validation::default(),
|
||||
)
|
||||
.map_err(|_| AppError::Unauthorized("Invalid session signature".into()))?;
|
||||
|
||||
// Парсим внутренний UUID из поля sub токена
|
||||
let user_id = uuid::Uuid::parse_str(&token_data.claims.sub)
|
||||
.map_err(|_| AppError::Unauthorized("Invalid token payload structure".into()))?;
|
||||
|
||||
// Ищем оперативника в сети по его системному UUID
|
||||
let user = state
|
||||
.repo
|
||||
.get_user_by_id(user_id)
|
||||
@@ -51,7 +60,8 @@ pub async fn admin_guard(req: Request, next: Next) -> Result<Response, AppError>
|
||||
.get::<User>()
|
||||
.ok_or_else(|| AppError::Unauthorized("Context lost: Auth required".into()))?;
|
||||
|
||||
if user.role != "admin" {
|
||||
let admin_id: i64 = std::env::var("ADMIN_TG_ID").unwrap().parse().unwrap();
|
||||
if user.tg_id == Some(admin_id) || user.role == "admin" {
|
||||
warn!(
|
||||
"SECURITY_ALERT: Unauthorized admin access attempt by @{:?}",
|
||||
user.tg_username
|
||||
|
||||
@@ -41,7 +41,8 @@ impl AuthService {
|
||||
let claims = Claims {
|
||||
sub: user_id.to_string(),
|
||||
tg_id,
|
||||
exp: (Utc::now() + chrono::Duration::hours(24)).timestamp() as usize,
|
||||
// Время жизни токена сокращено до 10 минут
|
||||
exp: (Utc::now() + chrono::Duration::minutes(10)).timestamp() as usize,
|
||||
};
|
||||
|
||||
encode(
|
||||
|
||||
Reference in New Issue
Block a user