def parse_federation_registration(self, resp, issuer): """ Receives a dynamic client registration response, verifies the signature and parses the compounded metadata statement. If only one federation are mentioned in the response then the name of that federation are stored in the *federation* attribute and the flattened response is handled in the normal pyoidc way. If there are more then one federation involved then the decision on which to use has to be made higher up, hence the list of :py:class:`fedoidc.operator.LessOrEqual` instances are stored in the attribute *registration_federations* :param resp: A MetadataStatement instance or a dictionary :param issuer: Issuer ID """ ms_list = self.federation_entity.get_metadata_statement( resp, cls=ClientMetadataStatement) if not ms_list: # No metadata statement that I can use raise RegistrationError('No trusted metadata') # response is a list of registration infos # At this point in time I may not know within which # federation I'll be working. if len(ms_list) == 1: ms = ms_list[0] _trusted_claims = ms.protected_claims() if not _trusted_claims: raise fedoidc.NoTrustedClaims() self.store_registration_info(_trusted_claims) self.federation = ms.fo self.redirect_uris = self.registration_response['redirect_uris'] else: self.registration_federations = ms_list
def verify(self, **kwargs): if "initiate_login_uri" in self and not self[ "initiate_login_uri"].startswith("https:"): raise RegistrationError("initiate_login_uri is not https") if "redirect_uris" in self: for uri in self["redirect_uris"]: if urlparse(uri).fragment: raise InvalidRedirectUri( "redirect_uri contains fragment: %s" % uri) for uri in ["client_uri", "logo_uri", "tos_uri", "policy_uri"]: if uri in self: try: resp = requests.request("GET", str(self[uri]), allow_redirects=True, verify=False) except requests.ConnectionError: raise MissingPage(self[uri]) if resp.status_code not in SUCCESSFUL: raise MissingPage(self[uri]) try: ss = self["software_statement"] except KeyError: pass else: _ss = [] for _s in ss: _ss.append(unpack_software_statement(_s, "", kwargs["keyjar"])) self["__software_statement"] = _ss return super(RegistrationRequest, self).verify(**kwargs)
def handle_response(self, response, issuer, func, response_cls): """ Handle a request response. Depending on which type of response it is different functions *func* will be used to handle it. If something went wrong an exception will be raised. :param response: A requests.request response :param issuer: who was the request sent to :param func: A function to use for handling a correct response :param response_cls: The response should match this class """ err_msg = 'Got error response: {}' unk_msg = 'Unknown response: {}' if response.status_code in [200, 201]: resp = response_cls().deserialize(response.text, "json") # Some implementations sends back a 200 with an error message inside if resp.verify(): # got a proper response func(resp, issuer) else: resp = ErrorResponse().deserialize(response.text, "json") if resp.verify(): logger.error(err_msg.format(sanitize(resp.to_json()))) if self.events: self.events.store('protocol response', resp) raise RegistrationError(resp.to_dict()) else: # Something else logger.error(unk_msg.format(sanitize(response.text))) raise RegistrationError(response.text) else: try: resp = ErrorResponse().deserialize(response.text, "json") except _decode_err: logger.error(unk_msg.format(sanitize(response.text))) raise RegistrationError(response.text) if resp.verify(): logger.error(err_msg.format(sanitize(resp.to_json()))) if self.events: self.events.store('protocol response', resp) raise RegistrationError(resp.to_dict()) else: # Something else logger.error(unk_msg.format(sanitize(response.text))) raise RegistrationError(response.text)
def verify(self, **kwargs): if "initiate_login_uri" in self and not self[ "initiate_login_uri"].startswith("https:"): raise RegistrationError('initiate_login_uri is not https') if "redirect_uris" in self: for uri in self["redirect_uris"]: if urlparse(uri).fragment: raise InvalidRedirectUri( "redirect_uri contains fragment: %s" % uri) for uri in ["client_uri", "logo_uri", "tos_uri", "policy_uri"]: if uri in self: try: resp = requests.request("GET", str(self[uri]), allow_redirects=True, verify=False) except requests.ConnectionError: raise MissingPage(self[uri]) if resp.status_code not in SUCCESSFUL: raise MissingPage(self[uri]) # if "grant_types" in self and "response_types" in self: # for typ in self["grant_types"]: # if typ == "authorization_code": # assert "code" in self["response_types"] # elif typ == "implicit": # assert "token" in self["response_types"] try: ss = self['software_statement'] except KeyError: pass else: # need to get the client keys before I can verify any signature # kj = kwargs['keyjar'] # The case where jwks_uri is used # try: # kj.add(,self['jwks_uri']) _ss = [] for _s in ss: _ss.append(unpack_software_statement(_s, '', kwargs['keyjar'])) self['__software_statement'] = _ss return super(RegistrationRequest, self).verify(**kwargs)
def handle_registration_info(self, response): err_msg = 'Got error response: {}' unk_msg = 'Unknown response: {}' if response.status_code in [200, 201]: resp = RegistrationResponse().deserialize(response.text, "json") # Some implementations sends back a 200 with an error message inside if resp.verify(): # got a proper registration response resp = self.get_metadata_statement(resp) if resp is None: # No metadata statement that I can use raise RegistrationError('No trusted metadata') self.store_response(resp, response.text) self.store_registration_info(resp) else: resp = ErrorResponse().deserialize(response.text, "json") if resp.verify(): logger.error(err_msg.format(sanitize(resp.to_json()))) if self.events: self.events.store('protocol response', resp) raise RegistrationError(resp.to_dict()) else: # Something else logger.error(unk_msg.format(sanitize(response.text))) raise RegistrationError(response.text) else: try: resp = ErrorResponse().deserialize(response.text, "json") except _decode_err: logger.error(unk_msg.format(sanitize(response.text))) raise RegistrationError(response.text) if resp.verify(): logger.error(err_msg.format(sanitize(resp.to_json()))) if self.events: self.events.store('protocol response', resp) raise RegistrationError(resp.to_dict()) else: # Something else logger.error(unk_msg.format(sanitize(response.text))) raise RegistrationError(response.text) return resp