def parse_federation_provider_info(self, resp, issuer): """ Takes a provider info response and parses it. If according to the info the OP has more then one federation in common with the client then the decision has to be handled higher up. The list of :py:class:`fedoidc.operator.LessOrEqual` instances are stored in *provider_federations*. If the OP and RP only has one federation in common then the choice is easy and the name of the federation are stored in the *federation* attribute while the provider info are stored in the normal pyoidc Client way. :param resp: A MetadataStatement instance :param issuer: The OpenID Provider ID """ ms_list = self.federation_entity.get_metadata_statement( resp, cls=ProviderConfigurationResponse) if not ms_list: # No metadata statement that I can use raise ParameterError('No trusted metadata') # response is a list of metadata statements # At this point in time I may not know within which # federation I'll be working. if len(resp) == 1: ms = ms_list[0] self.handle_provider_config(ms.protected_claims(), issuer) self.federation = ms.fo else: self.provider_federations = ms_list
def _run(self): if self.skip: return self.conv.events.store( EV_REQUEST, "op_args: {}, req_args: {}".format(self.op_args, self.req_args), direction=OUTGOING) if 'authn_method' not in self.op_args: _ent = self.conv.entity try: #use the registered authn method self.op_args['authn_method'] = _ent.registration_response['token_endpoint_auth_method'] except KeyError: #use the first mutually supported authn method for am in _ent.client_authn_method.keys(): if am in _ent.provider_info['token_endpoint_auth_methods_supported']: self.op_args['authn_method'] = am break try: atr = self.catch_exception_and_error( self.conv.entity.do_access_token_request, request_args=self.req_args, **self.op_args) except HttpError: return None if atr is None or isinstance(atr, ErrorResponse): return atr try: msg = atr['id_token'] except KeyError: pass else: display_jwx_headers(msg, self.conv) try: _jws_alg = atr["id_token"].jws_header['alg'] except (KeyError, AttributeError): pass else: if _jws_alg == "none": pass elif "kid" not in atr[ "id_token"].jws_header and _jws_alg != "HS256": keys = self.conv.entity.keyjar.keys_by_alg_and_usage( self.conv.info["issuer"], _jws_alg, "ver") if len(keys) > 1: raise ParameterError("No 'kid' in id_token header!") if not same_issuer(self.conv.info["issuer"], atr["id_token"]["iss"]): raise IssuerMismatch(" {} != {}".format(self.conv.info["issuer"], atr["id_token"]["iss"])) # assert isinstance(atr, AccessTokenResponse) return atr
def get_redirect_uri(self, areq): """ verify that the redirect URI is reasonable :param areq: The Authorization request :return: Tuple of (redirect_uri, Response instance) Response instance is not None of matching redirect_uri failed """ if 'redirect_uri' in areq: self._verify_redirect_uri(areq) uri = areq["redirect_uri"] else: raise ParameterError( "Missing redirect_uri and more than one or none registered") return uri
def _run(self): if self.skip: return if 'authn_method' not in self.op_args: _ent = self.conv.entity try: self.op_args['authn_method'] = _ent.registration_response[ 'token_endpoint_auth_method'] except KeyError: for am in _ent.client_authn_method.keys(): if am in _ent.provider_info[ 'token_endpoint_auth_methods_supported']: self.op_args['authn_method'] = am break self.conv.events.store(EV_REQUEST, "op_args: {}, req_args: {}".format( self.op_args, self.req_args), direction=OUTGOING) atr = self.catch_exception_and_error( self.conv.entity.do_access_token_refresh, request_args=self.req_args, **self.op_args) try: msg = atr['id_token'] except KeyError: pass else: display_jwx_headers(msg, self.conv) try: _jws_alg = atr["id_token"].jws_header["alg"] except (KeyError, AttributeError): pass else: if _jws_alg == "none": pass elif "kid" not in atr[ "id_token"].jws_header and not _jws_alg == "HS256": keys = self.conv.entity.keyjar.keys_by_alg_and_usage( self.conv.info["issuer"], _jws_alg, "ver") if len(keys) > 1: raise ParameterError("No 'kid' in id_token header!") return atr
def parse_federation_provider_info(self, resp, issuer): """ Takes a provider info response and parses it. If according to the info the OP has more then one federation in common with the client then the decision has to be handled higher up. The list of :py:class:`fedoidc.operator.LessOrEqual` instances are stored in *provider_federations*. If the OP and RP only has one federation in common then the choice is easy and the name of the federation are stored in the *federation* attribute while the provider info are stored in the normal pyoidc Client way. :param resp: A MetadataStatement instance :param issuer: The OpenID Provider ID """ les = self.federation_entity.get_metadata_statement( resp, cls=ProviderConfigurationResponse) if not les: # No metadata statement that I can use raise ParameterError('No trusted metadata') # response is a list of metadata statements # At this point in time I may not know within which # federation I'll be working. if len(les) == 1: ms = les[0] _claims = ms.protected_claims() self.handle_provider_config(ms.protected_claims(), issuer) if 'signed_jwks_uri' in _claims: _kb = fedoidc.KeyBundle(source=_claims['signed_jwks_uri'], verify_keys=les.signing_keys, verify_ssl=False) _kb.do_remote() replace_jwks_key_bundle(self.keyjar, issuer, _kb) self.federation = ms.fo else: self.provider_federations = les
def _run(self): if self.skip: return self.conv.events.store(EV_REQUEST, "op_args: {}, req_args: {}".format( self.op_args, self.req_args), direction=OUTGOING) atr = self.catch_exception_and_error( self.conv.entity.do_access_token_request, request_args=self.req_args, **self.op_args) if atr is None or isinstance(atr, ErrorResponse): return atr try: _jws_alg = atr["id_token"].jws_header["alg"] except (KeyError, AttributeError): pass else: if _jws_alg == "none": pass elif "kid" not in atr[ "id_token"].jws_header and not _jws_alg == "HS256": keys = self.conv.entity.keyjar.keys_by_alg_and_usage( self.conv.info["issuer"], _jws_alg, "ver") if len(keys) > 1: raise ParameterError("No 'kid' in id_token header!") if not same_issuer(self.conv.info["issuer"], atr["id_token"]["iss"]): raise IssuerMismatch(" {} != {}".format(self.conv.info["issuer"], atr["id_token"]["iss"])) # assert isinstance(atr, AccessTokenResponse) return atr