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 <jens@goauthentik.io> * add nonce claim Signed-off-by: Jens Langhammer <jens@goauthentik.io> Signed-off-by: Jens Langhammer <jens@goauthentik.io>
This commit is contained in:
parent
9c9f441cff
commit
20931ccc1d
|
@ -6,6 +6,7 @@ from django.shortcuts import get_object_or_404, reverse
|
||||||
from django.views import View
|
from django.views import View
|
||||||
from structlog.stdlib import get_logger
|
from structlog.stdlib import get_logger
|
||||||
|
|
||||||
|
from authentik.core.exceptions import PropertyMappingExpressionException
|
||||||
from authentik.core.models import Application
|
from authentik.core.models import Application
|
||||||
from authentik.providers.oauth2.constants import (
|
from authentik.providers.oauth2.constants import (
|
||||||
ACR_AUTHENTIK_DEFAULT,
|
ACR_AUTHENTIK_DEFAULT,
|
||||||
|
@ -108,20 +109,40 @@ class ProviderInfoView(View):
|
||||||
"scopes_supported": scopes,
|
"scopes_supported": scopes,
|
||||||
# https://openid.net/specs/openid-connect-core-1_0.html#RequestObject
|
# https://openid.net/specs/openid-connect-core-1_0.html#RequestObject
|
||||||
"request_parameter_supported": False,
|
"request_parameter_supported": False,
|
||||||
# Because claims are dynamic and per-application, the only claims listed here
|
"claims_supported": self.get_claims(provider),
|
||||||
# are ones that are always set by authentik itself on every token
|
|
||||||
"claims_supported": [
|
|
||||||
"sub",
|
|
||||||
"iss",
|
|
||||||
"aud",
|
|
||||||
"exp",
|
|
||||||
"iat",
|
|
||||||
"auth_time",
|
|
||||||
"acr",
|
|
||||||
],
|
|
||||||
"claims_parameter_supported": False,
|
"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
|
# pylint: disable=unused-argument
|
||||||
def get(self, request: HttpRequest, *args, **kwargs) -> HttpResponse:
|
def get(self, request: HttpRequest, *args, **kwargs) -> HttpResponse:
|
||||||
"""OpenID-compliant Provider Info"""
|
"""OpenID-compliant Provider Info"""
|
||||||
|
|
|
@ -110,6 +110,8 @@ class UserInfoView(View):
|
||||||
return HttpResponseBadRequest()
|
return HttpResponseBadRequest()
|
||||||
claims = self.get_claims(self.token)
|
claims = self.get_claims(self.token)
|
||||||
claims["sub"] = self.token.id_token.sub
|
claims["sub"] = self.token.id_token.sub
|
||||||
|
if self.token.id_token.nonce:
|
||||||
|
claims["nonce"] = self.token.id_token.nonce
|
||||||
response = TokenResponse(claims)
|
response = TokenResponse(claims)
|
||||||
return response
|
return response
|
||||||
|
|
||||||
|
|
Reference in a new issue