def validate_user_signout(self, request):
        """
        Performs a call to userinfo_endpoint to validate that the bene is
        signed out. When NOT signed out, an exception is thrown.
        This assumes the bene is signed out, if the userinfo endpoint returns
        a HTTP_403_FORBIDDEN respose and the auth_token is no longer valid.
        """
        headers = self.slsx_common_headers(request)
        headers.update(self.auth_header())

        auth_flow_dict = get_session_auth_flow_trace(request)

        response = requests.get(self.userinfo_endpoint + "/" + self.user_id,
                                headers=headers,
                                allow_redirects=False,
                                verify=self.verify_ssl_internal,
                                hooks={
                                    'response': [
                                        response_hook_wrapper(
                                            sender=SLSxUserInfoResponse,
                                            auth_flow_dict=auth_flow_dict)
                                    ]
                                })
        self.validate_signout_status_code = response.status_code

        if self.validate_signout_status_code != status.HTTP_403_FORBIDDEN:
            log_authenticate_start(
                auth_flow_dict,
                "FAIL",
                "SLSx validate signout response_code = {code}."
                " Expecting HTTP_403_FORBIDDEN.".format(
                    code=self.validate_signout_status_code),
                slsx_client=self)
            raise BBMyMedicareSLSxValidateSignoutException(
                settings.MEDICARE_ERROR_MSG)
Beispiel #2
0
def handle_token_created(sender, request, token, **kwargs):
    # Get auth flow dict from session for logging
    auth_flow_dict = get_session_auth_flow_trace(request)

    token_logger.info(
        get_event(
            Token(token, action="authorized", auth_flow_dict=auth_flow_dict)))
    def user_signout(self, request):
        """
        This uses the SLSx signout endpoint to sign out the bene.
        After it does the signout, the response is a redirect to the
        Medicare.gov signout page. Since this is more of a browser type
        functionality, we disable the redirects in the HTTP GET call.
        NOTE: This enpoint always returns a 302---even if the signout
              did not work.
        """
        headers = self.slsx_common_headers(request)
        headers.update(self.auth_header())

        auth_flow_dict = get_session_auth_flow_trace(request)

        response = requests.get(self.signout_endpoint,
                                headers=headers,
                                allow_redirects=False,
                                verify=self.verify_ssl_external)
        self.signout_status_code = response.status_code
        response.raise_for_status()

        if self.signout_status_code != status.HTTP_302_FOUND:
            log_authenticate_start(auth_flow_dict,
                                   "FAIL",
                                   "SLSx signout response_code = {code}."
                                   " Expecting HTTP_302_FOUND.".format(
                                       code=self.signout_status_code),
                                   slsx_client=self)
            raise BBMyMedicareSLSxSignoutException(settings.MEDICARE_ERROR_MSG)
    def exchange_for_access_token(self, req_token, request):
        """
        Exchanges the request_token from the slsx -> medicare.gov
        login flow for an auth_token via the slsx token endpoint.
        """
        data_dict = {
            "request_token": req_token,
            "client_id": self.client_id,
            "client_secret": self.client_secret,
        }

        headers = self.slsx_common_headers(request)

        auth_flow_dict = get_session_auth_flow_trace(request)

        response = requests.post(self.token_endpoint,
                                 auth=self.basic_auth(),
                                 json=data_dict,
                                 headers=headers,
                                 allow_redirects=False,
                                 verify=self.verify_ssl_external,
                                 hooks={
                                     'response': [
                                         response_hook_wrapper(
                                             sender=SLSxTokenResponse,
                                             auth_flow_dict=auth_flow_dict)
                                     ]
                                 })
        self.token_status_code = response.status_code
        response.raise_for_status()

        token_response = response.json()

        self.auth_token = token_response.get('auth_token', None)
        if self.auth_token is None:
            log_authenticate_start(
                auth_flow_dict,
                "FAIL",
                "Exchange auth_token is missing in response error",
                slsx_client=self)
            raise BBMyMedicareSLSxTokenException(settings.MEDICARE_ERROR_MSG)

        self.user_id = token_response.get('user_id', None)
        if self.user_id is None:
            log_authenticate_start(
                auth_flow_dict,
                "FAIL",
                "Exchange user_id is missing in response error",
                slsx_client=self)
            raise BBMyMedicareSLSxTokenException(settings.MEDICARE_ERROR_MSG)

        if self.user_id is None:
            log_authenticate_start(
                auth_flow_dict,
                "FAIL",
                "Exchange user_id is missing in response error",
                slsx_client=self)
            raise BBMyMedicareSLSxTokenException(settings.MEDICARE_ERROR_MSG)
