示例#1
0
    def authenticate_OIDC(self,
                          client_id: str,
                          webbrowser_open=None,
                          timeout=120) -> 'Connection':
        """
        Authenticates a user to the backend using OpenID Connect.

        :param client_id: Client id to use for OpenID Connect authentication
        :param webbrowser_open: optional handler for the initial OAuth authentication request
            (opens a webbrowser by default)
        :param timeout: number of seconds after which to abort the authentication procedure
        """
        # Local import to avoid importing the whole OpenID Connect dependency chain. TODO: just do global import?
        from openeo.rest.auth.oidc import OidcAuthCodePkceAuthenticator

        # Per spec: '/credentials/oidc' will redirect to  OpenID Connect discovery document
        oidc_discovery_url = self.build_url('/credentials/oidc')
        authenticator = OidcAuthCodePkceAuthenticator(
            client_id=client_id,
            oidc_discovery_url=oidc_discovery_url,
            webbrowser_open=webbrowser_open,
            timeout=timeout,
        )
        # Do the Oauth/OpenID Connect flow and use the access token as bearer token.
        tokens = authenticator.get_tokens()
        # TODO: ability to refresh the token when expired?
        self.auth = BearerAuth(bearer=tokens.access_token)
        return self
示例#2
0
def test_oidc_flow(oidc_test_setup):
    # see test/rest/conftest.py for `oidc_test_setup` fixture
    client_id = "myclient"
    oidc_discovery_url = "http://oidc.example.com/.well-known/openid-configuration"
    state, webbrowser_open = oidc_test_setup(
        client_id=client_id, oidc_discovery_url=oidc_discovery_url)

    authenticator = OidcAuthCodePkceAuthenticator(
        client_id=client_id,
        oidc_discovery_url=oidc_discovery_url,
        webbrowser_open=webbrowser_open)
    # Do the Oauth/OpenID Connect flow
    tokens = authenticator.get_tokens()
    assert state["access_token"] == tokens.access_token
示例#3
0
    def authenticate_OIDC(
            self, client_id: str,
            provider_id: str = None,
            webbrowser_open=None,
            timeout=120,
            server_address: Tuple[str, int] = None
    ) -> 'Connection':
        """
        Authenticates a user to the backend using OpenID Connect.

        :param client_id: Client id to use for OpenID Connect authentication
        :param webbrowser_open: optional handler for the initial OAuth authentication request
            (opens a webbrowser by default)
        :param timeout: number of seconds after which to abort the authentication procedure
        :param server_address: optional tuple (hostname, port_number) to serve the OAuth redirect callback on

        TODO: deprecated?
        """
        # TODO: option to increase log level temporarily?
        provider_id, provider = self._get_oidc_provider(provider_id)

        client_info = OidcClientInfo(client_id=client_id, provider=provider)
        authenticator = OidcAuthCodePkceAuthenticator(
            client_info=client_info,
            webbrowser_open=webbrowser_open,
            timeout=timeout,
            server_address=server_address,
        )
        return self._authenticate_oidc(authenticator, provider_id=provider_id)
示例#4
0
 def token_callback(request, context):
     """Fake code to token exchange by Oauth Provider"""
     params = _get_query_params(query=request.text)
     assert params["client_id"] == client_id
     assert params["grant_type"] == "authorization_code"
     assert state[
         "code_challenge"] == OidcAuthCodePkceAuthenticator.hash_code_verifier(
             params["code_verifier"])
     assert params["code"] == "6uthc0d3"
     assert params["redirect_uri"] == state["redirect_uri"]
     state["access_token"] = _jwt_encode({}, {
         "sub": "123",
         "name": "john",
         "nonce": state["nonce"]
     })
     return json.dumps({
         "access_token":
         state["access_token"],
         "id_token":
         _jwt_encode({}, {
             "sub": "123",
             "name": "john",
             "nonce": state["nonce"]
         }),
         "refresh_token":
         _jwt_encode({}, {"nonce": state["nonce"]}),
     })
示例#5
0
    def authenticate_oidc_authorization_code(
        self,
        client_id: str = None,
        client_secret: str = None,
        provider_id: str = None,
        timeout: int = None,
        server_address: Tuple[str, int] = None,
        webbrowser_open: Callable = None,
        store_refresh_token=False,
    ) -> 'Connection':
        """
        OpenID Connect Authorization Code Flow (with PKCE).

        WARNING: this API is in experimental phase
        """
        provider_id, client_info = self._get_oidc_provider_and_client_info(
            provider_id=provider_id,
            client_id=client_id,
            client_secret=client_secret)
        authenticator = OidcAuthCodePkceAuthenticator(
            client_info=client_info,
            webbrowser_open=webbrowser_open,
            timeout=timeout,
            server_address=server_address)
        return self._authenticate_oidc(authenticator,
                                       provider_id=provider_id,
                                       store_refresh_token=store_refresh_token)
