-
-
Notifications
You must be signed in to change notification settings - Fork 216
Auth error handling with status codes #841
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Auth error handling with status codes #841
Conversation
bin/core/src/auth/mod.rs
Outdated
| auth_jwt_get_user_id(jwt) | ||
| .await | ||
| .context("failed to authenticate jwt") | ||
| .map_err(|e| e.status_code(StatusCode::UNAUTHORIZED)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can .status_code() directly after .context()
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, I didn't think so, sure
bin/core/src/auth/mod.rs
Outdated
| auth_api_key_get_user_id(key, secret) | ||
| .await | ||
| .context("failed to authenticate api key") | ||
| .map_err(|e| e.status_code(StatusCode::UNAUTHORIZED)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same here
bin/core/src/auth/mod.rs
Outdated
| serror::Error::from( | ||
| anyhow!("user not enabled") | ||
| .status_code(StatusCode::FORBIDDEN) | ||
| ) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This one is not consistent with the rest
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll adjust the others too so that it's consistent. I just left them as they were at first because the adjustment caused errors in the websocket file.
|
I hope this version is what you had in mind. I kept the low-level functions with their original 'anyhow::Result' signatures and logic unchanged. Only the high-level functions now consistently use 'serror::Result' with proper HTTP status codes. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this PR is necessary. It already does return UNAUTHORIZED for all failures to auth from fn auth_request
|
I do see that GetUser returns 500. This should be one line change though, add status code unauthorized to call in GetUser, there is unnecessary changes here. |
|
Okay then I'll refractor my PR to the following to fix the bug. I thought that I can also improve the behavior when no impl Resolve<AuthArgs> for GetUser {
#[instrument(name = "GetUser", level = "debug", skip(self))]
async fn resolve(
self,
AuthArgs { headers }: &AuthArgs,
) -> serror::Result<User> {
let user_id = get_user_id_from_headers(headers)
.await
.status_code(StatusCode::UNAUTHORIZED)?;
Ok(get_user(&user_id).await?)
}
} |
| let user_id = get_user_id_from_headers(headers) | ||
| .await | ||
| .status_code(StatusCode::UNAUTHORIZED)?; | ||
| Ok(get_user(&user_id).await?) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| Ok(get_user(&user_id).await?) | |
| get_user(&user_id).await.status_code(StatusCode::UNAUTHORIZED) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Re-check, this is on get_user. Currently it will 500 if it can't find user at id.
|
I think unauthorized is fine in all these cases, there is still the message with the reason. 400 in particular already being used specifically for invalid json or other invalid body on otherwise authenticated request and shouldn't be mixed into auth related errors. |
|
I didn't expect that. From a developer's perspective, I agree with you that 401 and/or the error message clearly indicate what the actual problem is. But when I look at it from a security perspective, the potential attack vector could be minimised if we don't describe the actual problem in too much detail and return more details about the status code. I had that in mind when I was working on this PR. PR is ready |
|
Not sure what you are referring to re attack vectors or security, don't see how status code is relevant there. |
I don't think this is a major issue currently, but it does provide the opportunity for username enumeration attacks. The principle I'm referring to is Information Disclosure - where different error messages reveal system internals to potential attackers. Current examples in the codebase: The security concern: An attacker can systematically test credentials and learn about valid users/keys based on different error responses. My suggested solution: Environment-based error handling - detailed errors in development, generic "Authentication failed" in production. This maintains developer experience while preventing information leakage in production environments. With this explanation, I would like to conclude the PR at this point. |
This is reasonable, just has more to do with the message than status code. It could be handled in another focused PR with intention to remove some of it. There's still the one issue with this PR re #841 (comment) |
|
Anyways, that's just an addition, this PR looks fine and will add the other part in follow up commit, thanks |
* Refactor authentication error handling to use serror::Result and status codes * Refactor error messages * Refactor authentication error handling to include status codes and improve error messages * clean up * clean * fmt
* start 1.19.4 * deploy 1.19.4-dev-1 * try smaller binaries with cargo strip * deploy 1.19.4-dev-2 * smaller binaries with cargo strip * Fix Submit Dialog Button Behavior with 500 Errors on Duplicate Names (#819) * Implement enhanced error handling and messaging for resource creation * Implement improved error handling for resource creation across alerter, build, and sync * Implement error handling improvements for resource copying and validation feedback * Adjust error handling for resource creation to distinguish validation errors from unexpected system errors * Refactor resource creation error handling by removing redundant match statements and simplifying the error propagation in multiple API modules. * fmt * bump indexmap * fix account selector showing empty when account no longer found * clean up theme logic, ensure monaco and others get up to date current theme * enforce disable_non_admin_create for tags. Clean up status code responses * update server cache concurrency controller * deploy 1.19.4-dev-3 * Allow signing in by pressing enter (#830) * Improve dialog overflow handling to prevent clipping of content (#828) * Add Email notification entry to community.md (#824) * Add clickable file path to show/hide file contents in StackInfo (#827) * add clickable file path to show/hide file contents in StackInfo Also added CopyButton due to the new functionality making the file path not selectable. * Move clicking interaction to CardHeader * Avoid sync edge cases of having toggle show function capturing showContents from outside Co-authored-by: Maxwell Becker <[email protected]> * Format previous change * Add `default_show_contents` to `handleToggleShow` --------- Co-authored-by: Maxwell Becker <[email protected]> * deploy 1.19.4-dev-4 * avoid stake info ShowHideButton double toggle * Allow multiple simultaneous Action runs for use with Args * deploy 1.19.4-dev-5 * feat: persist all table sorting states including unsorted (#832) - Always save sorting state to localStorage, even when empty/unsorted - Fixes issue where 'unsorted' state was not persisted across page reloads - Ensures consistent and predictable sorting behavior for all DataTable components * autofocus on login username field (#837) * Fix unnecessary auth queries flooding console on login page (#842) * Refactor authentication error handling to use serror::Result and status codes * Enable user query only when JWT is present * Enable query execution in useRead only if JWT is present * Revert backend auth changes - keep PR focused on frontend only * Fix unnecessary API queries to unreachable servers flooding console (#843) * Implement server availability checks in various components * Refactor server availability check to ensure only healthy servers are identified * cargo fmt * fmt * Auth error handling with status codes (#841) * Refactor authentication error handling to use serror::Result and status codes * Refactor error messages * Refactor authentication error handling to include status codes and improve error messages * clean up * clean * fmt * invalid user id also UNAUTHORIZED * deploy 1.19.4-dev-6 * deploy 1.19.4-dev-7 --------- Co-authored-by: Marcel Pfennig <[email protected]> Co-authored-by: jack <[email protected]> Co-authored-by: Guten <[email protected]> Co-authored-by: Paulo Roberto Albuquerque <[email protected]> Co-authored-by: Lorenzo Farnararo <[email protected]>


Problem:
The current error handling in authentication is not optimal, as it always returns HTTP status code 500, regardless of whether no credentials were found in the header, the credentials are incorrect, or the user exists but is disabled. This prevents the client from distinguishing why authentication failed.
I noticed this problem in the browser console when navigating to the login page. Resources are being queried in the background even though we are not logged in. This would certainly be worth its own issue, but I will fix the problem piece by piece in smaller PRs.
Solution:
Similar to PR #819, I have adjusted the error handling to use different HTTP status codes and provide clearer information to the user about why authentication failed.
401 UNAUTHORIZED