def match_fhir_id(mbi_hash, hicn_hash, request=None):
    """
      Matches a patient identifier via the backend FHIR server
      using an MBI or HICN hash.

      Summary:
        - Perform primary lookup using mbi_hash.
        - If there is an mbi_hash lookup issue, raise exception.
        - Perform secondary lookup using HICN_HASH
        - If there is a hicn_hash lookup issue, raise exception.
        - A NotFound exception is raised, if no match was found.
      Returns:
        fhir_id = Matched patient identifier.
        hash_lookup_type = The type used for the successful lookup (M or H).
      Raises exceptions:
        UpstreamServerException: If hicn_hash or mbi_hash search found duplicates.
        NotFound: If both searches did not match a fhir_id.
    """
    # Get auth flow session values.
    auth_flow_dict = get_session_auth_flow_trace(request)

    # Perform primary lookup using MBI_HASH
    if mbi_hash:
        try:
            fhir_id = search_fhir_id_by_identifier_mbi_hash(mbi_hash, request)
        except UpstreamServerException as err:
            log_match_fhir_id(auth_flow_dict, None, mbi_hash, hicn_hash, False,
                              "M", str(err))
            # Don't return a 404 because retrying later will not fix this.
            raise UpstreamServerException(str(err))

        if fhir_id:
            # Found beneficiary!
            log_match_fhir_id(auth_flow_dict, fhir_id, mbi_hash, hicn_hash,
                              True, "M", "FOUND beneficiary via mbi_hash")
            return fhir_id, "M"

    # Perform secondary lookup using HICN_HASH
    try:
        fhir_id = search_fhir_id_by_identifier_hicn_hash(hicn_hash, request)
    except UpstreamServerException as err:
        log_match_fhir_id(auth_flow_dict, None, mbi_hash, hicn_hash, False,
                          "H", str(err))
        # Don't return a 404 because retrying later will not fix this.
        raise UpstreamServerException(str(err))

    if fhir_id:
        # Found beneficiary!
        log_match_fhir_id(auth_flow_dict, fhir_id, mbi_hash, hicn_hash, True,
                          "H", "FOUND beneficiary via hicn_hash")
        return fhir_id, "H"
    else:
        log_match_fhir_id(auth_flow_dict, fhir_id, mbi_hash, hicn_hash, False,
                          None,
                          "FHIR ID NOT FOUND for both mbi_hash and hicn_hash")
        raise exceptions.NotFound(
            "The requested Beneficiary has no entry, however this may change")
    def get_user_info(self, request):
        """
        Retrieves and returns bene information containing MBI/HICN values
        from the userinfo endpoint.
        """
        headers = self.slsx_common_headers(request)
        headers.update(self.auth_header())

        auth_flow_dict = get_session_auth_flow_trace(request)

        response = requests.get(self.userinfo_endpoint + "/" + self.user_id,
                                headers=headers,
                                allow_redirects=False,
                                verify=self.verify_ssl_internal,
                                hooks={
                                    'response': [
                                        response_hook_wrapper(
                                            sender=SLSxUserInfoResponse,
                                            auth_flow_dict=auth_flow_dict)
                                    ]
                                })
        self.userinfo_status_code = response.status_code
        response.raise_for_status()

        # Get data.user part of response
        try:
            data_user_response = response.json().get('data').get('user')
        except KeyError:
            log_authenticate_start(
                auth_flow_dict,
                "FAIL",
                "SLSx userinfo issue with data.user sub fields in response error",
                slsx_client=self)
            raise BBMyMedicareSLSxUserinfoException(
                settings.MEDICARE_ERROR_MSG)

        if data_user_response.get('id', None) is None:
            log_authenticate_start(
                auth_flow_dict,
                "FAIL",
                "SLSx userinfo user_id is missing in response error",
                slsx_client=self)
            raise BBMyMedicareSLSxUserinfoException(
                settings.MEDICARE_ERROR_MSG)

        if self.user_id != data_user_response.get('id', None):
            log_authenticate_start(
                auth_flow_dict,
                "FAIL",
                "SLSx userinfo user_id is not equal in response error",
                slsx_client=self)
            raise BBMyMedicareSLSxUserinfoException(
                settings.MEDICARE_ERROR_MSG)

        return data_user_response
