-
Notifications
You must be signed in to change notification settings - Fork 3.9k
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
feat: Add JwtAuthentication as a default DRF auth class. #32802
Conversation
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.
Thanks. Some thoughts...
Also, there is |
@robrap yea, this is indeed blocked on the forgiving JWT auth, because without it we will have auth failures where the JWT is not provided. It took going through this exercise to see that unfortunately, sorry for the ping. Without the JWTAuthentication class behaving like DRF expects, it's hard to move forward on this so I'm gonna focus back on that. |
UPDATED: when the JWT is not provided, it should just move on to the next authentication class. If an invalid JWT is provided, it would fail and not try any other means. Did you actually see this cause a problem, and if so, can you explain where? Note that the JWT Cookie doesn’t become a single cookie (it starts as two) unless the special header is supplied which only the MFEs supply. |
Still digging further but |
What’s interesting is that for a logged out user (from the name of the test), a 401 seems more correct, right? We should still probably understand why this is changing the response. |
@feanil: What I discovered is that with or without this change, we are getting When including Even the forgiving JWT cookie code won't fix this. We'll need to discuss. |
@feanil: More thoughts on my previous comment.
|
@feanil: Here is my updated plan:
|
@robrap this seems fine to me but what setting are you changing? |
@feanil: I am adding the following as
I will back them out once they are tested and we land the defaults in edx-platform in this PR. Does that make sense? |
Gotcha, sounds good to me. |
[request] @feanil:
|
99dce18
to
bbd3e63
Compare
Done, added as a new commit.
This is not needed because Reference: https://github.com/openedx/edx-platform/blob/master/cms/envs/common.py#L73 |
@feanil: Looks like there are more failures, but hopefully they are all for 403 => 401. |
@robrap looks like they are, I'll keep stomping at them, until this is green. |
96debf3
to
6e9b271
Compare
@feanil: Mostly copied from Slack so it doesn't get lost. Are you planning on following up on this?
|
6e9b271
to
2eedb40
Compare
dafe868
to
b5cccf9
Compare
I'm keeping this as a Draft until I land my testing. I'm hoping it won't be long. |
@feanil: I am copying this info from elsewhere. I also added some notes from edx.org monitoring which help me feel more confident that this is unlikely to cause problems. Consider adding a backward incompatible note to the commit comment and using See potential comments: BREAKING CHANGE: For any affected endpoint that also required the user to be authenticated, the endpoint will now return a 401 in place of a 403 when the user is not authenticated.
Generally speaking, this is should not be a problem.
Note: On edx.org, the only endpoints using the default authentication classes that also had 403 responses were the following:
|
be6adb8
to
653d44d
Compare
@feanil: I just discovered we will possibly be breaking docstrings as well. Here is one example of a docstring for NotificationCountView that would need to be updated. Based on monitoring, I've found 37 views that will be affected by this change:
|
Good point, thanks for realizing and running the query, I'm on PTO for the rest of this week but I'll update all those docstrings when I'm back next week. We should consider this PR blocked until that update is made. |
@feanil: The likely situation is that this PR will be blocked until I've rolled out forgiving JWTs and this change as overrides in edx.org. By that time, I imagine this PR will be ready to remove from Draft and merge. |
653d44d
to
93cc859
Compare
@robrap I took a closer look at this and I don't think the docstrings need to change. Though there is a behavioral change. Because we set JWT Auth to be first in the list. If the user uses JWT auth to hit the endpoints, they'll get the correct behavior of 403 for permission denied and 401 for when they have failed to auth. But if they hit the endpoint with a session id cookie, to hit the same endpoint, they'll get a 401 now while they used to get a 403. This is a change in behavior so we should make sure there are no adverse effects when you roll this out but in terms of docstrings, they are always going to be right/wrong depending on which auth type we're using. In my opinion, this seems like a shortcoming of DRF(I feel like it should be able to understand if you succeeded in authenticating independently from running into permission issues but it dosen't do that at the moment.) I think the best course of action is to leave the docs as is because they convey the correct behavior for APIs using JWT auth which is what we're moving towards. |
@feanil: It is indeed complicated.
I am asking some teams to make error handling updates to respond to 401 or 403, which will be more resilient to this. Based on all of our findings, it seems the docs should really state "401 or 403", and not just 403, so people know how to appropriately handle errors. Thoughts? |
So in all of my testing I was using valid tokens to actually check the permission issue, it sounds like there was a historic confusing issue where we used to say 403 for bad credentials which we no longer do and that could cause issues? |
@feanil: I think we agreed offline that:
Thus, there is nothing left to do except wait on my deployments and testing and I'll let you know when we are ready for this. Does that sound right? |
@robrap that sounds right to me. Do you want to leave this PR in draft till then in-case we find there are more changes to make? |
@feanil: Yes. Let's leave it in draft. I hope there will be no more issues, but this will ensure I complete testing this change in Prod on edx.org before we merge this. |
a2e1921
to
efefe80
Compare
By default DRF sets 'DEFAULT_AUTHENTICATION_CLASSES' to: ``` [ 'rest_framework.authentication.SessionAuthentication', 'rest_framework.authentication.BasicAuthentication' ] ``` We also want to allow for JWT Authentication as a valid default auth choice. This will allow users to send JWT tokens in the authorization header to any existing API endpoints and access them. If any APIs have set custom authentication classes, this will not override that. I believe this is a fairly safe change to make since it only adds one authentication class and does not impact authorization of any of the endpoints that might be affected. Note: This change changes the default for both the LMS and CMS because `cms/envs/common.py` imports this value from the LMS. BREAKING CHANGE: For any affected endpoint that also required the user to be authenticated, the endpoint will now return a 401 in place of a 403 when the user is not authenticated. - See [these DRF docs](https://github.com/encode/django-rest-framework/blob/master/docs/api-guide/authentication.md#unauthorized-and-forbidden-responses) for a deeper explanation about why this changes. - Here is [an example endpoint](https://github.com/openedx/edx-platform/blob/b8ecfed67dc0520b8c4d95de3096b35acc083611/openedx/core/djangoapps/embargo/views.py#L20-L21) that does not override defaults and checks for IsAuthenticated. Generally speaking, this is should not be a problem. An issue would appear only if the caller of the endpoint is specifically handling 403s in a way that would be missed for 401s.
When including `JwtAuthentication`, the auth_header becomes `JWT realm="api"`. Without it, it is `None`. This changes the behavior of the code in DRF and returns a slightly different auth response. Relevant Code: https://github.com/encode/django-rest-framework/blob/56946fac8f29aa44ce84391f138d63c4c8a2a285/rest_framework/views.py#L456C3-L456C3
efefe80
to
ac2cc15
Compare
2U Release Notice: This PR has been deployed to the edX staging environment in preparation for a release to production. |
2U Release Notice: This PR has been deployed to the edX production environment. |
By default DRF sets 'DEFAULT_AUTHENTICATION_CLASSES' to:
We also want to allow for JWT Authentication as a valid default auth
choice. This will allow users to send JWT tokens in the authorization
header to any existing API endpoints and access them. If any APIs have
set custom authentication classes, this will not override that.
I believe this is a fairly safe change to make since it only adds one
authentication class and does not impact authorization of any of the
endpoints that might be affected.