-
-
Notifications
You must be signed in to change notification settings - Fork 571
/
provider.py
113 lines (103 loc) · 4.52 KB
/
provider.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
"""authentik OAuth2 OpenID well-known views"""
from typing import Any
from django.http import HttpRequest, HttpResponse, JsonResponse
from django.shortcuts import get_object_or_404, reverse
from django.views import View
from structlog.stdlib import get_logger
from authentik.core.models import Application
from authentik.providers.oauth2.constants import (
ACR_AUTHENTIK_DEFAULT,
GRANT_TYPE_AUTHORIZATION_CODE,
GRANT_TYPE_CLIENT_CREDENTIALS,
GRANT_TYPE_IMPLICIT,
GRANT_TYPE_PASSWORD,
GRANT_TYPE_REFRESH_TOKEN,
SCOPE_OPENID,
)
from authentik.providers.oauth2.models import OAuth2Provider, ResponseTypes, ScopeMapping
from authentik.providers.oauth2.utils import cors_allow
LOGGER = get_logger()
PLAN_CONTEXT_PARAMS = "params"
PLAN_CONTEXT_SCOPES = "scopes"
class ProviderInfoView(View):
"""OpenID-compliant Provider Info"""
provider: OAuth2Provider
def get_info(self, provider: OAuth2Provider) -> dict[str, Any]:
"""Get dictionary for OpenID Connect information"""
scopes = list(
ScopeMapping.objects.filter(provider=provider).values_list("scope_name", flat=True)
)
if SCOPE_OPENID not in scopes:
scopes.append(SCOPE_OPENID)
_, supported_alg = provider.get_jwt_key()
return {
"issuer": provider.get_issuer(self.request),
"authorization_endpoint": self.request.build_absolute_uri(
reverse("authentik_providers_oauth2:authorize")
),
"token_endpoint": self.request.build_absolute_uri(
reverse("authentik_providers_oauth2:token")
),
"userinfo_endpoint": self.request.build_absolute_uri(
reverse("authentik_providers_oauth2:userinfo")
),
"end_session_endpoint": self.request.build_absolute_uri(
reverse(
"authentik_core:if-session-end",
kwargs={"application_slug": provider.application.slug},
)
),
"introspection_endpoint": self.request.build_absolute_uri(
reverse("authentik_providers_oauth2:token-introspection")
),
"response_types_supported": [
ResponseTypes.CODE,
ResponseTypes.ID_TOKEN,
ResponseTypes.ID_TOKEN_TOKEN,
ResponseTypes.CODE_TOKEN,
ResponseTypes.CODE_ID_TOKEN,
ResponseTypes.CODE_ID_TOKEN_TOKEN,
],
"jwks_uri": self.request.build_absolute_uri(
reverse(
"authentik_providers_oauth2:jwks",
kwargs={"application_slug": provider.application.slug},
)
),
"grant_types_supported": [
GRANT_TYPE_AUTHORIZATION_CODE,
GRANT_TYPE_REFRESH_TOKEN,
GRANT_TYPE_IMPLICIT,
GRANT_TYPE_CLIENT_CREDENTIALS,
GRANT_TYPE_PASSWORD,
],
"id_token_signing_alg_values_supported": [supported_alg],
# See: http://openid.net/specs/openid-connect-core-1_0.html#SubjectIDTypes
"subject_types_supported": ["public"],
"token_endpoint_auth_methods_supported": [
"client_secret_post",
"client_secret_basic",
],
"acr_values_supported": [ACR_AUTHENTIK_DEFAULT],
"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 fixed Claim is "sub"
"claims_supported": ["sub"],
"claims_parameter_supported": False,
}
# pylint: disable=unused-argument
def get(self, request: HttpRequest, *args, **kwargs) -> HttpResponse:
"""OpenID-compliant Provider Info"""
return JsonResponse(self.get_info(self.provider), json_dumps_params={"indent": 2})
def dispatch(
self, request: HttpRequest, application_slug: str, *args: Any, **kwargs: Any
) -> HttpResponse:
# Since this view only supports get, we can statically set the CORS headers
application = get_object_or_404(Application, slug=application_slug)
self.provider: OAuth2Provider = get_object_or_404(
OAuth2Provider, pk=application.provider_id
)
response = super().dispatch(request, *args, **kwargs)
cors_allow(request, response, *self.provider.redirect_uris.split("\n"))
return response