Beispiel #7
0
def handle_app_authorized(sender, request, auth_status, auth_status_code, user,
                          application, share_demographic_scopes, scopes, allow,
                          access_token_delete_cnt, refresh_token_delete_cnt,
                          data_access_grant_delete_cnt, **kwargs):

    # Get auth flow dict from session for logging
    auth_flow_dict = get_session_auth_flow_trace(request)

    log_dict = {
        "type": "Authorization",
        "auth_status": auth_status,
        "auth_status_code": auth_status_code,
        "user": {
            "id": user.id,
            "username": user.username,
            "crosswalk": {
                "id": user.crosswalk.id,
                "user_hicn_hash": user.crosswalk.user_hicn_hash,
                "user_mbi_hash": user.crosswalk.user_mbi_hash,
                "fhir_id": user.crosswalk.fhir_id,
                "user_id_type": user.crosswalk.user_id_type,
            },
        },
        "application": {
            "id": application.id,
            "name": application.name,
        },
        "share_demographic_scopes": share_demographic_scopes,
        "scopes": scopes,
        "allow": allow,
        "access_token_delete_cnt": access_token_delete_cnt,
        "refresh_token_delete_cnt": access_token_delete_cnt,
        "data_access_grant_delete_cnt": data_access_grant_delete_cnt,
    }

    # Update with auth flow session info
    if auth_flow_dict:
        log_dict.update(auth_flow_dict)

    if settings.LOG_JSON_FORMAT_PRETTY:
        token_logger.info(get_event(json.dumps(log_dict, indent=2)))
    else:
        token_logger.info(get_event(json.dumps(log_dict)))