示例#6
0
 def authenticate_oidc_authorization_code(
     self,
     client_id: str = None,
     client_secret: str = None,
     provider_id: str = None,
     timeout: int = None,
     server_address: Tuple[str, int] = None,
     webbrowser_open: Callable = None,
     store_refresh_token=False,
 ) -> 'Connection':
     """
     OpenID Connect Authorization Code Flow (with PKCE).
     """
     provider_id, client_info = self._get_oidc_provider_and_client_info(
         provider_id=provider_id,
         client_id=client_id,
         client_secret=client_secret,
         default_client_grant_types=[DefaultOidcClientGrant.AUTH_CODE_PKCE],
     )
     authenticator = OidcAuthCodePkceAuthenticator(
         client_info=client_info,
         webbrowser_open=webbrowser_open,
         timeout=timeout,
         server_address=server_address)
     return self._authenticate_oidc(authenticator,
                                    provider_id=provider_id,
                                    store_refresh_token=store_refresh_token)
示例#7
0
 def token_callback_authorization_code(
         self, request: requests_mock.request._RequestObjectProxy, context):
     """Fake code to token exchange by Oauth Provider"""
     params = self._get_query_params(query=request.text)
     assert params["client_id"] == self.expected_client_id
     assert params["grant_type"] == "authorization_code"
     assert self.state[
         "code_challenge"] == OidcAuthCodePkceAuthenticator.hash_code_verifier(
             params["code_verifier"])
     assert params["code"] == self.expected_authorization_code
     assert params["redirect_uri"] == self.state["redirect_uri"]
     self.state["access_token"] = self._jwt_encode(
         {}, {
             "sub": "123",
             "name": "john",
             "nonce": self.state["nonce"]
         })
     return json.dumps({
         "access_token":
         self.state["access_token"],
         "id_token":
         self._jwt_encode({}, {
             "sub": "123",
             "name": "john",
             "nonce": self.state["nonce"]
         }),
         "refresh_token":
         self._jwt_encode({}, {}),
     })
示例#8
0
def test_oidc_auth_code_pkce_flow(requests_mock):
    requests_mock.get("http://oidc.test/.well-known/openid-configuration",
                      json={"scopes_supported": ["openid"]})

    client_id = "myclient"
    oidc_discovery_url = "http://oidc.test/.well-known/openid-configuration"
    oidc_mock = OidcMock(requests_mock=requests_mock,
                         expected_grant_type="authorization_code",
                         expected_client_id=client_id,
                         expected_fields={"scope": "openid testpkce"},
                         oidc_discovery_url=oidc_discovery_url,
                         scopes_supported=["openid", "testpkce"])
    provider = OidcProviderInfo(discovery_url=oidc_discovery_url,
                                scopes=["openid", "testpkce"])
    authenticator = OidcAuthCodePkceAuthenticator(
        client_info=OidcClientInfo(client_id=client_id, provider=provider),
        webbrowser_open=oidc_mock.webbrowser_open)
    # Do the Oauth/OpenID Connect flow
    tokens = authenticator.get_tokens()
    assert oidc_mock.state["access_token"] == tokens.access_token
示例#9
0
 def token_callback_authorization_code(
         self, request: requests_mock.request._RequestObjectProxy, context):
     """Fake code to token exchange by Oauth Provider"""
     params = self._get_query_params(query=request.text)
     assert params["client_id"] == self.expected_client_id
     assert params["grant_type"] == "authorization_code"
     assert self.state[
         "code_challenge"] == OidcAuthCodePkceAuthenticator.hash_code_verifier(
             params["code_verifier"])
     assert params["code"] == self.expected_authorization_code
     assert params["redirect_uri"] == self.state["redirect_uri"]
     return self._build_token_response()
示例#10
0
    def authenticate_oidc_authorization_code(
            self,
            client_id: str,
            client_secret: str = None,
            provider_id: str = None,
            timeout: int = None,
            server_address: Tuple[str, int] = None,
            webbrowser_open: Callable = None) -> 'Connection':
        """
        OpenID Connect Authorization Code Flow (with PKCE).

        WARNING: this API is in experimental phase
        """
        provider_id, provider = self._get_oidc_provider(provider_id)
        # TODO: load client info and settings from config file?
        client_info = OidcClientInfo(client_id=client_id,
                                     client_secret=client_secret,
                                     provider=provider)
        authenticator = OidcAuthCodePkceAuthenticator(
            client_info=client_info,
            webbrowser_open=webbrowser_open,
            timeout=timeout,
            server_address=server_address)
        return self._authenticate_oidc(authenticator, provider_id=provider_id)