-
Notifications
You must be signed in to change notification settings - Fork 16
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
fix: use forgiving jwt authentication #197
fix: use forgiving jwt authentication #197
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.
Notes for my future self or future reviewers. Also see "Author Concerns" of the PR description.
Closing this draft PR with comments for ARCHBOM-1218 until the ticket is picked up again. |
Re-opening this because I think it's still relevant once we update it a bit. I'll take a stab at re-basing it off of the latest main branch. |
1de9346
to
bcab347
Compare
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.
Just a few comments from a more thorough review, next I'm gonna try to get this going locally and see what the test coverage looks like.
35f3baf
to
b567e94
Compare
@feanil: What's your plan for this? |
@robrap I had to backburner this a bit to get some other work around documentation moving. I think I'll be able to finish that up this week and then I can come back to this next week. |
The idea behind this work is to use "forgiving" jwt authentication when working with JWT cookies, which means that if jwt cookie authentication fails, we would try other authentication mechanisms, rather than failing and halting the authentication attempt. This solution would replace an earlier solution to issues around jwt cookies that introduced an HTTP_USE_JWT_COOKIE header. For more background and details, see the new ADR: 0002-remove-use-jwt-cookie-header.rst. Also contains: * add custom attributes `jwt_auth_has_jwt_cookie` for debugging. * ENABLE_FORGIVING_JWT_COOKIES toggle for rollout of what would be a future breaking change, when we have fully switched to forgiving jwt cookies. ARCHBOM-1218
By default it will be off so the release should be safe to push out and then we can enable as needed to test the new code paths.
We now set multiple attribuets as a part of authentication so change how we validate our mock calls.
02a6bd9
to
88f7879
Compare
Run all the existing tests with both forgiving and original JWT Auth behaviors. Only one test needed to be modified. Previously we were raising an exception when CSRF checks failed within the authentication process but with forgiving auth, we no longer rais an exception so we update the one test to handle both cases for now. This will get cleaned when we hopefully move forward with only having the forgiving JWT auth flow in the future.
This test was missing an assert to ensure that authentication succeeded. However when we add the assert, I learned that the test was failing because the Authorization header was not being submitted correctly into the initial request. I updated the test so that it would pass as expected.
88f7879
to
65919e4
Compare
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 @feanil. I'm going to discuss monitoring with someone on my team late tomorrow, and will come back with a proposal around that. In the meantime, I've noted other things.
Also, when done, please check the Conversations tab to ensure you caught all the comments. Some of my comments are not new, but just pings on old comments. Thanks!
edx_rest_framework_extensions/auth/jwt/tests/test_middleware.py
Outdated
Show resolved
Hide resolved
Co-authored-by: Robert Raposa <[email protected]>
Co-authored-by: Robert Raposa <[email protected]>
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.
@feanil: Confirming that I will be updating the refactor PR and fixing some of the monitoring there, and then we can merge back in to this PR and finish any remaining issues here.
This initial refactor recombines the original and forgiving versions of process_view, and tries to keep as close to the original as possible. Changes to original include: - reconstitute cookie if is_forgiving_jwt_cookies_enabled - move setting request user to the bottom of the method - for forgiving cookies, user is set if jwt cookie is found
Monitoring shows that missing JWT cookies is already a common case, and will be even more common once this is enabled. Therefore, there is no reason to log this as a warning, nor even to log it at all.
- Add new custom attribute use_jwt_cookie_requested - Remove custom attribute request_jwt_cookie Notes: - request_jwt_cookie had a confusing name - the new temporary attribute use_jwt_cookie_requested provides more specific help for the overall removal of this header. - the new attribute jwt_auth_has_jwt_cookie (separate commit) can be used instead to determine if we reconstituted.
Simplify middleware code for reconstituting cookies by simply returning early if USE_JWT_COOKIE_HEADER is not supplied, and we haven't yet enabled ENABLE_FORGIVING_JWT_COOKIES. To accomplish this, one minor change was made that should be fine, but it does affect the USE_JWT_COOKIE_HEADER case. Rather than setting request user for all scenarios where USE_JWT_COOKIE_HEADER is supplied, including when there is no JWT cookie, we only set the request user if the JWT cookie has been reconstituted.
Updates docs for request_auth_type_guess custom attribute using annotations.
Updates docs for jwt_auth_failed custom attribute using annotations.
Made the following custom attribute changes: * replace jwt_auth_has_jwt_cookie (was in JwtAuthentication) with new has_jwt_cookie in JwtAuthCookieMiddleware * refactor and rename jwt_auth_forgiving_jwt_cookies to is_forgiving_jwt_cookies_enabled * annotate is_forgiving_jwt_cookies_enabled * add and annotate jwt_auth_failure_forgiven
Combine _authenticate_original and _authenticate_forgiving_jwt_cookies into one method. Note: The refactor makes a change to the original, where we now use check to see if there is JWT cookie, rather than checking if the USE_JWT_COOKIE header exists, to determine whether to check for CSRF protection.
Configure test settings to enable more complete JwtAuthetication testing with JWT cookies. Note: A new test_authenticate_with_correct_jwt_cookie will be added in a separate commit because it relies on other changes.
* Add jwt_auth_result with various values for the different possible outcomes of JwtAuthentication. * Remove jwt_auth_failure_forgiven custom attribute, which was replaced by jwt_auth_result value 'forgiven-failure'. Configure test settings to enable more complete JwtAuthetication testing with JWT cookies. Note: A new test_authenticate_with_correct_jwt_cookie will be added in a separate commit because it relies on other changes.
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.
@timmc-edx @feanil: You may want to review the Aug 8th and Aug 10th commits by commit.
Here is a summary of changes:
- docs: update annotations for request_auth_type_guess
- docs: add annotations for jwt_auth_failed
- fixup! forgiving jwt custom attribute updates
- replace jwt_auth_has_jwt_cookie (was in JwtAuthentication) with new has_jwt_cookie in JwtAuthCookieMiddleware
- refactor and rename jwt_auth_forgiving_jwt_cookies to is_forgiving_jwt_cookies_enabled
- annotate is_forgiving_jwt_cookies_enabled
- add and annotate jwt_auth_failure_forgiven
- Note: This is replaced by jwt_auth_result in a future commit.
- fixup! refactor JwtAuthentication authenticate (combined orginal and forgiving_jwt_cookies)
- Note: this was another refactor like the one from the separate PR
- feat: enable JWT cookie testing
- adds a test setting used in a follow-up commit
- fixup! switch to jwt_auth_result custom attribute
- replaces jwt_auth_failure_forgiven
UPDATE: Also added a changelog entry and bumped the version.
# Not using JWT cookies, CSRF validation not required | ||
use_jwt_cookie_requested = request.META.get(USE_JWT_COOKIE_HEADER) | ||
if not use_jwt_cookie_requested: | ||
return user_and_auth |
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.
Note to reviewer: The refactor makes a change to this original code (not seen in the changed code) where
we now check to see if there is JWT cookie, rather than checking if the USE_JWT_COOKIE
header exists, to determine whether to check for CSRF protection.
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.
One question, otherwise looks good to me.
@@ -142,9 +139,15 @@ def _authenticate_forgiving_jwt_cookies(self, request): | |||
# .. custom_attribute_description: Includes a summary of the JWT failure exception | |||
# for debugging. | |||
set_custom_attribute('jwt_auth_failed', 'Exception:{}'.format(repr(exception))) | |||
# .. custom_attribute_name: jwt_auth_failure_forgiven | |||
# .. custom_attribute_description: This attribute will be True if the JWT failure | |||
# is forgiven. Only JWT cookie failures will be forgiven. In the case of a |
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.
What's Only JWT cookie failures will be forgiven.
meant to communicate? It suggests that maybe JWT auth where you use a JWT Authorization header is not forgiven? Is that right?
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.
@feanil: You are correct. Also, this comment went away when this attribute was removed in favor of jwt_auth_result, so there is no doc updates needed.
@feanil @timmc-edx: [inform] I just added a changelog entry as well. |
Description:
The idea behind this work is to use "forgiving" jwt authentication
when working with JWT cookies, which means that if jwt cookie
authentication fails, we would try other authentication mechanisms,
rather than failing and halting the authentication attempt.
This solution would replace an earlier solution to issues around
jwt cookies that introduced an HTTP_USE_JWT_COOKIE header.
For more background and details, see the new ADR:
0002-remove-use-jwt-cookie-header.rst.
Also contains:
be a future breaking change, when we have fully switched to
forgiving jwt cookies.
JIRA:
Author concerns:
Reviewers:
Merge checklist:
Post merge:
finished.