Skip to content

Commit 0759e29

Browse files
authored
BB2-4144: Updated error handling for BFD errors during auth flow (#1381)
* Updated error handling for BFD errors during auth flow * Remove early return (was for testing purposes) * Fix tests * Fix test (for real this time)
1 parent cc945bc commit 0759e29

File tree

4 files changed

+38
-24
lines changed

4 files changed

+38
-24
lines changed

apps/fhir/server/authentication.py

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,8 @@ def search_fhir_id_by_identifier(search_identifier, request=None):
103103
if err_detail is not None:
104104
raise UpstreamServerException(err_detail)
105105
return fhir_id
106+
except requests.exceptions.HTTPError as e:
107+
raise UpstreamServerException(e)
106108
except requests.exceptions.SSLError as e:
107109
if retries < max_retries and (env is None or env == 'DEV'):
108110
# Checking target_env ensures the retry logic only happens on local
@@ -146,22 +148,23 @@ def match_fhir_id(mbi, mbi_hash, hicn_hash, request=None):
146148
return fhir_id, "M"
147149

148150
# Perform secondary lookup using HICN_HASH
149-
try:
150-
fhir_id = search_fhir_id_by_identifier_hicn_hash(hicn_hash, request)
151-
except UpstreamServerException as err:
152-
log_match_fhir_id(request, None, mbi_hash, hicn_hash, False, "H", str(err))
153-
# Don't return a 404 because retrying later will not fix this.
154-
raise UpstreamServerException(err.detail)
155-
156-
if fhir_id:
157-
# Found beneficiary!
158-
log_match_fhir_id(request, fhir_id, mbi_hash, hicn_hash, True, "H",
159-
"FOUND beneficiary via hicn_hash")
160-
return fhir_id, "H"
161-
else:
162-
log_match_fhir_id(request, fhir_id, mbi_hash, hicn_hash, False, None,
163-
"FHIR ID NOT FOUND for both mbi_hash and hicn_hash")
164-
raise exceptions.NotFound("The requested Beneficiary has no entry, however this may change")
151+
if hicn_hash:
152+
try:
153+
fhir_id = search_fhir_id_by_identifier_hicn_hash(hicn_hash, request)
154+
except UpstreamServerException as err:
155+
log_match_fhir_id(request, None, mbi_hash, hicn_hash, False, "H", str(err))
156+
# Don't return a 404 because retrying later will not fix this.
157+
raise UpstreamServerException(err.detail)
158+
159+
if fhir_id:
160+
# Found beneficiary!
161+
log_match_fhir_id(request, fhir_id, mbi_hash, hicn_hash, True, "H",
162+
"FOUND beneficiary via hicn_hash")
163+
return fhir_id, "H"
164+
165+
log_match_fhir_id(request, fhir_id, mbi_hash, hicn_hash, False, None,
166+
"FHIR ID NOT FOUND for both mbi_hash and hicn_hash")
167+
raise exceptions.NotFound("The requested Beneficiary has no entry, however this may change")
165168

166169

167170
def _validate_patient_search_result(bundle_of_patients):

apps/fhir/server/tests/test_authentication.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
from django.test import RequestFactory
44
from django.test.client import Client
55
from httmock import HTTMock, urlmatch
6-
from requests.exceptions import HTTPError
76
from rest_framework import exceptions
87

98
from apps.fhir.bluebutton.exceptions import UpstreamServerException
@@ -111,7 +110,7 @@ def test_match_fhir_id_server_hicn_error(self):
111110
Expecting: HTTPError exception raised
112111
'''
113112
with HTTMock(self.create_fhir_mock(self.ERROR_KEY, self.NOT_FOUND_KEY)):
114-
with self.assertRaises(HTTPError):
113+
with self.assertRaises(UpstreamServerException):
115114
fhir_id, hash_lookup_type = match_fhir_id(
116115
mbi=self.test_mbi,
117116
mbi_hash=self.test_mbi_hash,
@@ -124,7 +123,7 @@ def test_match_fhir_id_server_mbi_error(self):
124123
Expecting: HTTPError exception raised
125124
'''
126125
with HTTMock(self.create_fhir_mock(self.NOT_FOUND_KEY, self.ERROR_KEY)):
127-
with self.assertRaises(HTTPError):
126+
with self.assertRaises(UpstreamServerException):
128127
fhir_id, hash_lookup_type = match_fhir_id(
129128
mbi=self.test_mbi,
130129
mbi_hash=self.test_mbi_hash,

apps/mymedicare_cb/models.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ class BBMyMedicareCallbackCrosswalkUpdateException(APIException):
2323
status_code = status.HTTP_500_INTERNAL_SERVER_ERROR
2424

2525

26-
def get_and_update_user(slsx_client: OAuth2ConfigSLSx, request=None):
26+
def get_and_update_user(slsx_client: OAuth2ConfigSLSx, request=None, version=2):
2727
"""
2828
Find or create the user associated
2929
with the identity information from the ID provider.
@@ -53,10 +53,15 @@ def get_and_update_user(slsx_client: OAuth2ConfigSLSx, request=None):
5353
logger = logging.getLogger(logging.AUDIT_AUTHN_MED_CALLBACK_LOGGER, request)
5454

5555
# Match a patient identifier via the backend FHIR server
56+
if version == 3:
57+
hicn_hash = None
58+
else:
59+
hicn_hash = slsx_client.hicn_hash
60+
5661
fhir_id, hash_lookup_type = match_fhir_id(
5762
mbi=slsx_client.mbi,
5863
mbi_hash=slsx_client.mbi_hash,
59-
hicn_hash=slsx_client.hicn_hash, request=request
64+
hicn_hash=hicn_hash, request=request
6065
)
6166

6267
log_dict = {

apps/mymedicare_cb/views.py

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,15 @@
2222
from apps.dot_ext.models import Approval
2323
from apps.mymedicare_cb.models import (BBMyMedicareCallbackCrosswalkCreateException,
2424
BBMyMedicareCallbackCrosswalkUpdateException)
25+
from apps.fhir.bluebutton.exceptions import UpstreamServerException
2526
from .authorization import (OAuth2ConfigSLSx,
2627
MedicareCallbackExceptionType,
2728
BBMyMedicareCallbackAuthenticateSlsUserInfoValidateException)
2829
from .models import AnonUserState, get_and_update_user
2930

3031

3132
# For SLSx auth workflow info, see apps/mymedicare_db/README.md
32-
def authenticate(request):
33+
def authenticate(request, version=2):
3334
# Update authorization flow from previously stored state in AuthFlowUuid instance in mymedicare_login().
3435
request_state = request.GET.get('relay')
3536

@@ -63,7 +64,7 @@ def authenticate(request):
6364
slsx_client.log_event(request, {})
6465

6566
# Find or create the user associated with the identity information from SLS.
66-
user, crosswalk_action = get_and_update_user(slsx_client, request=request)
67+
user, crosswalk_action = get_and_update_user(slsx_client, request=request, version=version)
6768

6869
# Set crosswalk_action and get auth flow session values.
6970
set_session_auth_flow_trace_value(request, 'auth_crosswalk_action', crosswalk_action)
@@ -105,7 +106,7 @@ def callback(request, version=2):
105106

106107
user_not_found_error = None
107108
try:
108-
authenticate(request)
109+
authenticate(request, version=version)
109110
except ValidationError as e:
110111
return JsonResponse({
111112
"error": e.message,
@@ -125,6 +126,12 @@ def callback(request, version=2):
125126
return JsonResponse({
126127
"error": e.detail,
127128
}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
129+
except UpstreamServerException:
130+
# Return more generic message to users to prevent oversharing information
131+
# Full error details will be available in logs from match_fhir_id
132+
return JsonResponse({
133+
"error": "Failed to retrieve data from data source."
134+
}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
128135

129136
scheme, netloc, path, query_string, fragment = urlsplit(next_uri)
130137

0 commit comments

Comments
 (0)