Ejemplo n.º 1
0
 def test_provider_config(self):
     c = Consumer(None, None)
     response = ASConfigurationResponse(**{'issuer': 'https://example.com',
                                           'end_session_endpoint': 'https://example.com/end_session'})
     with responses.RequestsMock() as rsps:
         rsps.add(responses.GET, 'https://example.com/.well-known/openid-configuration', json=response.to_dict())
         info = c.provider_config('https://example.com')
     assert isinstance(info, ASConfigurationResponse)
     assert _eq(info.keys(), ['issuer', 'version', 'end_session_endpoint'])
     assert info["end_session_endpoint"] == "https://example.com/end_session"
Ejemplo n.º 2
0
    def registration_endpoint(self, request, authn=None, **kwargs):
        try:
            reg_req = RegistrationRequest().deserialize(request, "json")
        except ValueError:
            reg_req = RegistrationRequest().deserialize(request)

        logger.debug("@registration_endpoint: {}".format(reg_req))
        self.events.store(EV_PROTOCOL_REQUEST, reg_req)

        if self.strict:
            resp = self.check_scheme(reg_req)
            if resp:
                return resp

        _response = provider.Provider.registration_endpoint(self,
                                                            request=request,
                                                            authn=authn,
                                                            **kwargs)

        logger.debug('registration response: {}'.format(_response.message))
        self.init_keys = []
        if "jwks_uri" in reg_req:
            if _response.status == "200 OK":
                # find the client id
                req_resp = ASConfigurationResponse().from_json(
                    _response.message)
                # for kb in self.keyjar[req_resp["client_id"]]:
                #     if kb.imp_jwks:
                #         self.trace.info("Client JWKS: {}".format(kb.imp_jwks))

        return _response
Ejemplo n.º 3
0
 def test_provider_config(self):
     c = Consumer(None, None)
     response = ASConfigurationResponse(
         **{
             "issuer": "https://example.com",
             "end_session_endpoint": "https://example.com/end_session",
         })
     with responses.RequestsMock() as rsps:
         rsps.add(
             responses.GET,
             "https://example.com/.well-known/openid-configuration",
             json=response.to_dict(),
         )
         info = c.provider_config("https://example.com")
     assert isinstance(info, ASConfigurationResponse)
     assert _eq(info.keys(), ["issuer", "version", "end_session_endpoint"])
     assert info[
         "end_session_endpoint"] == "https://example.com/end_session"
Ejemplo n.º 4
0
    def handle_provider_config(
        self,
        pcr: ASConfigurationResponse,
        issuer: str,
        keys: bool = True,
        endpoints: bool = True,
    ) -> None:
        """
        Deal with Provider Config Response.

        :param pcr: The ProviderConfigResponse instance
        :param issuer: The one I thought should be the issuer of the config
        :param keys: Should I deal with keys
        :param endpoints: Should I deal with endpoints, that is store them as attributes in self.
        """
        if "issuer" in pcr:
            _pcr_issuer = pcr["issuer"]
            if pcr["issuer"].endswith("/"):
                if issuer.endswith("/"):
                    _issuer = issuer
                else:
                    _issuer = issuer + "/"
            else:
                if issuer.endswith("/"):
                    _issuer = issuer[:-1]
                else:
                    _issuer = issuer

            if not self.allow.get("issuer_mismatch", False) and _issuer != _pcr_issuer:
                raise PyoidcError(
                    "provider info issuer mismatch '%s' != '%s'"
                    % (_issuer, _pcr_issuer)
                )

            self.provider_info = pcr
        else:
            _pcr_issuer = issuer

        self.issuer = _pcr_issuer

        if endpoints:
            for key, val in pcr.items():
                if key.endswith("_endpoint"):
                    setattr(self, key, val)

        if keys:
            if self.keyjar is None:
                self.keyjar = KeyJar()

            self.keyjar.load_keys(pcr, _pcr_issuer)
