Exemple #1
0
    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
Exemple #2
0
    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
Exemple #3
0
    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
Exemple #4
0
    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
Exemple #5
0
    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
Exemple #6
0
    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