Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
eb64ae9
BB2-4250: Initial commit - sorting out how to use the flag in differe…
JamesDemeryNava Nov 21, 2025
499d00a
Ensure 403s are thrown if an application is not in the v3_early_adopt…
JamesDemeryNava Nov 21, 2025
0699b7d
Some comments, prevent v3/userinfo from returning successfully if the…
JamesDemeryNava Nov 21, 2025
423bb30
Ensure token and auth flows function or throw 403s depending on value…
JamesDemeryNava Nov 24, 2025
801d5ca
Fix some failing unit tests, add integration tests for 403s
JamesDemeryNava Nov 25, 2025
62c3d1c
Add tests around specific errors being raised for functions added to …
JamesDemeryNava Nov 25, 2025
5c35c40
Merge branch 'master' into jamesdemery/BB2-4250-v3_endpoint_app_specific
JamesDemeryNava Nov 25, 2025
916de16
Cleanup: Remove/add some TODOs
JamesDemeryNava Nov 25, 2025
ebd6c64
Merge branch 'master' into jamesdemery/BB2-4250-v3_endpoint_app_specific
JamesDemeryNava Dec 1, 2025
7657a4d
Merge branch 'master' into jamesdemery/BB2-4250-v3_endpoint_app_specific
JamesDemeryNava Dec 1, 2025
8345457
Address security concern raised by Github
JamesDemeryNava Dec 2, 2025
d89d507
Merge branch 'master' into jamesdemery/BB2-4250-v3_endpoint_app_specific
JamesDemeryNava Dec 2, 2025
0b3f054
Merge branch 'master' into jamesdemery/BB2-4250-v3_endpoint_app_specific
JamesDemeryNava Dec 3, 2025
1f83723
Merge branch 'master' into jamesdemery/BB2-4250-v3_endpoint_app_specific
JamesDemeryNava Dec 3, 2025
1e184af
Clean up and address PR feedback. Modify conditionals, throw 403 earl…
JamesDemeryNava Dec 3, 2025
ef0efae
Merge branch 'master' into jamesdemery/BB2-4250-v3_endpoint_app_specific
JamesDemeryNava Dec 3, 2025
eb306ce
Address PR feedback: Handle ObjectNotFound same as app not in flag, r…
JamesDemeryNava Dec 4, 2025
73e0cb5
Ensure a 403 is actually returned not a 500 when debug is set to false
JamesDemeryNava Dec 4, 2025
314ab24
Standardize error responses for token/auth flows - missing token erro…
JamesDemeryNava Dec 4, 2025
8b69aea
Ensure validation for v3 in tokenView only happens on refresh token
JamesDemeryNava Dec 4, 2025
1268a71
Modify comment and fix failing unit test (new error being raised)
JamesDemeryNava Dec 4, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 13 additions & 7 deletions apps/dot_ext/views/authorization.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,8 @@ class AuthorizationView(DotAuthorizationView):
# TODO: rename this so that it isn't the same as self.version (works but confusing)
# this needs to be here for urls.py as_view(version) calls, but don't use it
version = 0
# Variable to help reduce the amount of times validate_v3_authorization_request is called
validate_v3_call = True
form_class = SimpleAllowForm
login_url = "/mymedicare/login"

Expand Down Expand Up @@ -149,6 +151,11 @@ def dispatch(self, request, *args, **kwargs):
initially create an AuthFlowUuid object for authorization
flow tracing in logs.
"""
path_info = self.request.__dict__.get('path_info')
version = get_api_version_number_from_url(path_info)
# If it is not version 3, we don't need to check anything, just return
if version == Versions.V3 and self.validate_v3_call:
self.validate_v3_authorization_request()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In testing with a running local server with the flag created but without any apps enabled, I ended up with a generic 500 server error when issuing the authorize request. Seems like maybe in this path we need to add some kind of exception handling?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm assuming this was a v3 auth flow, do you know what the Everyone setting was? Had to be No or Unknown, but just want to confirm. Have not been able to reproduce the generic 500 error on the authorize request yet. I also set the superusers setting to False here, though I don't think that would have any bearing.

# TODO: Should the client_id match a valid application here before continuing, instead of after matching to FHIR_ID?
if not kwargs.get('is_subclass_approvalview', False):
# Create new authorization flow trace UUID in session and AuthFlowUuid instance, if subclass is not ApprovalView
Expand Down Expand Up @@ -241,7 +248,11 @@ def validate_v3_authorization_request(self):
try:
application = get_application_model().objects.get(client_id=client_id[0])
application_user = get_user_model().objects.get(id=application.user_id)
if flag.id is not None and flag.is_active_for_user(application_user):

if flag.id is None or flag.is_active_for_user(application_user):
# Update the class variable to ensure subsequent calls to dispatch don't call this function
# more times than is needed
self.validate_v3_call = False
return
else:
raise AccessDeniedTokenCustomError(
Expand Down Expand Up @@ -292,11 +303,6 @@ def form_valid(self, form):
refresh_token_delete_cnt = 0

try:
path_info = self.request.__dict__.get('path_info')
version = get_api_version_number_from_url(path_info)
# If it is not version 3, we don't need to check anything, just return
if version == Versions.V3:
self.validate_v3_authorization_request()

if not scopes:
# Since the create_authorization_response will re-inject scopes even when none are
Expand Down Expand Up @@ -456,7 +462,7 @@ def validate_v3_token_call(self, request) -> None:
application = get_application_model().objects.get(id=refresh_token.application_id)
application_user = get_user_model().objects.get(id=application.user_id)

if flag.id is not None and flag.is_active_for_user(application_user):
if flag.id is None or flag.is_active_for_user(application_user):
return
else:
raise PermissionDenied(
Expand Down
2 changes: 1 addition & 1 deletion apps/fhir/bluebutton/permissions.py
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ def has_permission(self, request, view):
application_user = get_user_model().objects.get(id=application.user_id)
flag = get_waffle_flag_model().get('v3_early_adopter')

if flag.id is not None and flag.is_active_for_user(application_user):
if flag.id is None or flag.is_active_for_user(application_user):
return True
else:
raise PermissionDenied(
Expand Down
1 change: 1 addition & 0 deletions apps/fhir/bluebutton/tests/test_wellknown_endpoints.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ def setUp(self):

@skipIf((not settings.RUN_ONLINE_TESTS), 'Can\'t reach external sites.')
@override_switch('v3_endpoints', active=True)
@override_flag('v3_early_adopter', active=False)
def test_userinfo_returns_403(self):
first_access_token = self.create_token('John', 'Smith', fhir_id_v2=FHIR_ID_V2)
ac = AccessToken.objects.get(token=first_access_token)
Expand Down
2 changes: 1 addition & 1 deletion apps/wellknown/permissions.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ def has_permission(self, request, view):
application_user = get_user_model().objects.get(id=application.user_id)
flag = get_waffle_flag_model().get('v3_early_adopter')

if flag.id is not None and flag.is_active_for_user(application_user):
if flag.id is None or flag.is_active_for_user(application_user):
return True
else:
raise PermissionDenied(
Expand Down
Loading