Ejemplo n.º 5
0
    def __init__(
        self,
        client_id=None,
        client_authn_method=None,
        keyjar=None,
        verify_ssl=True,
        config=None,
        client_cert=None,
        timeout=5,
        message_factory: Type[MessageFactory] = OauthMessageFactory,
    ):
        """
        Initialize the instance.

        :param client_id: The client identifier
        :param client_authn_method: Methods that this client can use to
            authenticate itself. It's a dictionary with method names as
            keys and method classes as values.
        :param keyjar: The keyjar for this client.
        :param verify_ssl: Whether the SSL certificate should be verified.
        :param client_cert: A client certificate to use.
        :param timeout: Timeout for requests library. Can be specified either as
            a single integer or as a tuple of integers. For more details, refer to
            ``requests`` documentation.
        :param: message_factory: Factory for message classes, should inherit from OauthMessageFactory
        :return: Client instance
        """
        PBase.__init__(
            self,
            verify_ssl=verify_ssl,
            keyjar=keyjar,
            client_cert=client_cert,
            timeout=timeout,
        )

        self.client_id = client_id
        self.client_authn_method = client_authn_method

        self.nonce = None

        self.message_factory = message_factory
        self.grant = {}  # type: Dict[str, Grant]
        self.state2nonce = {}  # type: Dict[str, str]
        # own endpoint
        self.redirect_uris = []  # type: List[str]

        # service endpoints
        self.authorization_endpoint = None  # type: Optional[str]
        self.token_endpoint = None  # type: Optional[str]
        self.token_revocation_endpoint = None  # type: Optional[str]

        self.request2endpoint = REQUEST2ENDPOINT
        self.response2error = RESPONSE2ERROR  # type: Dict[str, List]
        self.grant_class = Grant
        self.token_class = Token

        self.provider_info = ASConfigurationResponse()  # type: Message
        self._c_secret = ""  # type: str
        self.kid = {"sig": {}, "enc": {}}  # type: Dict[str, Dict]
        self.authz_req = {}  # type: Dict[str, Message]

        # the OAuth issuer is the URL of the authorization server's
        # configuration information location
        self.config = config or {}
        try:
            self.issuer = self.config["issuer"]
        except KeyError:
            self.issuer = ""
        self.allow = {}  # type: Dict[str, Any]
