-
-
Notifications
You must be signed in to change notification settings - Fork 8.5k
🐛 Use 401 status code in security classes when credentials are missing
#13786
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
🐛 Use 401 status code in security classes when credentials are missing
#13786
Conversation
401 status code in security classes when credentials missed401 status code in security classes when credentials are missing
|
Thank you for opening this @YuriiMotov - we've just been surprised by an API reporting 403 for a missing token when we we'd be expecting to see 401 and trigger a login flow on the client side. We'd be glad to have this this fix merged. 🙏 (fwiw, I agree with the decision to follow other implementations and return 401 not 400) |
|
Any progress? |
|
We have been also noticing this and are waiting for a fix for a long time. |
|
I ran into this too when using schemathesis testing a route protected by |
cleder
left a comment
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.
The if self.not_authenticated_status_code == HTTP_403_FORBIDDEN: checks look a bit clunky, but given this is of a temporary nature it is probably fine
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
…o create the exception to be raised
… refactored into subclassing
…ame type of error for invalid authentication
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.
Awesome, thank you @YuriiMotov! 🙌
And thank you for all the investigation and notes with all the research. 🤓 ☕
I made the following updates:
- Simplify the
WWW-Authenticatechallenge for API key, as this is a custom challenge we are defining, I didn't want to also define custom parameters, but leave the simplest form. - Refactor the implementation to not have an extra parameter for defining the status code, instead, put the creation of the error in a method of the class, this way if someone wants to use the old behavior, they can create a subclass and override only that method.
- Refactor the HTTP classes to all return the same message for errors (
"Not authenticated"), instead of some times returning"Invalid authentication credentials", this simplifies the code a bit, and in particular makes it simpler to explain to users how to use the old behavior. - Simplify and refactor a bit the implementation.
- Add new docs for how to use the old behavior by subclassing, with new source examples and tests for them.
- Add notes and warnings about stub classes, as you suggested.
I also noted that the spec says that the realm is now optional, but only in a footer note (https://datatracker.ietf.org/doc/html/rfc7235#appendix-A). 😂 Anyway, we are good with that now.
This will be available in FastAPI 0.122.0, released in the next few hours. 🎉
📝 Docs previewLast commit 61d703e at: https://f4ebcc3e.fastapitiangolo.pages.dev Modified Pages |
* Sync with #14217 * Sync with #14359 * Sync with #13786 * Sync with #14070 * Sync with #14120 * Sync with #14211 * Sync with #14405 * "to deploy" -> "deployen" The LLM used that translation a lot ithis convinced me that "deployen" it is the better word. "bereitstellen" (or "ausliefern") is still used for "to serve". --------- Co-authored-by: Motov Yurii <[email protected]> Co-authored-by: Yurii Motov <[email protected]>
Warning
This description is partially outdated after changes described in this comment.
Description
This PR is an attempt to finally solve the issue with security tools returning error responses with status code
403instead of401when credentials are not provided.Breaking changes and workaround
These changes can break projects that rely on old behavior.
In order to mitigate this, the
not_authenticated_status_codeis introduced. If set to403, it will make it work the same way as it was before changes (return403status code).This option should be treated as a temporary workaround to give developers more time to update Clients to follow the new behavior.
Changes and reasoning
APIKeyQuery, APIKeyHeader, APIKeyCookie
not_authenticated_status_codeparameter can be used to revert this behavior back to returning 403 error code without sendingWWW-Authenticate.WWW-Authenticateinformation needed to understand how the key is supposed to be passed. I implemented default format (WWW-Authenticate: ApiKey in="...", name="..."), but it’s possible to override the template forWWW-Authenticateby subclassing and defining theformat_www_authenticate_header_valuemethodHTTP Basic
WWW-Authenticateheader on a lack of credentialsrealmis required according to the RFC, but optional in the current implementation. Fixing this would introduce breaking changes. Considering this is not a problem for people who want to follow the standard, I suggest we leave it as it is.HTTP Digest
WWW-Authenticateis just a stub for now (justWWW-Authenticate: Digest) (see notes)not_authenticated_status_codeparameter can be used to revert this behavior back to returning 403 error code without sendingWWW-Authenticate.HTTPDigestimplementation is just a stub, we can’t follow standards (we don’t generatenonce's, don’t haverealm, …). I suggest we just change the error status code and add a stub forWWW-Authenticate(justWWW-Authenticate: Digest). For nowHTTPDigestcan’t be used as it is, so, this is not a problem.Digestscheme. There have been made several attempts to implement it (Update HTTPDigest to match RFC 7616 #9825, 🔒 Match HTTP Digest specs from RFC 7616 #3071)HTTPDigestis just a stub?HTTP Bearer, OAuth2 schemes, OIDC
OAuth2PasswordBearerandOAuth2AuthorizationCodeBearer: not needed.HTTPBearerandOpenIdConnect:OAuth2PasswordBearerandOAuth2AuthorizationCodeBearer.not_authenticated_status_codeparameter added toHTTPBearercan be used to revert this behavior back to returning 403 error code without sendingWWW-Authenticate.WWW-Authenticateis not clearly described: It’s said that the value "Bearer" MUST be followed by one or more auth-param values. At the same time, all auth-param attributes are optional. In examples they always addrealm. Since we don’t haverealm, I suggest we just skip it and send justWWW-Authenticate: BearerWWW-Authenticateformat by addingrealmandscopeLinks