-
Notifications
You must be signed in to change notification settings - Fork 31
BB2-4961: Switch Account Link #1649
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
base: master
Are you sure you want to change the base?
Changes from all commits
a177e8b
56d508a
7ddfe0c
0b95685
28c5fc3
37d6f30
5aae555
c75dba4
d32f5df
c3a96cc
c118c3b
c42fc29
6a5b091
517ee74
fb67242
2bcf1ad
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,2 +1,10 @@ | ||
| from .application import ApplicationRegistration, ApplicationUpdate, ApplicationDelete # NOQA | ||
| from .authorization import AuthorizationView, ApprovalView, TokenView, RevokeTokenView, RevokeView, IntrospectTokenView # NOQA | ||
| from .authorization import ( # NOQA | ||
| AuthorizationView, | ||
| ApprovalView, | ||
| TokenView, | ||
| RevokeTokenView, | ||
| RevokeView, | ||
| IntrospectTokenView, | ||
| PermissionScreenLogoutView, | ||
| ) |
|
JamesDemeryNava marked this conversation as resolved.
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -9,22 +9,24 @@ | |
| from functools import wraps | ||
| from http import HTTPStatus | ||
| from typing import Any | ||
| from urllib.parse import parse_qs, urlparse | ||
| from urllib.parse import parse_qs, urlencode, urlparse | ||
|
|
||
| import jwt | ||
| import waffle | ||
| from django.conf import settings | ||
| from django.contrib.auth import get_user_model | ||
| from django.contrib.auth import get_user_model, logout | ||
| from django.contrib.auth.models import User | ||
| from django.contrib.auth.views import redirect_to_login | ||
| from django.core.cache import cache | ||
| from django.core.exceptions import ObjectDoesNotExist | ||
| from django.db.models import Q | ||
| from django.http import HttpRequest, JsonResponse | ||
| from django.http.response import HttpResponse, HttpResponseBadRequest | ||
| from django.shortcuts import redirect | ||
| from django.template.response import TemplateResponse | ||
| from django.urls import reverse | ||
| from django.utils.decorators import method_decorator | ||
| from django.views import View | ||
| from django.views.decorators.csrf import csrf_exempt | ||
| from django.views.decorators.debug import sensitive_post_parameters | ||
| from fhir.resources.R4B.address import Address | ||
|
|
@@ -69,6 +71,7 @@ | |
| AUDIT_EVENT_SEARCH_SCOPE, | ||
| CLIENT_CREDENTIALS, | ||
| CLIENT_CREDENTIALS_ACCEPTED_JWT_ALGORITHMS, | ||
| CODE_CHALLENGE_METHOD_S256, | ||
| HHS_SERVER_LOGNAME_FMT, | ||
| OPENID_SCOPE, | ||
| REFRESH_TOKEN, | ||
|
|
@@ -110,6 +113,7 @@ | |
| check_auth_tracking_and_create_access_token_extension, | ||
| check_can_token_scope_for_audit_event_scopes, | ||
| get_api_version_number_from_url, | ||
| get_oauth_param, | ||
| json_response_from_oauth2_error, | ||
| remove_application_user_pair_tokens_data_access, | ||
| validate_app_is_active, | ||
|
|
@@ -267,6 +271,19 @@ def get_context_data(self, **kwargs): | |
| context['permission_end_date_text'] = self.application.access_end_date_text() | ||
| context['permission_end_date'] = self.application.access_end_date() | ||
|
|
||
| params = [ | ||
| 'client_id', | ||
| 'redirect_uri', | ||
| 'response_type', | ||
| 'scope', | ||
| 'state', | ||
| 'code_challenge', | ||
| 'code_challenge_method', | ||
| ] | ||
| oauth_params = {} | ||
| for param in params: | ||
| oauth_params[param] = self.request.GET.get(param) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Would this work if the request method was POST? |
||
| self.request.session['oauth_params'] = oauth_params | ||
| if 'form' in context and self.version == Versions.V3: | ||
| # By setting this to matching_scopes instead of application_scopes, we ensure that the scopes | ||
| # for the access token are in the intersection of what the application is allowed to have and | ||
|
|
@@ -1138,6 +1155,7 @@ def _retrieve_prior_include_samhsa_and_part_d_eob_only_values( | |
| def post(self, request: HttpRequest, *args, **kwargs) -> HttpResponse: | ||
| version = get_api_version_number_from_url(self.request.path_info) | ||
| grant_type = request.POST.get('grant_type') | ||
|
|
||
| try: | ||
| # If it is not version 3, we don't need to check that the application is in the v3_early_adopter flag, | ||
| # just continue with standard validation. | ||
|
|
@@ -1431,3 +1449,47 @@ def post(self, request, *args, **kwargs): | |
| return json_response_from_oauth2_error(error) | ||
|
|
||
| return super(IntrospectTokenView, self).post(request, args, kwargs) | ||
|
|
||
|
|
||
| class PermissionScreenLogoutView(View): | ||
| def post(self, request, *args, **kwargs): | ||
| # Save version before logout clears the session | ||
| version = request.session.get('version', None) | ||
|
|
||
| # Save the original OAuth params before logout | ||
| oauth_params = { | ||
| 'client_id': get_oauth_param(request, 'client_id', 'auth_client_id'), | ||
| 'redirect_uri': get_oauth_param(request, 'redirect_uri'), | ||
| 'response_type': get_oauth_param(request, 'response_type'), | ||
| 'state': get_oauth_param(request, 'state'), | ||
| 'code_challenge_method': CODE_CHALLENGE_METHOD_S256, | ||
| 'code_challenge': request.session.get('oauth_params', {}).get('code_challenge'), | ||
| 'scope': request.session.get('oauth_params', {}).get('scope'), | ||
| 'code_verifier': request.session.get('code_verifier'), | ||
|
JamesDemeryNava marked this conversation as resolved.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Great catch. It doesn't come through on Postman auth requests (similar to our actual apps), but it does in testclient. So that is why it's included here, so the testclient switch account flow works. I'll leave a comment to explain that.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think it should be set in the session, but not placed in the authorize url parameters later on.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is there a change you are suggesting? I didn't add it to the authorize url parameters, just making it so it is retrievable after switch account is clicked for testclient.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It goes into the url parameters in line 1493 right? |
||
| } | ||
|
|
||
| # Remove None values | ||
| oauth_params = {k: v for k, v in oauth_params.items() if v is not None} | ||
|
|
||
| # Clear token and log out | ||
| request.session.pop('token', None) | ||
| logout(request) | ||
|
|
||
| # this is to avoid a corrupted session warning - though I am still seeing that warning | ||
|
JamesDemeryNava marked this conversation as resolved.
|
||
| request.session.cycle_key() | ||
|
|
||
| # Restore version after logout | ||
| if version is not None: | ||
| request.session['version'] = version | ||
|
|
||
| if 'testclient' in oauth_params.get('redirect_uri', ''): | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. (come back to this too) |
||
| # this is the key that the testclient looks for | ||
| request.session['api_ver'] = version | ||
| request.session['code_verifier'] = oauth_params.get('code_verifier') | ||
|
JamesDemeryNava marked this conversation as resolved.
|
||
| request.session['client_id'] = oauth_params.get('client_id') | ||
|
|
||
| # Rebuild the authorize URL with original params | ||
| base_url = request.build_absolute_uri('/').rstrip('/') | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. (come back to this too) |
||
| authorize_url = f'{base_url}/v3/o/authorize?{urlencode(oauth_params)}' | ||
|
|
||
| return redirect(authorize_url) | ||
|
github-advanced-security[bot] marked this conversation as resolved.
Fixed
|
||
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.
Should this handle POST too?
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 looked at Splunk and I swore we were only getting GET requests on authorize endpoints, which is why I wrote it as so. Looking now, I do see some POST requests, so i'll add handling for that as a backup.