Ejemplo n.º 6
0
    def __init__(
        self,
        client_id=None,
        client_authn_method=None,
        keyjar=None,
        verify_ssl=None,
        config=None,
        client_cert=None,
        timeout=None,
        message_factory: Type[MessageFactory] = OauthMessageFactory,
        settings: PyoidcSettings = None,
    ):
        """
        Initialize the instance.

        Keyword Args:
            settings
                Instance of :class:`OauthClientSettings` with configuration options.
                Currently used settings are:
                 - verify_ssl
                 - client_cert
                 - timeout

        :param client_id: The client identifier
        :param client_authn_method: Methods that this client can use to
            authenticate itself. It's a dictionary with method names as
            keys and method classes as values.
        :param keyjar: The keyjar for this client.
        :param verify_ssl: Whether the SSL certificate should be verified. Deprecated in favor of settings.
        :param client_cert: A client certificate to use. Deprecated in favor of settings.
        :param timeout: Timeout for requests library. Can be specified either as
            a single integer or as a tuple of integers. For more details, refer to
            ``requests`` documentation. Deprecated in favor of settings.
        :param: message_factory: Factory for message classes, should inherit from OauthMessageFactory
        :return: Client instance

        """
        self.settings = settings or OauthClientSettings()
        if verify_ssl is not None:
            warnings.warn(
                "`verify_ssl` is deprecated, please use `settings` instead if you need to set a non-default value.",
                DeprecationWarning,
                stacklevel=2,
            )
            self.settings.verify_ssl = verify_ssl
        if client_cert is not None:
            warnings.warn(
                "`client_cert` is deprecated, please use `settings` instead if you need to set a non-default value.",
                DeprecationWarning,
                stacklevel=2,
            )
            self.settings.client_cert = client_cert
        if timeout is not None:
            warnings.warn(
                "`timeout` is deprecated, please use `settings` instead if you need to set a non-default value.",
                DeprecationWarning,
                stacklevel=2,
            )
            self.settings.timeout = timeout
        PBase.__init__(self, keyjar=keyjar, settings=self.settings)

        self.sso_db = None  # type: Optional[SessionBackend]
        self.client_id = client_id
        self.client_authn_method = client_authn_method

        self.nonce = None  # type: Optional[str]

        self.message_factory = message_factory
        self.grant = {}  # type: Dict[str, Grant]
        self.state2nonce = {}  # type: Dict[str, str]
        # own endpoint
        self.redirect_uris = []  # type: List[str]
        # Default behaviour
        self.response_type = ["code"]

        # service endpoints
        self.authorization_endpoint = None  # type: Optional[str]
        self.token_endpoint = None  # type: Optional[str]
        self.token_revocation_endpoint = None  # type: Optional[str]

        self.request2endpoint = REQUEST2ENDPOINT
        self.response2error = RESPONSE2ERROR  # type: Dict[str, List]
        self.grant_class = Grant
        self.token_class = Token

        self.provider_info = ASConfigurationResponse()  # type: Message
        self._c_secret = ""  # type: str
        self.kid = {"sig": {}, "enc": {}}  # type: Dict[str, Dict]
        self.authz_req = {}  # type: Dict[str, Message]

        # the OAuth issuer is the URL of the authorization server's
        # configuration information location
        self.config = config or {}
        try:
            self.issuer = self.config["issuer"]
        except KeyError:
            self.issuer = ""
        self.allow = {}  # type: Dict[str, Any]
Ejemplo n.º 7
0
    def create_client(self, **kwargs):
        """
        Do an instantiation of a client instance.

        :param: Keyword arguments
            Keys are:
                srv_discovery_url
                client_info
                client_registration
                provider_info
                behaviour
        :return: client instance
        """
        _key_set = set(list(kwargs.keys()))
        try:
            _verify_ssl = kwargs["verify_ssl"]
        except KeyError:
            _verify_ssl = self.verify_ssl
        else:
            _key_set.discard("verify_ssl")

        _client = self.client_cls(
            client_authn_method=CLIENT_AUTHN_METHOD,
            behaviour=kwargs["behaviour"],
            verify_ssl=_verify_ssl,
        )

        # The behaviour parameter is not significant for the election process
        _key_set.discard("behaviour")

        for param in ["allow"]:
            try:
                setattr(_client, param, kwargs[param])
            except KeyError:
                pass
            else:
                _key_set.discard(param)

        if _key_set == {"client_info", "srv_discovery_url"}:
            # Ship the webfinger part
            # Gather OP information
            _client.provider_config(kwargs["srv_discovery_url"])
            # register the client
            _client.register(
                _client.provider_info["registration_endpoint"], **kwargs["client_info"]
            )
            self.get_path(
                kwargs["client_info"]["redirect_uris"], kwargs["srv_discovery_url"]
            )
        elif _key_set == {"provider_info", "client_info"}:
            _client.handle_provider_config(
                ASConfigurationResponse(**kwargs["provider_info"]),
                kwargs["provider_info"]["issuer"],
            )
            _client.register(
                _client.provider_info["registration_endpoint"], **kwargs["client_info"]
            )

            self.get_path(
                kwargs["client_info"]["redirect_uris"],
                kwargs["provider_info"]["issuer"],
            )
        elif _key_set == {"provider_info", "client_registration"}:
            _client.handle_provider_config(
                ASConfigurationResponse(**kwargs["provider_info"]),
                kwargs["provider_info"]["issuer"],
            )
            _client.store_registration_info(
                ClientInfoResponse(**kwargs["client_registration"])
            )
            self.get_path(
                kwargs["client_info"]["redirect_uris"],
                kwargs["provider_info"]["issuer"],
            )
        elif _key_set == {"srv_discovery_url", "client_registration"}:
            _client.provider_config(kwargs["srv_discovery_url"])
            _client.store_registration_info(
                ClientInfoResponse(**kwargs["client_registration"])
            )
            self.get_path(
                kwargs["client_registration"]["redirect_uris"],
                kwargs["srv_discovery_url"],
            )
        else:
            raise Exception("Configuration error ?")

        return client
