Improve authentication logging and error context
This commit is contained in:
@@ -47,7 +47,7 @@ pub fn gen_jwt(username: String) -> Result<String, StatusCode> {
|
|||||||
&EncodingKey::from_secret(secret.as_ref()),
|
&EncodingKey::from_secret(secret.as_ref()),
|
||||||
)
|
)
|
||||||
.map_err(|e| {
|
.map_err(|e| {
|
||||||
error!("Failed to create JWT: {}", e);
|
error!(error = %e, username = claim.username, "create jwt failed");
|
||||||
return StatusCode::INTERNAL_SERVER_ERROR;
|
return StatusCode::INTERNAL_SERVER_ERROR;
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -60,7 +60,7 @@ pub fn verify_jwt(token: String) -> Result<TokenData<AuthClaims>, StatusCode> {
|
|||||||
&Validation::default(),
|
&Validation::default(),
|
||||||
)
|
)
|
||||||
.map_err(|e| {
|
.map_err(|e| {
|
||||||
error!("Failed to verify JWT: {}", e);
|
error!(error = %e, "verify jwt failed");
|
||||||
return StatusCode::INTERNAL_SERVER_ERROR;
|
return StatusCode::INTERNAL_SERVER_ERROR;
|
||||||
});
|
});
|
||||||
result
|
result
|
||||||
|
|||||||
@@ -18,10 +18,12 @@ use crate::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
pub async fn login(state: Arc<AppState>, login_data: LoginData) -> Result<String, StatusCode> {
|
pub async fn login(state: Arc<AppState>, login_data: LoginData) -> Result<String, StatusCode> {
|
||||||
|
debug!(username = login_data.username.as_str(), "login started");
|
||||||
|
|
||||||
let user = db::user::get_by_username(&state.db_pool, &login_data.username)
|
let user = db::user::get_by_username(&state.db_pool, &login_data.username)
|
||||||
.await
|
.await
|
||||||
.map_err(|e| {
|
.map_err(|e| {
|
||||||
error!("Failed fetching user during login: {}", e);
|
error!(error = %e, username = login_data.username.as_str(), "fetch user during login failed");
|
||||||
return StatusCode::INTERNAL_SERVER_ERROR;
|
return StatusCode::INTERNAL_SERVER_ERROR;
|
||||||
})?;
|
})?;
|
||||||
let user = match user {
|
let user = match user {
|
||||||
@@ -30,7 +32,7 @@ pub async fn login(state: Arc<AppState>, login_data: LoginData) -> Result<String
|
|||||||
};
|
};
|
||||||
|
|
||||||
let verify = verify_password(&login_data.password, &user.password_hash).map_err(|e| {
|
let verify = verify_password(&login_data.password, &user.password_hash).map_err(|e| {
|
||||||
error!("Failed to verify password hash: {}", e);
|
error!(error = %e, username = login_data.username.as_str(), "verify password hash failed");
|
||||||
return StatusCode::INTERNAL_SERVER_ERROR;
|
return StatusCode::INTERNAL_SERVER_ERROR;
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
@@ -39,7 +41,7 @@ pub async fn login(state: Arc<AppState>, login_data: LoginData) -> Result<String
|
|||||||
}
|
}
|
||||||
|
|
||||||
let token = gen_jwt(user.username.clone()).map_err(|e| {
|
let token = gen_jwt(user.username.clone()).map_err(|e| {
|
||||||
error!("Failed to generate JWT: {}", e);
|
error!(error = %e, username = login_data.username.as_str(), "generate jwt failed");
|
||||||
StatusCode::INTERNAL_SERVER_ERROR
|
StatusCode::INTERNAL_SERVER_ERROR
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
|
|||||||
@@ -18,6 +18,11 @@ pub async fn auth(
|
|||||||
mut req: Request,
|
mut req: Request,
|
||||||
next: Next,
|
next: Next,
|
||||||
) -> Result<Response, StatusCode> {
|
) -> Result<Response, StatusCode> {
|
||||||
|
let request_method = req.method().clone();
|
||||||
|
let request_path = req.uri().path().to_string();
|
||||||
|
|
||||||
|
debug!(method = ?request_method, path = request_path, "authenticate request started");
|
||||||
|
|
||||||
// 1) Extract Authorization header
|
// 1) Extract Authorization header
|
||||||
let auth_header = req
|
let auth_header = req
|
||||||
.headers()
|
.headers()
|
||||||
@@ -25,7 +30,7 @@ pub async fn auth(
|
|||||||
.ok_or(StatusCode::FORBIDDEN)?; // no header at all
|
.ok_or(StatusCode::FORBIDDEN)?; // no header at all
|
||||||
|
|
||||||
let auth_header = auth_header.to_str().map_err(|e| {
|
let auth_header = auth_header.to_str().map_err(|e| {
|
||||||
error!("Failed to parse Authorization header: {}", e);
|
error!(error = %e, method = ?request_method, path = request_path, "authorization header parse failed");
|
||||||
StatusCode::FORBIDDEN
|
StatusCode::FORBIDDEN
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
@@ -35,6 +40,7 @@ pub async fn auth(
|
|||||||
(Some(scheme), Some(token)) if scheme.eq_ignore_ascii_case("bearer") => (scheme, token),
|
(Some(scheme), Some(token)) if scheme.eq_ignore_ascii_case("bearer") => (scheme, token),
|
||||||
_ => {
|
_ => {
|
||||||
// either wrong scheme or missing token
|
// either wrong scheme or missing token
|
||||||
|
warn!(method = ?request_method, path = request_path, "authorization header missing bearer token");
|
||||||
return Err(StatusCode::UNAUTHORIZED);
|
return Err(StatusCode::UNAUTHORIZED);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -47,11 +53,14 @@ pub async fn auth(
|
|||||||
let current_user = match user_routines::get_by_username(state, username)
|
let current_user = match user_routines::get_by_username(state, username)
|
||||||
.await
|
.await
|
||||||
.map_err(|e| {
|
.map_err(|e| {
|
||||||
error!("Error when fetching user via routine: {}", e);
|
error!(error = %e, method = ?request_method, path = request_path, username, "fetch user for auth failed");
|
||||||
return StatusCode::INTERNAL_SERVER_ERROR;
|
return StatusCode::INTERNAL_SERVER_ERROR;
|
||||||
})? {
|
})? {
|
||||||
Some(user) => user,
|
Some(user) => user,
|
||||||
None => return Err(StatusCode::INTERNAL_SERVER_ERROR),
|
None => {
|
||||||
|
error!(method = ?request_method, path = request_path, username, "authenticated user missing in database");
|
||||||
|
return Err(StatusCode::INTERNAL_SERVER_ERROR);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
// 5) Attach user to request extensions so handlers can grab it
|
// 5) Attach user to request extensions so handlers can grab it
|
||||||
req.extensions_mut().insert(current_user);
|
req.extensions_mut().insert(current_user);
|
||||||
|
|||||||
Reference in New Issue
Block a user