Пример #1
0
    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)
Пример #2
0
    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
Пример #3
0
    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
Пример #4
0
    def provider_config(self,
                        issuer,
                        keys=True,
                        endpoints=True,
                        response_cls=ProviderConfigurationResponse,
                        serv_pattern=OIDCONF_PATTERN):
        """
        The high level method that should be used, by an application, to get 
        the provider info.
        
        :param issuer: The provider/issuer ID
        :param keys: Whether I should store the keys I get back form the OP
        :type keys: Boolean
        :param endpoints: Should I deal with endpoints; that is store them
            as attributes in self. 
        :param response_cls: A class to store the response information in
        :param serv_pattern: A string pattern used to build the 
            query URL.
        :return: A :py:class:`fedoidc.ProviderConfigurationResponse` instance
        """
        if issuer.endswith("/"):
            _issuer = issuer[:-1]
        else:
            _issuer = issuer

        url = serv_pattern % _issuer

        pcr = None
        r = self.http_request(url, allow_redirects=True)
        if r.status_code == 200:
            try:
                pcr = response_cls().from_json(r.text)
            except:
                _err_txt = "Faulty provider config response: {}".format(r.text)
                logger.error(sanitize(_err_txt))
                raise ParseError(_err_txt)

        if 'metadata_statements' not in pcr:
            if 'metadata_statement_uris' not in pcr:
                # Talking to a federation unaware OP
                self.store_response(pcr, r.text)
                self.handle_provider_config(pcr, issuer, keys, endpoints)
                return pcr

        # logger.debug("Provider info: %s" % sanitize(pcr))
        if pcr is None:
            raise CommunicationError("Trying '%s', status %s" %
                                     (url, r.status_code))

        # 3 possible outcomes
        # a) No usable provider info -> Exception
        # b) Exactly one possible provider info to use
        # c) 2 or more usable provider info responses
        try:
            self.handle_response(r, _issuer,
                                 self.parse_federation_provider_info,
                                 ProviderConfigurationResponse)
        except RegistrationError as err:
            raise

        if self.provider_federations:
            return self.chose_provider_federation(_issuer)
        else:  # Otherwise there should be exactly one metadata statement I
            return self.provider_info