Ejemplo n.º 8
0
    def create_client(self, userid="", **kwargs):
        """
        Do an instantiation of a client instance.

        :param userid: An identifier of the user
        :param: Keyword arguments
            Keys are ["srv_discovery_url", "client_info", "client_registration",
            "provider_info"]
        :return: client instance
        """
        _key_set = set(list(kwargs.keys()))
        try:
            _verify_ssl = kwargs["verify_ssl"]
        except KeyError:
            _verify_ssl = self.verify_ssl
        else:
            _key_set.discard("verify_ssl")

        client = self.client_cls(
            client_authn_method=CLIENT_AUTHN_METHOD,
            behaviour=kwargs["behaviour"],
            verify_ssl=_verify_ssl,
        )

        try:
            client.userinfo_request_method = kwargs["userinfo_request_method"]
        except KeyError:
            pass
        else:
            _key_set.discard("userinfo_request_method")

        # The behaviour parameter is not significant for the election process
        _key_set.discard("behaviour")
        for param in ["allow"]:
            try:
                setattr(client, param, kwargs[param])
            except KeyError:
                pass
            else:
                _key_set.discard(param)

        if _key_set == {"client_info"}:  # Everything dynamic
            # There has to be a userid
            if not userid:
                raise MissingAttribute("Missing userid specification")

            # Find the service that provides information about the OP
            issuer = client.wf.discovery_query(userid)
            # Gather OP information
            client.provider_config(issuer)
            # register the client
            client.register(
                client.provider_info["registration_endpoint"], **kwargs["client_info"]
            )
            self.get_path(kwargs["client_info"]["redirect_uris"], issuer)
        elif _key_set == set(["client_info", "srv_discovery_url"]):
            # Ship the webfinger part
            # Gather OP information
            client.provider_config(kwargs["srv_discovery_url"])
            # register the client
            client.register(
                client.provider_info["registration_endpoint"], **kwargs["client_info"]
            )
            self.get_path(
                kwargs["client_info"]["redirect_uris"], kwargs["srv_discovery_url"]
            )
        elif _key_set == set(["provider_info", "client_info"]):
            client.handle_provider_config(
                ASConfigurationResponse(**kwargs["provider_info"]),
                kwargs["provider_info"]["issuer"],
            )
            client.register(
                client.provider_info["registration_endpoint"], **kwargs["client_info"]
            )

            self.get_path(
                kwargs["client_info"]["redirect_uris"],
                kwargs["provider_info"]["issuer"],
            )
        elif _key_set == set(["provider_info", "client_registration"]):
            client.handle_provider_config(
                ASConfigurationResponse(**kwargs["provider_info"]),
                kwargs["provider_info"]["issuer"],
            )
            client.store_registration_info(
                RegistrationResponse(**kwargs["client_registration"])
            )
            self.get_path(
                kwargs["client_info"]["redirect_uris"],
                kwargs["provider_info"]["issuer"],
            )
        elif _key_set == set(["srv_discovery_url", "client_registration"]):
            client.provider_config(kwargs["srv_discovery_url"])
            client.store_registration_info(
                RegistrationResponse(**kwargs["client_registration"])
            )
            self.get_path(
                kwargs["client_registration"]["redirect_uris"],
                kwargs["srv_discovery_url"],
            )
        else:
            raise Exception("Configuration error ?")

        return client