def verify(self, provider_capabilities, provider_software_statement, client_preferences, client_software_statement): # type: (Mapping[str, Union[str, Sequence[str]]], # Mapping[str, Union[str, Sequence[str]]], # Mapping[str, Union[str, Sequence[str]]], # Mapping[str, Union[str, Sequence[str]]]) -> Dict[str, Union[str, List[str]]] """ Verify the provider can satisfy the client's registration request. Negotiates the metadata parameters combined from the provider metadata, provider software statement, client metadata, and client software statement. :param provider_capabilities: provider metadata :param provider_software_statement: provider software statement :param client_preferences: client metadata :param client_software_statement: client software statement :raise OIDCFederationError: if the client metadata can't be matched with the provider's capabilities :return: the "negotiated" client metadata parameters that overrides/extends the initial registration request """ client_preferences = copy.deepcopy(client_preferences) client_preferences.update(client_software_statement) provider_capabilities = copy.deepcopy(provider_capabilities) provider_capabilities.update(provider_software_statement) client_preferences.update( self._match_array_preferences(client_preferences, provider_capabilities)) for client_preference, provider_capability in [v for v in PREFERENCE2PROVIDER.items() if v not in RegistrationRequestVerification.METADATA_AS_ARRAYS]: if client_preference not in client_preferences and provider_capability in provider_software_statement: # default to metadata from provider software statement to ensure restrictions from # the federation are applied restrictions = provider_software_statement[provider_capability] # just select the first, but could be some smarter heuristic client_preferences[client_preference] = restrictions[0] continue try: client_value = client_preferences[client_preference] provider_values = provider_capabilities[provider_capability] except KeyError: continue if client_value not in provider_values: raise OIDCFederationError( "Mismatch in registration request: {} '{}' not in {} '{}'.".format( client_preference, client_value, provider_capability, provider_values)) return client_preferences
def match_client_request(self, request): for _pref, _prov in PREFERENCE2PROVIDER.items(): if _pref in request: if _pref == "response_types": for val in request[_pref]: match = False p = set(val.split(" ")) for cv in self.capabilities[_prov]: if p == set(cv.split(" ")): match = True break if not match: raise CapabilitiesMisMatch("Not allowed {}".format(_pref)) else: if isinstance(request[_pref], str): if request[_pref] not in self.capabilities[_prov]: raise CapabilitiesMisMatch("Not allowed {}".format(_pref)) else: if not set(request[_pref]).issubset( set(self.capabilities[_prov]) ): raise CapabilitiesMisMatch("Not allowed {}".format(_pref))
def match_client_request(self, request): for _pref, _prov in PREFERENCE2PROVIDER.items(): if _pref in request: if _pref == "response_types": for val in request[_pref]: match = False p = set(val.split(" ")) for cv in self.capabilities[_prov]: if p == set(cv.split(' ')): match = True break if not match: raise CapabilitiesMisMatch( 'Not allowed {}'.format(_pref)) else: if isinstance(request[_pref], six.string_types): if request[_pref] not in self.capabilities[_prov]: raise CapabilitiesMisMatch( 'Not allowed {}'.format(_pref)) else: if not set(request[_pref]).issubset( set(self.capabilities[_prov])): raise CapabilitiesMisMatch( 'Not allowed {}'.format(_pref))