Skip to content

Commit 3eb12c6

Browse files
authored
Merge pull request #160 from refactor-group/122-fe-bug-unsuccessful-login-returns-500
Make sure that failed login attempts are returned as 401 Unauthorized.
2 parents 5c543fd + 0a648e7 commit 3eb12c6

File tree

3 files changed

+42
-5
lines changed

3 files changed

+42
-5
lines changed

domain/src/error.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ pub enum InternalErrorKind {
4040
pub enum EntityErrorKind {
4141
NotFound,
4242
Invalid,
43+
Unauthenticated,
4344
DbTransaction,
4445
Other(String),
4546
}
@@ -71,6 +72,7 @@ impl From<EntityApiError> for Error {
7172
let entity_error_kind = match err.error_kind {
7273
EntityApiErrorKind::RecordNotFound => EntityErrorKind::NotFound,
7374
EntityApiErrorKind::InvalidQueryTerm => EntityErrorKind::Invalid,
75+
EntityApiErrorKind::RecordUnauthenticated => EntityErrorKind::Unauthenticated,
7476
_ => EntityErrorKind::Other("EntityErrorKind".to_string()),
7577
};
7678

web/src/controller/user_session_controller.rs

Lines changed: 33 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use crate::controller::ApiResponse;
2+
use crate::error::{Error as WebError, Result as WebResult};
23
use axum::{http::StatusCode, response::IntoResponse, Form, Json};
34
use domain::user::{AuthSession, Credentials};
45
use log::*;
@@ -36,17 +37,44 @@ pub struct NextUrl {
3637
pub async fn login(
3738
mut auth_session: AuthSession,
3839
Form(creds): Form<Credentials>,
39-
) -> impl IntoResponse {
40+
) -> WebResult<impl IntoResponse> {
4041
debug!("UserSessionController::login()");
4142

4243
let user = match auth_session.authenticate(creds.clone()).await {
4344
Ok(Some(user)) => user,
44-
Ok(None) => return Err(StatusCode::UNAUTHORIZED.into_response()),
45-
Err(_) => return Err(StatusCode::INTERNAL_SERVER_ERROR.into_response()),
45+
Ok(None) => {
46+
// No user found - this should also be treated as an authentication error
47+
return Err(WebError::from(domain::error::Error {
48+
source: None,
49+
error_kind: domain::error::DomainErrorKind::Internal(
50+
domain::error::InternalErrorKind::Entity(
51+
domain::error::EntityErrorKind::Unauthenticated,
52+
),
53+
),
54+
}));
55+
}
56+
Err(auth_error) => {
57+
// axum_login errors contain our entity_api::Error in the error field
58+
warn!("Authentication failed: {:?}", auth_error);
59+
return Err(WebError::from(domain::error::Error {
60+
source: Some(Box::new(auth_error)),
61+
error_kind: domain::error::DomainErrorKind::Internal(
62+
domain::error::InternalErrorKind::Entity(
63+
domain::error::EntityErrorKind::Unauthenticated,
64+
),
65+
),
66+
}));
67+
}
4668
};
4769

48-
if auth_session.login(&user).await.is_err() {
49-
return Err(StatusCode::INTERNAL_SERVER_ERROR.into_response());
70+
if let Err(login_error) = auth_session.login(&user).await {
71+
warn!("Session login failed: {:?}", login_error);
72+
return Err(WebError::from(domain::error::Error {
73+
source: Some(Box::new(login_error)),
74+
error_kind: domain::error::DomainErrorKind::Internal(
75+
domain::error::InternalErrorKind::Other("Session login failed".to_string()),
76+
),
77+
}));
5078
}
5179

5280
let user_session_json = json!({

web/src/error.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,13 @@ impl Error {
8888
);
8989
(StatusCode::NOT_FOUND, "NOT FOUND").into_response()
9090
}
91+
EntityErrorKind::Unauthenticated => {
92+
warn!(
93+
"EntityErrorKind::Unauthenticated: Responding with 401 Unauthorized. Error: {:?}",
94+
self
95+
);
96+
(StatusCode::UNAUTHORIZED, "UNAUTHORIZED").into_response()
97+
}
9198
EntityErrorKind::DbTransaction => {
9299
warn!(
93100
"EntityErrorKind::DbTransaction: Responding with 500 Internal Server Error. Error: {:?}",

0 commit comments

Comments
 (0)