def _get_approved_attributes(self, provider_supported_claims, authn_req): requested_claims = list(scope2claims(authn_req["scope"]).keys()) if "claims" in authn_req: for k in ["id_token", "userinfo"]: if k in authn_req["claims"]: requested_claims.extend(authn_req["claims"][k].keys()) return set(provider_supported_claims).intersection(set(requested_claims))
def handle_userinfo_request(self, request=None, http_headers=None): # type: (Optional[str], Optional[Mapping[str, str]]) -> oic.oic.message.OpenIDSchema """ Handles a userinfo request. :param request: urlencoded request (either query string or POST body) :param http_headers: http headers """ if http_headers is None: http_headers = {} userinfo_request = dict(parse_qsl(request)) bearer_token = extract_bearer_token_from_http_request( userinfo_request, http_headers.get('Authorization')) introspection = self.authz_state.introspect_access_token(bearer_token) if not introspection['active']: raise InvalidAccessToken('The access token has expired') scope = introspection['scope'] user_id = self.authz_state.get_user_id_for_subject_identifier( introspection['sub']) requested_claims = scope2claims(scope.split()) authentication_request = self.authz_state.get_authorization_request_for_access_token( bearer_token) requested_claims.update( self._get_requested_claims_in(authentication_request, 'userinfo')) user_claims = self.userinfo.get_claims_for(user_id, requested_claims) user_claims.setdefault('sub', introspection['sub']) response = OpenIDSchema(**user_claims) logger.debug('userinfo=%s from requested_claims=%s userinfo=%s', response, requested_claims, user_claims) return response
def authorize(self, authentication_request, # type: oic.oic.message.AuthorizationRequest user_id, # type: str extra_id_token_claims=None # type: Optional[Union[Mapping[str, Union[str, List[str]]], Callable[[str, str], Mapping[str, Union[str, List[str]]]]] ): # type: (...) -> oic.oic.message.AuthorizationResponse """ Creates an Authentication Response for the specified authentication request and local identifier of the authenticated user. """ custom_sub = self.userinfo[user_id].get('sub') if custom_sub: self.authz_state.subject_identifiers[user_id] = {'public': custom_sub} sub = custom_sub else: sub = self._create_subject_identifier(user_id, authentication_request['client_id'], authentication_request['redirect_uri']) self._check_subject_identifier_matches_requested(authentication_request, sub) response = AuthorizationResponse() authz_code = None if 'code' in authentication_request['response_type']: authz_code = self.authz_state.create_authorization_code(authentication_request, sub) response['code'] = authz_code access_token_value = None if 'token' in authentication_request['response_type']: access_token = self.authz_state.create_access_token(authentication_request, sub) access_token_value = access_token.value self._add_access_token_to_response(response, access_token) if 'id_token' in authentication_request['response_type']: if extra_id_token_claims is None: extra_id_token_claims = {} elif callable(extra_id_token_claims): extra_id_token_claims = extra_id_token_claims(user_id, authentication_request['client_id']) requested_claims = self._get_requested_claims_in(authentication_request, 'id_token') if len(authentication_request['response_type']) == 1: # only id token is issued -> no way of doing userinfo request, so include all claims in ID Token, # even those requested by the scope parameter requested_claims.update( scope2claims( authentication_request['scope'], extra_scope_dict=self.extra_scopes ) ) user_claims = self.userinfo.get_claims_for(user_id, requested_claims) response['id_token'] = self._create_signed_id_token(authentication_request['client_id'], sub, user_claims, authentication_request.get('nonce'), authz_code, access_token_value, extra_id_token_claims) logger.debug('issued id_token=%s from requested_claims=%s userinfo=%s extra_claims=%s', response['id_token'], requested_claims, user_claims, extra_id_token_claims) if 'state' in authentication_request: response['state'] = authentication_request['state'] return response
def test_scope2claims_with_non_standard_scope(self): claims = scope2claims(['my_scope', 'email']) assert Counter(claims.keys()) == Counter(SCOPE2CLAIMS['email'])
def test_scope2claims(self): claims = scope2claims(['profile', 'email']) assert Counter(claims.keys()) == Counter(SCOPE2CLAIMS['profile'] + SCOPE2CLAIMS['email'])
def test_scope2claims_extra_scope_dict(self): claims = scope2claims(["my_scope", "email"], extra_scope_dict={"my_scope": ["my_attribute"]}) assert sorted( claims.keys()) == ["email", "email_verified", "my_attribute"]
def test_scope2claims_with_non_standard_scope(self): claims = scope2claims(["my_scope", "email"]) assert Counter(claims.keys()) == Counter(SCOPE2CLAIMS["email"])
def test_scope2claims(self): claims = scope2claims(["profile", "email"]) assert Counter(claims.keys()) == Counter(SCOPE2CLAIMS["profile"] + SCOPE2CLAIMS["email"])
def test_scope2claims_extra_scope_dict(self): claims = scope2claims(['my_scope', 'email'], extra_scope_dict={'my_scope': ['my_attribute']}) assert sorted( claims.keys()) == ['email', 'email_verified', 'my_attribute']
def test_scope2claims_extra_scope_dict(self): claims = scope2claims(['my_scope', 'email'], extra_scope_dict={'my_scope': ['my_attribute']}) assert sorted(claims.keys()) == ['email', 'email_verified', 'my_attribute']