Beispiel #8
0
def authenticate(request):
    # Update authorization flow from previously stored state in AuthFlowUuid instance in mymedicare_login().
    request_state = request.GET.get('relay')

    clear_session_auth_flow_trace(request)
    update_session_auth_flow_trace_from_state(request, request_state)

    # Get auth flow session values.
    auth_flow_dict = get_session_auth_flow_trace(request)

    # SLSx client instance
    slsx_client = OAuth2ConfigSLSx()

    request_token = request.GET.get('req_token', None)
    if request_token is None:
        log_authenticate_start(auth_flow_dict, "FAIL",
                               "SLSx request_token is missing in callback error.", slsx_client=slsx_client)
        raise ValidationError(settings.MEDICARE_ERROR_MSG)

    # Exchange req_token for access token
    slsx_client.exchange_for_access_token(request_token, request)

    # Get user_info
    user_info = slsx_client.get_user_info(request)

    # Signout bene to prevent SSO issues per BB2-544
    slsx_client.user_signout(request)

    # Validate bene is signed out per BB2-544
    slsx_client.validate_user_signout(request)

    # Set identity values from userinfo response.
    sls_subject = slsx_client.user_id.strip()
    sls_hicn = user_info.get("hicn", "").strip()
    #     Convert SLS's mbi to UPPER case.
    sls_mbi = user_info.get("mbi", "").strip().upper()
    sls_first_name = user_info.get('firstName', "")
    if sls_first_name is None:
        sls_first_name = ""
    sls_last_name = user_info.get('lastName', "")
    if sls_last_name is None:
        sls_last_name = ""
    sls_email = user_info.get('email', "")
    if sls_email is None:
        sls_email = ""

    # If MBI returned from SLSx is blank, set to None for hash logging
    if sls_mbi == "":
        sls_mbi = None

    # Validate: sls_subject cannot be empty. TODO: Validate format too.
    if sls_subject == "":
        err_msg = "User info sub cannot be empty"
        log_authenticate_start(auth_flow_dict, "FAIL", err_msg, slsx_client=slsx_client)
        raise BBMyMedicareCallbackAuthenticateSlsUserInfoValidateException(settings.MEDICARE_ERROR_MSG)

    # Validate: sls_hicn cannot be empty.
    if sls_hicn == "":
        err_msg = "User info HICN cannot be empty."
        log_authenticate_start(auth_flow_dict, "FAIL", err_msg, sls_subject, slsx_client=slsx_client)
        raise BBMyMedicareCallbackAuthenticateSlsUserInfoValidateException(settings.MEDICARE_ERROR_MSG)

    # Set Hash values once here for performance and logging.
    sls_hicn_hash = hash_hicn(sls_hicn)
    sls_mbi_hash = hash_mbi(sls_mbi)

    # Validate: sls_mbi format.
    #    NOTE: mbi return from SLS can be empty/None (so can use hicn for matching later)
    sls_mbi_format_valid, sls_mbi_format_msg = is_mbi_format_valid(sls_mbi)
    sls_mbi_format_synthetic = is_mbi_format_synthetic(sls_mbi)
    if not sls_mbi_format_valid and sls_mbi is not None:
        err_msg = "User info MBI format is not valid. "
        log_authenticate_start(auth_flow_dict, "FAIL", err_msg,
                               sls_subject, sls_mbi_format_valid,
                               sls_mbi_format_msg, sls_mbi_format_synthetic,
                               sls_hicn_hash, sls_mbi_hash, slsx_client)
        raise BBMyMedicareCallbackAuthenticateSlsUserInfoValidateException(settings.MEDICARE_ERROR_MSG)

    # Log successful identity information gathered.
    log_authenticate_start(auth_flow_dict, "OK", None, sls_subject,
                           sls_mbi_format_valid, sls_mbi_format_msg,
                           sls_mbi_format_synthetic, sls_hicn_hash, sls_mbi_hash, slsx_client)

    # Find or create the user associated with the identity information from SLS.
    user, crosswalk_action = get_and_update_user(subject=sls_subject,
                                                 mbi_hash=sls_mbi_hash,
                                                 hicn_hash=sls_hicn_hash,
                                                 first_name=sls_first_name,
                                                 last_name=sls_last_name,
                                                 email=sls_email, request=request)

    # Set crosswalk_action and get auth flow session values.
    set_session_auth_flow_trace_value(request, 'auth_crosswalk_action', crosswalk_action)
    auth_flow_dict = get_session_auth_flow_trace(request)

    # Log successful authentication with beneficiary when we return back here.
    log_authenticate_success(auth_flow_dict, sls_subject, user)

    # Update request user.
    request.user = user
Beispiel #9
0
def search_fhir_id_by_identifier(search_identifier, request=None):
    """
        Search the backend FHIR server's patient resource
        using the specified identifier.

        Return:  fhir_id = matched ID (or None for no match).

        Raises exception:
            UpstreamServerException: For backend response issues.
    """
    # Get certs from FHIR server settings
    auth_settings = FhirServerAuth(None)
    certs = (auth_settings['cert_file'], auth_settings['key_file'])

    # Add headers for FHIR backend logging, including auth_flow_dict
    if request:
        # Get auth flow session values.
        auth_flow_dict = get_session_auth_flow_trace(request)
        headers = generate_info_headers(request)
        headers = set_default_header(request, headers)
        # may be part of the contract with BFD
        headers['BlueButton-AuthUuid'] = auth_flow_dict.get('auth_uuid', '')
        headers['BlueButton-AuthAppId'] = auth_flow_dict.get('auth_app_id', '')
        headers['BlueButton-AuthAppName'] = auth_flow_dict.get('auth_app_name', '')
        headers['BlueButton-AuthClientId'] = auth_flow_dict.get('auth_client_id', '')
    else:
        headers = None
        auth_flow_dict = None

    # Build URL with patient ID search by identifier.
    url = get_resourcerouter().fhir_url \
        + "Patient/?identifier=" + search_identifier \
        + "&_format=" + settings.FHIR_PARAM_FORMAT

    s = requests.Session()

    req = requests.Request('GET', url, headers=headers)
    prepped = req.prepare()
    pre_fetch.send_robust(FhirServerAuth, request=req, auth_flow_dict=auth_flow_dict)
    response = s.send(prepped, cert=certs, verify=False)
    post_fetch.send_robust(FhirServerAuth, request=req, response=response, auth_flow_dict=auth_flow_dict)
    response.raise_for_status()
    backend_data = response.json()

    # Parse and validate backend_data response.
    if (
        'total' in backend_data
            and backend_data.get('total', 0) == 1
            and 'entry' in backend_data
            and isinstance(backend_data.get('entry', False), list)
            and len(backend_data.get('entry', '')) == 1
            and isinstance(backend_data['entry'][0].get('resource', False), dict)
            and isinstance(backend_data['entry'][0]['resource'].get('resourceType', False), str)
            and backend_data['entry'][0]['resource']['resourceType'] == "Patient"
            and isinstance(backend_data['entry'][0]['resource'].get('id', False), str)
            and len(backend_data['entry'][0]['resource']['id']) > 0
    ):
        # Found a single matching ID.
        fhir_id = backend_data['entry'][0]['resource']['id']
        return fhir_id
    elif (
        'total' in backend_data
            and 'entry' in backend_data
            and (backend_data.get('total', 0) > 1 or len(backend_data.get('entry', '')) > 1)
    ):
        # Has duplicate beneficiary IDs.
        raise UpstreamServerException("Duplicate beneficiaries found in Patient resource bundle")
    elif (
        'total' in backend_data
            and 'entry' not in backend_data
            and backend_data.get('total', -1) == 0
    ):
        # Not found.
        return None
    else:
        # Unexpected result! Something weird is happening?
        raise UpstreamServerException("Unexpected result found in the Patient resource bundle")
