Skip to content

Commit

Permalink
Issue #192: Initial/experimental support for default_client
Browse files Browse the repository at this point in the history
related: EP-3700/EP-3759
  • Loading branch information
soxofaan committed Mar 25, 2021
1 parent 7b619e2 commit 883ad11
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 5 deletions.
11 changes: 10 additions & 1 deletion openeo/rest/auth/oidc.py
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,12 @@ def _decode(data: str) -> dict:
class OidcProviderInfo:
"""OpenID Connect Provider information, as provided by an openEO back-end (endpoint `/credentials/oidc`)"""

def __init__(self, issuer: str = None, discovery_url: str = None, scopes: List[str] = None):
# TODO: The "default_client" feature is still experimental in openEO API. See Open-EO/openeo-api#366

def __init__(
self, issuer: str = None, discovery_url: str = None, scopes: List[str] = None,
default_client: Union[dict, None] = None
):
if issuer is None and discovery_url is None:
raise ValueError("At least `issuer` or `discovery_url` should be specified")
self.discovery_url = discovery_url or (issuer.rstrip("/") + "/.well-known/openid-configuration")
Expand All @@ -230,6 +235,7 @@ def __init__(self, issuer: str = None, discovery_url: str = None, scopes: List[s
# Minimal set of scopes to request
self._supported_scopes = self.config.get("scopes_supported", ["openid"])
self._scopes = {"openid"}.union(scopes or []).intersection(self._supported_scopes)
self.default_client = default_client

def get_scopes_string(self, request_refresh_token: bool = False):
"""
Expand All @@ -244,6 +250,9 @@ def get_scopes_string(self, request_refresh_token: bool = False):
scopes = scopes | {"offline_access"}
return " ".join(sorted(scopes))

def get_default_client_id(self) -> Union[str, None]:
return self.default_client and self.default_client.get("id")


class OidcClientInfo:
"""
Expand Down
21 changes: 17 additions & 4 deletions openeo/rest/connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -331,7 +331,11 @@ def _get_oidc_provider(self, provider_id: Union[str, None] = None) -> Tuple[str,
raise OpenEoClientException("No provider_id given. Available: {p!r}.".format(
p=list(providers.keys()))
)
provider = OidcProviderInfo(issuer=provider["issuer"], scopes=provider.get("scopes"))
provider = OidcProviderInfo(
issuer=provider["issuer"], scopes=provider.get("scopes"),
# TODO: This "default_client" feature is still experimental in openEO API. See Open-EO/openeo-api#366
default_client=provider.get("default_client")
)
else:
# Per spec: '/credentials/oidc' will redirect to OpenID Connect discovery document
provider = OidcProviderInfo(discovery_url=self.build_url('/credentials/oidc'))
Expand All @@ -355,9 +359,18 @@ def _get_oidc_provider_and_client_info(
client_id, client_secret = self._get_auth_config().get_oidc_client_configs(
backend=self._orig_url, provider_id=provider_id
)
_log.info("Using client_id {c!r} from config (provider {p!r})".format(c=client_id, p=provider_id))
if client_id is None:
raise OpenEoClientException("No client ID found.")
if client_id:
_log.info("Using client_id {c!r} from config (provider {p!r})".format(c=client_id, p=provider_id))
if client_id is None:
# TODO: This "default_client" feature is still experimental in openEO API. See Open-EO/openeo-api#366
# Try "default_client" from backend's provider info.
client_id = provider.get_default_client_id()
if client_id:
_log.info("Using default client_id {c!r} from OIDC provider {p!r} info.".format(
c=client_id, p=provider_id
))
if client_id is None:
raise OpenEoClientException("No client ID found.")

client_info = OidcClientInfo(client_id=client_id, client_secret=client_secret, provider=provider)

Expand Down
12 changes: 12 additions & 0 deletions tests/rest/auth/test_oidc.py
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,18 @@ def test_provider_info_scopes(requests_mock):
).get_scopes_string()


def test_provider_info_default_client_none(requests_mock):
requests_mock.get("https://authit.test/.well-known/openid-configuration", json={})
info = OidcProviderInfo(issuer="https://authit.test")
assert info.get_default_client_id() is None


def test_provider_info_default_client_available(requests_mock):
requests_mock.get("https://authit.test/.well-known/openid-configuration", json={})
info = OidcProviderInfo(issuer="https://authit.test", default_client={"id": "jak4l0v3-45lsdfe3d"})
assert info.get_default_client_id() == "jak4l0v3-45lsdfe3d"


@pytest.mark.parametrize(
["scopes_supported", "expected"], [
(["openid", "email"], "openid"),
Expand Down

0 comments on commit 883ad11

Please sign in to comment.