From 20931ccc1d1767cd894c588055b62e7dfa1a1176 Mon Sep 17 00:00:00 2001 From: Jens L Date: Fri, 13 Jan 2023 14:14:25 +0100 Subject: [PATCH] providers/oauth2: correctly fill claims_supported based on selected scopes (#4429) * providers/oauth2: correctly fill claims_supported based on selected scopes Signed-off-by: Jens Langhammer * add nonce claim Signed-off-by: Jens Langhammer Signed-off-by: Jens Langhammer --- authentik/providers/oauth2/views/provider.py | 43 +++++++++++++++----- authentik/providers/oauth2/views/userinfo.py | 2 + 2 files changed, 34 insertions(+), 11 deletions(-) diff --git a/authentik/providers/oauth2/views/provider.py b/authentik/providers/oauth2/views/provider.py index 62e993855..99b0cea86 100644 --- a/authentik/providers/oauth2/views/provider.py +++ b/authentik/providers/oauth2/views/provider.py @@ -6,6 +6,7 @@ from django.shortcuts import get_object_or_404, reverse from django.views import View from structlog.stdlib import get_logger +from authentik.core.exceptions import PropertyMappingExpressionException from authentik.core.models import Application from authentik.providers.oauth2.constants import ( ACR_AUTHENTIK_DEFAULT, @@ -108,20 +109,40 @@ class ProviderInfoView(View): "scopes_supported": scopes, # https://openid.net/specs/openid-connect-core-1_0.html#RequestObject "request_parameter_supported": False, - # Because claims are dynamic and per-application, the only claims listed here - # are ones that are always set by authentik itself on every token - "claims_supported": [ - "sub", - "iss", - "aud", - "exp", - "iat", - "auth_time", - "acr", - ], + "claims_supported": self.get_claims(provider), "claims_parameter_supported": False, } + def get_claims(self, provider: OAuth2Provider) -> list[str]: + """Get a list of supported claims based on configured scope mappings""" + default_claims = [ + "sub", + "iss", + "aud", + "exp", + "iat", + "auth_time", + "acr", + "amr", + "nonce", + ] + for scope in ScopeMapping.objects.filter(provider=provider).order_by("scope_name"): + value = None + try: + value = scope.evaluate( + user=self.request.user, + request=self.request, + provider=provider, + ) + except PropertyMappingExpressionException: + continue + if value is None: + continue + if not isinstance(value, dict): + continue + default_claims.extend(value.keys()) + return default_claims + # pylint: disable=unused-argument def get(self, request: HttpRequest, *args, **kwargs) -> HttpResponse: """OpenID-compliant Provider Info""" diff --git a/authentik/providers/oauth2/views/userinfo.py b/authentik/providers/oauth2/views/userinfo.py index eef88cf71..cb0968786 100644 --- a/authentik/providers/oauth2/views/userinfo.py +++ b/authentik/providers/oauth2/views/userinfo.py @@ -110,6 +110,8 @@ class UserInfoView(View): return HttpResponseBadRequest() claims = self.get_claims(self.token) claims["sub"] = self.token.id_token.sub + if self.token.id_token.nonce: + claims["nonce"] = self.token.id_token.nonce response = TokenResponse(claims) return response