Beispiel #10
0
def get_and_update_user(subject,
                        mbi_hash,
                        hicn_hash,
                        first_name,
                        last_name,
                        email,
                        request=None):
    """
    Find or create the user associated
    with the identity information from the ID provider.

    Args:
        Identity parameters passed in from ID provider.

        subject = ID provider's sub or username
        mbi_hash = Previously hashed mbi
        hicn_hash = Previously hashed hicn
        first_name
        last_name
        email
        request = request from caller to pass along for logging info.
    Returns:
        user = The user that was existing or newly created
        crosswalk_type =  Type of crosswalk activity:
            "R" = Returned existing crosswalk record
            "C" = Created new crosswalk record
    Raises:
        KeyError: If an expected key is missing from user_info.
        KeyError: If response from fhir server is malformed.
        AssertionError: If a user is matched but not all identifiers match.
    """
    # Get auth flow session values.
    auth_flow_dict = get_session_auth_flow_trace(request)

    # Match a patient identifier via the backend FHIR server
    fhir_id, hash_lookup_type = match_fhir_id(mbi_hash=mbi_hash,
                                              hicn_hash=hicn_hash,
                                              request=request)

    try:
        # Does an existing user and crosswalk exist for SLSx username?
        user = User.objects.get(username=subject)

        if user.crosswalk.user_hicn_hash != hicn_hash:
            err_msg = "Found user's hicn did not match"
            log_get_and_update_user(auth_flow_dict, "FAIL", user, fhir_id,
                                    mbi_hash, hicn_hash, hash_lookup_type,
                                    err_msg)
            raise BBMyMedicareCallbackCrosswalkUpdateException(err_msg)

        if user.crosswalk.fhir_id != fhir_id:
            err_msg = "Found user's fhir_id did not match"
            log_get_and_update_user(auth_flow_dict, "FAIL", user, fhir_id,
                                    mbi_hash, hicn_hash, hash_lookup_type,
                                    err_msg)
            raise BBMyMedicareCallbackCrosswalkUpdateException(err_msg)

        if user.crosswalk.user_mbi_hash is not None:
            if user.crosswalk.user_mbi_hash != mbi_hash:
                err_msg = "Found user's mbi did not match"
                log_get_and_update_user(auth_flow_dict, "FAIL", user, fhir_id,
                                        mbi_hash, hicn_hash, hash_lookup_type,
                                        err_msg)
                raise BBMyMedicareCallbackCrosswalkUpdateException(err_msg)
        else:
            # Previously stored value was None/Null and mbi_hash != None, update just the mbi hash.
            if mbi_hash is not None:
                err_msg = "UPDATE mbi_hash since previous value was NULL"
                log_get_and_update_user(auth_flow_dict, "OK", user, fhir_id,
                                        mbi_hash, hicn_hash, hash_lookup_type,
                                        err_msg)
                user.crosswalk.user_mbi_hash = mbi_hash
                user.crosswalk.user_id_type = hash_lookup_type
                user.crosswalk.save()

        # Update hash type used for lookup, if it has changed from last match.
        if user.crosswalk.user_id_type != hash_lookup_type:
            err_msg = "UPDATE user_id_type as it has changed from the previous lookup value"
            log_get_and_update_user(auth_flow_dict, "OK", user, fhir_id,
                                    mbi_hash, hicn_hash, hash_lookup_type,
                                    err_msg)
            user.crosswalk.user_id_type = hash_lookup_type
            user.crosswalk.save()

        err_msg = "RETURN existing beneficiary record"
        log_get_and_update_user(auth_flow_dict, "OK", user, fhir_id, mbi_hash,
                                hicn_hash, hash_lookup_type, err_msg)
        return user, "R"
    except User.DoesNotExist:
        pass

    user = create_beneficiary_record(username=subject,
                                     user_hicn_hash=hicn_hash,
                                     user_mbi_hash=mbi_hash,
                                     fhir_id=fhir_id,
                                     first_name=first_name,
                                     last_name=last_name,
                                     email=email,
                                     user_id_type=hash_lookup_type,
                                     auth_flow_dict=auth_flow_dict)

    err_msg = "CREATE beneficiary record"
    log_get_and_update_user(auth_flow_dict, "OK", user, fhir_id, mbi_hash,
                            hicn_hash, hash_lookup_type, err_msg)
    return user, "C"
Beispiel #11
0
    def __str__(self):
        '''
        --- Logging custom items ---
        '''
        self.log_msg['start_time'] = self.request._logging_start_dt.timestamp()
        self.log_msg['end_time'] = datetime.datetime.utcnow().timestamp()
        self.log_msg['elapsed'] = datetime.datetime.utcnow().timestamp(
        ) - self.request._logging_start_dt.timestamp()
        self.log_msg['ip_addr'] = get_ip_from_request(self.request)
        self.log_msg['request_uuid'] = str(self.request._logging_uuid)
        '''
        --- Logging items from request.POST ---
        '''
        if getattr(self.request, 'POST', False):
            self._log_msg_update_from_dict(self.request.POST,
                                           'req_post_grant_type', 'grant_type')
        '''
        --- Logging items from request.headers ---
        '''
        if getattr(self.request, 'headers', False):
            request_headers = getattr(self.request, 'headers')
            self._log_msg_update_from_dict(request_headers,
                                           'req_header_accept_encoding',
                                           'Accept-Encoding')
            self._log_msg_update_from_dict(request_headers,
                                           'req_header_content_length',
                                           'Content-Length')
            self._log_msg_update_from_dict(request_headers,
                                           'req_header_content_type',
                                           'Content-Type')
            self._log_msg_update_from_dict(request_headers, 'req_header_host',
                                           'Host')
            self._log_msg_update_from_dict(request_headers,
                                           'req_header_referrer', 'Referer')
            self._log_msg_update_from_dict(request_headers,
                                           'req_header_user_agent',
                                           'User-Agent')
        '''
        --- Logging items from request.body ---
        '''
        if getattr(self.request, 'body', False):
            req_body = self.request.body.decode('utf-8', 'ignore')
            try:
                request_body_dict = dict(
                    item.split("=") for item in req_body.split("&"))
                self._log_msg_update_from_dict(request_body_dict,
                                               'req_client_id', 'client_id')

                if self.log_msg.get('req_client_id', False):
                    Application = get_application_model()
                    application = Application.objects.get(
                        client_id=self.log_msg.get('req_client_id'))
                    self._log_msg_update_from_object(application,
                                                     'req_app_name', 'name')
                    self._log_msg_update_from_object(application, 'req_app_id',
                                                     'id')

                refresh_token = request_body_dict.get('refresh_token', None)
                if refresh_token is not None:
                    self.log_msg['req_refresh_token_hash'] = hashlib.sha256(
                        str(refresh_token).encode('utf-8')).hexdigest()

                # Log AC passed from RequestTimeLoggingMiddleware.process_request() pre-response
                self._log_msg_update_from_object(self.request,
                                                 'req_access_token_hash',
                                                 '_req_access_token_hash')

                self._log_msg_update_from_dict(request_body_dict,
                                               'req_response_type',
                                               'response_type')
                self._log_msg_update_from_dict(request_body_dict,
                                               'req_code_challenge_method',
                                               'code_challenge_method')
                self._log_msg_update_from_dict(request_body_dict,
                                               'req_grant_type', 'grant_type')
                self._log_msg_update_from_dict(request_body_dict,
                                               'req_redirect_uri',
                                               'redirect_uri')
                self._log_msg_update_from_dict(request_body_dict, 'req_scope',
                                               'scope')
                self._log_msg_update_from_dict(request_body_dict,
                                               'req_share_demographic_scopes',
                                               'share_demographic_scopes')
                self._log_msg_update_from_dict(request_body_dict, 'req_allow',
                                               'allow')
            except ObjectDoesNotExist:
                pass
            except ValueError:
                pass
        '''
        --- Logging items from request.user ---
        '''
        if getattr(self.request, 'user', False):
            self._log_msg_update_from_object(self.request.user, 'req_user_id',
                                             'id')
            self._log_msg_update_from_object(self.request.user,
                                             'req_user_username', 'username')
            if getattr(self.request.user, 'crosswalk', False):
                self._log_msg_update_from_object(self.request.user.crosswalk,
                                                 'req_fhir_id', 'fhir_id')
        '''
        --- Logging items from request.session for Auth Flow Tracing ---
        '''
        if getattr(self.request, 'session', False):
            if is_path_part_of_auth_flow_trace(self.request.path):
                auth_flow_dict = get_session_auth_flow_trace(self.request)
                for k in SESSION_AUTH_FLOW_TRACE_KEYS:
                    if auth_flow_dict.get(k, None):
                        self.log_msg[k] = auth_flow_dict.get(k, None)
        '''
        --- Logging items from request.GET for query params ---
        '''
        if getattr(self.request, 'GET', False):
            # Log selected query params only
            self._log_msg_update_from_querydict('req_qparam__count', '_count')
            self._log_msg_update_from_querydict('req_qparam__id', '_id')
            self._log_msg_update_from_querydict('req_qparam_beneficiary',
                                                'beneficiary')
            self._log_msg_update_from_querydict('req_qparam_beneficiary',
                                                'Beneficiary')
            self._log_msg_update_from_querydict('req_qparam_client_id',
                                                'client_id')
            self._log_msg_update_from_querydict('req_qparam_count', 'count')
            self._log_msg_update_from_querydict('req_qparam_format', '_format')
            self._log_msg_update_from_querydict('req_qparam_lastupdated',
                                                '_lastUpdated')
            self._log_msg_update_from_querydict('req_qparam_patient',
                                                'patient')
            self._log_msg_update_from_querydict('req_qparam_patient',
                                                'Patient')
            self._log_msg_update_from_querydict('req_qparam_response_type',
                                                'response_type')
            self._log_msg_update_from_querydict('req_qparam_startindex',
                                                'startIndex')
            self._log_msg_update_from_querydict('req_qparam_type', 'type')

            if self.log_msg.get('req_qparam_client_id', False):
                Application = get_application_model()
                application = Application.objects.get(
                    client_id=self.log_msg.get('req_qparam_client_id'))
                self._log_msg_update_from_object(application, 'req_app_name',
                                                 'name')
                self._log_msg_update_from_object(application, 'req_app_id',
                                                 'id')
        '''
        --- Logging items from request ---
        '''
        self._log_msg_update_from_object(self.request, 'path', 'path')
        self._log_msg_update_from_object(self.request, 'request_method',
                                         'method')
        self._log_msg_update_from_object(self.request, 'request_scheme',
                                         'scheme')
        '''
        --- Logging items from get_user_from_request() ---
        '''
        user = get_user_from_request(self.request)
        if user:
            self.log_msg['user'] = str(user)
            try:
                self.log_msg['fhir_id'] = str(user.crosswalk.fhir_id)
            except ObjectDoesNotExist:
                pass
        '''
        --- Logging items from request access token ---
        '''
        access_token = getattr(self.request, 'auth',
                               get_access_token_from_request(self.request))
        if AccessToken.objects.filter(token=access_token).exists():
            try:
                at = AccessToken.objects.get(token=access_token)

                self.log_msg['access_token_hash'] = hashlib.sha256(
                    str(access_token).encode('utf-8')).hexdigest()
                self.log_msg['access_token_scopes'] = ' '.join(
                    [s for s in at.scopes])
                self._log_msg_update_from_object(at.application,
                                                 'access_token_id', 'id')

                self._log_msg_update_from_object(at.application, 'app_name',
                                                 'name')
                self._log_msg_update_from_object(at.application, 'app_id',
                                                 'id')
                self._log_msg_update_from_object(
                    at.application, 'app_require_demographic_scopes',
                    'require_demographic_scopes')
                self._log_msg_update_from_object(at.application.user, 'dev_id',
                                                 'id')
                self._log_msg_update_from_object(at.application.user,
                                                 'dev_name', 'username')

                self._log_msg_update_from_object(at.user, 'user_id', 'id')
                self._log_msg_update_from_object(at.user, 'user_username',
                                                 'username')
            except ObjectDoesNotExist:
                pass
        '''
        --- Logging items from response ---
        '''
        self.log_msg['response_code'] = getattr(self.response, 'status_code',
                                                0)
        if self.log_msg['response_code'] in (300, 301, 302, 307):
            self.log_msg['location'] = self.response.get('Location', '?')
        elif getattr(self.response, 'content', False):
            self.log_msg['size'] = len(self.response.content)
        '''
        --- Logging items from a FHIR type response ---
        '''
        if type(self.response) == Response:
            self.log_msg['fhir_bundle_type'] = self.response.data.get(
                'type', None)
            self.log_msg['fhir_resource_id'] = self.response.data.get(
                'id', None)
            self.log_msg['fhir_resource_type'] = self.response.data.get(
                'resourceType', None)
            self.log_msg['fhir_attribute_count'] = len(self.response.data)
            if self.response.data.get('entry', False):
                self.log_msg['fhir_entry_count'] = len(
                    self.response.data.get('entry'))
            else:
                self.log_msg['fhir_entry_count'] = None
            self.log_msg['fhir_total'] = self.response.data.get('total', None)
        '''
        --- Logging items from response content (refresh_token)
        '''
        access_token = None
        if (getattr(self.response, 'content', False)
                and self.log_msg.get('req_post_grant_type', False)
                and self.log_msg.get('request_method', False)):

            response_content = json.loads(self.response.content)
            resp_access_token = response_content.get('access_token', None)

            if (self.log_msg['req_post_grant_type'] == "refresh_token"
                    and self.log_msg['request_method'] == "POST"
                    and AccessToken.objects.filter(
                        token=resp_access_token).exists()):

                self._log_msg_update_from_dict(response_content,
                                               'resp_fhir_id', 'patient')
                self._log_msg_update_from_dict(response_content,
                                               'resp_expires_in', 'expires_in')
                self._log_msg_update_from_dict(response_content,
                                               'resp_token_type', 'token_type')
                self._log_msg_update_from_dict(response_content, 'resp_scope',
                                               'scope')

                self.log_msg['resp_refresh_token_hash'] = hashlib.sha256(
                    str(response_content.get(
                        'refresh_token', None)).encode('utf-8')).hexdigest()

                try:
                    at = AccessToken.objects.get(token=resp_access_token)
                    self.log_msg['resp_access_token_hash'] = hashlib.sha256(
                        str(access_token).encode('utf-8')).hexdigest()
                    self.log_msg['resp_access_token_scopes'] = ' '.join(
                        [s for s in at.scopes])

                    self._log_msg_update_from_object(at.application,
                                                     'resp_app_id', 'id')
                    self._log_msg_update_from_object(at.application,
                                                     'resp_app_name', 'name')
                    self._log_msg_update_from_object(
                        at.application, 'resp_app_require_demographic_scopes',
                        'require_demographic_scopes')
                    self._log_msg_update_from_object(at.application.user,
                                                     'resp_dev_id', 'id')
                    self._log_msg_update_from_object(at.application.user,
                                                     'resp_dev_name',
                                                     'username')

                    self._log_msg_update_from_object(at.user, 'resp_user_id',
                                                     'id')
                    self._log_msg_update_from_object(at.user,
                                                     'resp_user_username',
                                                     'username')
                except ObjectDoesNotExist:
                    pass

        if settings.LOG_JSON_FORMAT_PRETTY:
            return (json.dumps(self.log_msg, indent=2))
        else:
            return (json.dumps(self.log_msg))