okta-client-python 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- okta_client/__init__.py +20 -0
- okta_client/authfoundation/__init__.py +197 -0
- okta_client/authfoundation/authentication.py +247 -0
- okta_client/authfoundation/coalesced_result.py +113 -0
- okta_client/authfoundation/codable.py +72 -0
- okta_client/authfoundation/expires.py +49 -0
- okta_client/authfoundation/key_provider.py +130 -0
- okta_client/authfoundation/networking/__init__.py +56 -0
- okta_client/authfoundation/networking/body.py +46 -0
- okta_client/authfoundation/networking/client.py +200 -0
- okta_client/authfoundation/networking/types.py +293 -0
- okta_client/authfoundation/oauth2/__init__.py +104 -0
- okta_client/authfoundation/oauth2/claims.py +44 -0
- okta_client/authfoundation/oauth2/client.py +402 -0
- okta_client/authfoundation/oauth2/client_authorization.py +172 -0
- okta_client/authfoundation/oauth2/config.py +298 -0
- okta_client/authfoundation/oauth2/errors.py +32 -0
- okta_client/authfoundation/oauth2/jwt_bearer_claims.py +59 -0
- okta_client/authfoundation/oauth2/jwt_bearer_utils.py +30 -0
- okta_client/authfoundation/oauth2/jwt_context.py +52 -0
- okta_client/authfoundation/oauth2/jwt_token.py +214 -0
- okta_client/authfoundation/oauth2/models.py +198 -0
- okta_client/authfoundation/oauth2/parameters.py +36 -0
- okta_client/authfoundation/oauth2/refresh_token.py +165 -0
- okta_client/authfoundation/oauth2/request_protocols.py +174 -0
- okta_client/authfoundation/oauth2/requests/__init__.py +37 -0
- okta_client/authfoundation/oauth2/requests/introspect.py +50 -0
- okta_client/authfoundation/oauth2/requests/jwks.py +44 -0
- okta_client/authfoundation/oauth2/requests/oauth_authorization_server.py +44 -0
- okta_client/authfoundation/oauth2/requests/openid_configuration.py +47 -0
- okta_client/authfoundation/oauth2/requests/revoke.py +54 -0
- okta_client/authfoundation/oauth2/requests/user_info.py +37 -0
- okta_client/authfoundation/oauth2/utils.py +25 -0
- okta_client/authfoundation/oauth2/validation_protocols.py +33 -0
- okta_client/authfoundation/oauth2/validator_registry.py +64 -0
- okta_client/authfoundation/oauth2/validators/token_hash.py +37 -0
- okta_client/authfoundation/oauth2/validators/token_validator.py +26 -0
- okta_client/authfoundation/time_coordinator.py +57 -0
- okta_client/authfoundation/token.py +201 -0
- okta_client/authfoundation/user_agent.py +80 -0
- okta_client/authfoundation/utils.py +63 -0
- okta_client/browser_signin/__init__.py +11 -0
- okta_client/directauth/__init__.py +11 -0
- okta_client/oauth2auth/__init__.py +63 -0
- okta_client/oauth2auth/authorization_code.py +594 -0
- okta_client/oauth2auth/cross_app.py +626 -0
- okta_client/oauth2auth/jwt_bearer.py +182 -0
- okta_client/oauth2auth/resource_owner.py +159 -0
- okta_client/oauth2auth/token_exchange.py +380 -0
- okta_client/oauth2auth/utils.py +87 -0
- okta_client/py.typed +0 -0
- okta_client_python-0.1.0.dist-info/METADATA +936 -0
- okta_client_python-0.1.0.dist-info/RECORD +56 -0
- okta_client_python-0.1.0.dist-info/WHEEL +5 -0
- okta_client_python-0.1.0.dist-info/licenses/LICENSE +171 -0
- okta_client_python-0.1.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,293 @@
|
|
|
1
|
+
# The Okta software accompanied by this notice is provided pursuant to the following terms:
|
|
2
|
+
# Copyright © 2026-Present, Okta, Inc.
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the
|
|
4
|
+
# License.
|
|
5
|
+
# You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0.
|
|
6
|
+
# Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an
|
|
7
|
+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
8
|
+
# See the License for the specific language governing permissions and limitations under the License.
|
|
9
|
+
# coding: utf-8
|
|
10
|
+
|
|
11
|
+
from __future__ import annotations
|
|
12
|
+
|
|
13
|
+
from collections.abc import Iterator, Mapping, Sequence
|
|
14
|
+
from dataclasses import dataclass
|
|
15
|
+
from datetime import datetime
|
|
16
|
+
from enum import Enum
|
|
17
|
+
from typing import (
|
|
18
|
+
TYPE_CHECKING,
|
|
19
|
+
Any,
|
|
20
|
+
Generic,
|
|
21
|
+
Protocol,
|
|
22
|
+
TypeVar,
|
|
23
|
+
cast,
|
|
24
|
+
runtime_checkable,
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
if TYPE_CHECKING:
|
|
28
|
+
from .client import APIClient
|
|
29
|
+
|
|
30
|
+
T = TypeVar("T")
|
|
31
|
+
ListenerT = TypeVar("ListenerT")
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class APIContentType(str, Enum):
|
|
35
|
+
"""Common content types for request and response bodies."""
|
|
36
|
+
JSON = "application/json"
|
|
37
|
+
FORM_URLENCODED = "application/x-www-form-urlencoded"
|
|
38
|
+
TEXT = "text/plain"
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
class APIRequestMethod(str, Enum):
|
|
42
|
+
"""HTTP request methods."""
|
|
43
|
+
GET = "GET"
|
|
44
|
+
POST = "POST"
|
|
45
|
+
PUT = "PUT"
|
|
46
|
+
PATCH = "PATCH"
|
|
47
|
+
DELETE = "DELETE"
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
@runtime_checkable
|
|
51
|
+
class RequestValueConvertible(Protocol):
|
|
52
|
+
"""Protocol for values that can serialize themselves to a string."""
|
|
53
|
+
|
|
54
|
+
def to_request_value(self) -> str:
|
|
55
|
+
"""Return a string representation for request serialization."""
|
|
56
|
+
...
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
RequestValue = str | int | float | bool | Sequence[str] | RequestValueConvertible | None
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
@runtime_checkable
|
|
63
|
+
class APIRequestBody(Protocol):
|
|
64
|
+
"""Protocol for requests that supply body parameters."""
|
|
65
|
+
@property
|
|
66
|
+
def body_parameters(self) -> Mapping[str, RequestValue]:
|
|
67
|
+
"""Body parameters to serialize based on content type."""
|
|
68
|
+
...
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
@runtime_checkable
|
|
72
|
+
class APIAuthorization(Protocol):
|
|
73
|
+
"""Protocol for objects that authorize an outgoing HTTP request."""
|
|
74
|
+
def authorize(self, request: HTTPRequest) -> HTTPRequest:
|
|
75
|
+
"""Apply authorization to the request and return it."""
|
|
76
|
+
...
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
class APIParsingContext(Protocol):
|
|
80
|
+
"""Marker protocol for parsing hints."""
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
@dataclass(frozen=True)
|
|
84
|
+
class APIRateLimit:
|
|
85
|
+
"""Rate-limit metadata extracted from responses."""
|
|
86
|
+
limit: int
|
|
87
|
+
remaining: int
|
|
88
|
+
reset: datetime
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
class BackoffStrategy(Protocol):
|
|
92
|
+
"""Protocol for retry backoff strategies."""
|
|
93
|
+
def delay_for_attempt(self, attempt: int) -> float:
|
|
94
|
+
"""Return a delay in seconds for the given attempt."""
|
|
95
|
+
...
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
@dataclass(frozen=True)
|
|
99
|
+
class APIRetry:
|
|
100
|
+
"""Retry policy returned by listeners or defaults."""
|
|
101
|
+
kind: str
|
|
102
|
+
maximum_count: int | None = None
|
|
103
|
+
backoff_strategy: BackoffStrategy | None = None
|
|
104
|
+
|
|
105
|
+
@classmethod
|
|
106
|
+
def do_not_retry(cls) -> APIRetry:
|
|
107
|
+
"""Return a policy that disables retries."""
|
|
108
|
+
return cls(kind="do_not_retry")
|
|
109
|
+
|
|
110
|
+
@classmethod
|
|
111
|
+
def retry(cls, maximum_count: int, backoff_strategy: BackoffStrategy | None = None) -> APIRetry:
|
|
112
|
+
"""Return a policy that retries up to a maximum count."""
|
|
113
|
+
return cls(kind="retry", maximum_count=maximum_count, backoff_strategy=backoff_strategy)
|
|
114
|
+
|
|
115
|
+
@classmethod
|
|
116
|
+
def default(cls) -> APIRetry:
|
|
117
|
+
"""Return the SDK default retry policy."""
|
|
118
|
+
return cls(kind="default")
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
@dataclass(frozen=True)
|
|
122
|
+
class RawResponse:
|
|
123
|
+
"""Raw response data returned by the network interface."""
|
|
124
|
+
status_code: int
|
|
125
|
+
headers: Mapping[str, str]
|
|
126
|
+
body: bytes
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
@dataclass
|
|
130
|
+
class HTTPRequest:
|
|
131
|
+
"""HTTP request envelope used by the network interface."""
|
|
132
|
+
method: APIRequestMethod
|
|
133
|
+
url: str
|
|
134
|
+
headers: dict[str, str]
|
|
135
|
+
body: bytes | None
|
|
136
|
+
timeout: float | None
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
@dataclass(frozen=True)
|
|
140
|
+
class APIResponse(Generic[T]):
|
|
141
|
+
"""Parsed response payload plus response metadata."""
|
|
142
|
+
result: T
|
|
143
|
+
status_code: int
|
|
144
|
+
headers: Mapping[str, str]
|
|
145
|
+
request_id: str | None = None
|
|
146
|
+
rate_limit: APIRateLimit | None = None
|
|
147
|
+
links: Mapping[str, str] | None = None
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
class APIRequest(Generic[T], Protocol):
|
|
151
|
+
"""Protocol describing a transport-agnostic API request."""
|
|
152
|
+
@property
|
|
153
|
+
def http_method(self) -> APIRequestMethod:
|
|
154
|
+
...
|
|
155
|
+
|
|
156
|
+
@property
|
|
157
|
+
def url(self) -> str:
|
|
158
|
+
...
|
|
159
|
+
|
|
160
|
+
@property
|
|
161
|
+
def query(self) -> Mapping[str, RequestValue] | None:
|
|
162
|
+
...
|
|
163
|
+
|
|
164
|
+
@property
|
|
165
|
+
def headers(self) -> Mapping[str, RequestValue] | None:
|
|
166
|
+
...
|
|
167
|
+
|
|
168
|
+
@property
|
|
169
|
+
def accepts_type(self) -> APIContentType | None:
|
|
170
|
+
...
|
|
171
|
+
|
|
172
|
+
@property
|
|
173
|
+
def content_type(self) -> APIContentType | None:
|
|
174
|
+
...
|
|
175
|
+
|
|
176
|
+
@property
|
|
177
|
+
def authorization(self) -> APIAuthorization | None:
|
|
178
|
+
...
|
|
179
|
+
|
|
180
|
+
@property
|
|
181
|
+
def timeout(self) -> float | None:
|
|
182
|
+
...
|
|
183
|
+
|
|
184
|
+
def body(self) -> bytes | None:
|
|
185
|
+
"""Return the serialized request body, if any."""
|
|
186
|
+
...
|
|
187
|
+
|
|
188
|
+
def parse_response(self, response: RawResponse, parsing_context: APIParsingContext | None = None) -> T:
|
|
189
|
+
"""Parse the raw response into a typed result."""
|
|
190
|
+
...
|
|
191
|
+
|
|
192
|
+
def build_http_request(self, client: APIClient) -> HTTPRequest:
|
|
193
|
+
"""Build a platform HTTP request using the provided client."""
|
|
194
|
+
return client.build_http_request(cast("APIRequest[Any]", self))
|
|
195
|
+
|
|
196
|
+
def send(self, client: APIClient, parsing_context: APIParsingContext | None = None) -> APIResponse[T]:
|
|
197
|
+
"""Send the request using the provided client."""
|
|
198
|
+
return client.send(cast("APIRequest[T]", self), parsing_context=parsing_context)
|
|
199
|
+
|
|
200
|
+
class BaseAPIRequest(Generic[T]):
|
|
201
|
+
"""Base request with standard optional defaults."""
|
|
202
|
+
|
|
203
|
+
@property
|
|
204
|
+
def query(self) -> Mapping[str, RequestValue] | None:
|
|
205
|
+
return None
|
|
206
|
+
|
|
207
|
+
@property
|
|
208
|
+
def headers(self) -> Mapping[str, RequestValue] | None:
|
|
209
|
+
return None
|
|
210
|
+
|
|
211
|
+
@property
|
|
212
|
+
def accepts_type(self) -> APIContentType | None:
|
|
213
|
+
return None
|
|
214
|
+
|
|
215
|
+
@property
|
|
216
|
+
def content_type(self) -> APIContentType | None:
|
|
217
|
+
return None
|
|
218
|
+
|
|
219
|
+
@property
|
|
220
|
+
def authorization(self) -> APIAuthorization | None:
|
|
221
|
+
return None
|
|
222
|
+
|
|
223
|
+
@property
|
|
224
|
+
def timeout(self) -> float | None:
|
|
225
|
+
return None
|
|
226
|
+
|
|
227
|
+
def body(self) -> bytes | None:
|
|
228
|
+
return None
|
|
229
|
+
|
|
230
|
+
def build_http_request(self, client: APIClient) -> HTTPRequest:
|
|
231
|
+
"""Build a platform HTTP request using the provided client."""
|
|
232
|
+
return client.build_http_request(cast("APIRequest[Any]", self))
|
|
233
|
+
|
|
234
|
+
def send(self, client: APIClient, parsing_context: APIParsingContext | None = None) -> APIResponse[T]:
|
|
235
|
+
"""Send the request using the provided client."""
|
|
236
|
+
return client.send(cast("APIRequest[T]", self), parsing_context=parsing_context)
|
|
237
|
+
|
|
238
|
+
|
|
239
|
+
class NetworkInterface(Protocol):
|
|
240
|
+
"""Protocol for transport implementations used by APIClient."""
|
|
241
|
+
def send(self, request: HTTPRequest) -> RawResponse:
|
|
242
|
+
"""Send an HTTP request and return the raw response."""
|
|
243
|
+
...
|
|
244
|
+
|
|
245
|
+
|
|
246
|
+
@runtime_checkable
|
|
247
|
+
class APIClientListener(Protocol):
|
|
248
|
+
"""Listener for request lifecycle events."""
|
|
249
|
+
def will_send(self, client: APIClient, request: HTTPRequest) -> None:
|
|
250
|
+
"""Called before a request is sent."""
|
|
251
|
+
...
|
|
252
|
+
|
|
253
|
+
def did_send(self, client: APIClient, request: HTTPRequest, response: APIResponse[Any]) -> None:
|
|
254
|
+
"""Called when a response is received successfully."""
|
|
255
|
+
...
|
|
256
|
+
|
|
257
|
+
def did_send_error(self, client: APIClient, request: HTTPRequest, error: Exception) -> None:
|
|
258
|
+
"""Called when a request fails with an error."""
|
|
259
|
+
...
|
|
260
|
+
|
|
261
|
+
def should_retry(self, client: APIClient, request: HTTPRequest, rate_limit: APIRateLimit | None) -> APIRetry:
|
|
262
|
+
"""Return a retry policy for the given request."""
|
|
263
|
+
...
|
|
264
|
+
|
|
265
|
+
|
|
266
|
+
class ListenerCollection(Generic[ListenerT]):
|
|
267
|
+
"""Thread-unsafe collection of listeners with add/remove semantics."""
|
|
268
|
+
def __init__(self) -> None:
|
|
269
|
+
self._listeners: list[ListenerT] = []
|
|
270
|
+
|
|
271
|
+
def add(self, listener: ListenerT) -> None:
|
|
272
|
+
"""Add a listener if it is not already registered."""
|
|
273
|
+
if listener not in self._listeners:
|
|
274
|
+
self._listeners.append(listener)
|
|
275
|
+
|
|
276
|
+
def remove(self, listener: ListenerT) -> None:
|
|
277
|
+
"""Remove a listener if present."""
|
|
278
|
+
if listener in self._listeners:
|
|
279
|
+
self._listeners.remove(listener)
|
|
280
|
+
|
|
281
|
+
def __iter__(self) -> Iterator[ListenerT]:
|
|
282
|
+
"""Iterate over registered listeners."""
|
|
283
|
+
return iter(self._listeners)
|
|
284
|
+
|
|
285
|
+
|
|
286
|
+
@dataclass(frozen=True)
|
|
287
|
+
class APIClientConfiguration:
|
|
288
|
+
"""Immutable configuration for APIClient defaults."""
|
|
289
|
+
base_url: str
|
|
290
|
+
user_agent: str
|
|
291
|
+
additional_http_headers: Mapping[str, str] | None = None
|
|
292
|
+
request_id_header: str | None = None
|
|
293
|
+
timeout: float | None = None
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
# The Okta software accompanied by this notice is provided pursuant to the following terms:
|
|
2
|
+
# Copyright © 2026-Present, Okta, Inc.
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the
|
|
4
|
+
# License.
|
|
5
|
+
# You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0.
|
|
6
|
+
# Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an
|
|
7
|
+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
8
|
+
# See the License for the specific language governing permissions and limitations under the License.
|
|
9
|
+
# coding: utf-8
|
|
10
|
+
|
|
11
|
+
from __future__ import annotations
|
|
12
|
+
|
|
13
|
+
from .claims import HasClaims, IdTokenClaim
|
|
14
|
+
from .client_authorization import (
|
|
15
|
+
ClientAssertionAuthorization,
|
|
16
|
+
ClientAuthorization,
|
|
17
|
+
ClientIdAuthorization,
|
|
18
|
+
ClientSecretAuthorization,
|
|
19
|
+
)
|
|
20
|
+
from .config import (
|
|
21
|
+
ConfigurationError,
|
|
22
|
+
ConfigurationFileNotFoundError,
|
|
23
|
+
ConfigurationParseError,
|
|
24
|
+
InvalidConfigurationError,
|
|
25
|
+
OAuth2ClientConfiguration,
|
|
26
|
+
)
|
|
27
|
+
from .errors import OAuth2Error
|
|
28
|
+
from .jwt_bearer_claims import JWTBearerClaims
|
|
29
|
+
from .jwt_context import JWTUsageContext, JWTValidationContext
|
|
30
|
+
from .jwt_token import JWT, JWTType
|
|
31
|
+
from .models import JWK, JWKS, OpenIdConfiguration, TokenInfo, UserInfo
|
|
32
|
+
from .parameters import OAuth2APIRequestCategory, ProvidesOAuth2Parameters
|
|
33
|
+
from .request_protocols import (
|
|
34
|
+
IDTokenValidatorContext,
|
|
35
|
+
OAuth2APIRequest,
|
|
36
|
+
OAuth2TokenRequest,
|
|
37
|
+
OAuth2TokenRequestDefaults,
|
|
38
|
+
)
|
|
39
|
+
from .requests import (
|
|
40
|
+
IntrospectRequest,
|
|
41
|
+
JWKSRequest,
|
|
42
|
+
OpenIDConfigurationRequest,
|
|
43
|
+
RevokeRequest,
|
|
44
|
+
UserInfoRequest,
|
|
45
|
+
)
|
|
46
|
+
from .utils import NullIDTokenValidatorContext
|
|
47
|
+
from .validation_protocols import TokenHashValidator, TokenValidator
|
|
48
|
+
from .validator_registry import (
|
|
49
|
+
get_access_token_validator,
|
|
50
|
+
get_device_secret_validator,
|
|
51
|
+
get_token_validator,
|
|
52
|
+
set_access_token_validator,
|
|
53
|
+
set_device_secret_validator,
|
|
54
|
+
set_token_validator,
|
|
55
|
+
)
|
|
56
|
+
from .validators.token_hash import DefaultTokenHashValidator
|
|
57
|
+
from .validators.token_validator import DefaultTokenValidator
|
|
58
|
+
|
|
59
|
+
__all__ = [
|
|
60
|
+
"JWK",
|
|
61
|
+
"JWKS",
|
|
62
|
+
"JWT",
|
|
63
|
+
"ClientAssertionAuthorization",
|
|
64
|
+
"ClientAuthorization",
|
|
65
|
+
"ClientIdAuthorization",
|
|
66
|
+
"ClientSecretAuthorization",
|
|
67
|
+
"ConfigurationError",
|
|
68
|
+
"ConfigurationFileNotFoundError",
|
|
69
|
+
"ConfigurationParseError",
|
|
70
|
+
"DefaultTokenHashValidator",
|
|
71
|
+
"DefaultTokenValidator",
|
|
72
|
+
"HasClaims",
|
|
73
|
+
"IDTokenValidatorContext",
|
|
74
|
+
"IdTokenClaim",
|
|
75
|
+
"IntrospectRequest",
|
|
76
|
+
"InvalidConfigurationError",
|
|
77
|
+
"JWKSRequest",
|
|
78
|
+
"JWTBearerClaims",
|
|
79
|
+
"JWTType",
|
|
80
|
+
"JWTUsageContext",
|
|
81
|
+
"JWTValidationContext",
|
|
82
|
+
"NullIDTokenValidatorContext",
|
|
83
|
+
"OAuth2APIRequest",
|
|
84
|
+
"OAuth2APIRequestCategory",
|
|
85
|
+
"OAuth2ClientConfiguration",
|
|
86
|
+
"OAuth2Error",
|
|
87
|
+
"OAuth2TokenRequest",
|
|
88
|
+
"OAuth2TokenRequestDefaults",
|
|
89
|
+
"OpenIDConfigurationRequest",
|
|
90
|
+
"OpenIdConfiguration",
|
|
91
|
+
"ProvidesOAuth2Parameters",
|
|
92
|
+
"RevokeRequest",
|
|
93
|
+
"TokenHashValidator",
|
|
94
|
+
"TokenInfo",
|
|
95
|
+
"TokenValidator",
|
|
96
|
+
"UserInfo",
|
|
97
|
+
"UserInfoRequest",
|
|
98
|
+
"get_access_token_validator",
|
|
99
|
+
"get_device_secret_validator",
|
|
100
|
+
"get_token_validator",
|
|
101
|
+
"set_access_token_validator",
|
|
102
|
+
"set_device_secret_validator",
|
|
103
|
+
"set_token_validator",
|
|
104
|
+
]
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# The Okta software accompanied by this notice is provided pursuant to the following terms:
|
|
2
|
+
# Copyright © 2026-Present, Okta, Inc.
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the
|
|
4
|
+
# License.
|
|
5
|
+
# You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0.
|
|
6
|
+
# Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an
|
|
7
|
+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
8
|
+
# See the License for the specific language governing permissions and limitations under the License.
|
|
9
|
+
# coding: utf-8
|
|
10
|
+
|
|
11
|
+
from __future__ import annotations
|
|
12
|
+
|
|
13
|
+
from enum import Enum
|
|
14
|
+
from typing import Any, Generic, Protocol, TypeVar, runtime_checkable
|
|
15
|
+
|
|
16
|
+
ClaimEnum = TypeVar("ClaimEnum", bound=Enum, contravariant=True)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
@runtime_checkable
|
|
20
|
+
class HasClaims(Protocol, Generic[ClaimEnum]):
|
|
21
|
+
"""Protocol for objects exposing typed claim values."""
|
|
22
|
+
|
|
23
|
+
def claim(self, claim: ClaimEnum) -> Any:
|
|
24
|
+
...
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class IdTokenClaim(str, Enum):
|
|
28
|
+
"""Standard OpenID Connect ID token claims."""
|
|
29
|
+
|
|
30
|
+
ISSUER = "iss"
|
|
31
|
+
SUBJECT = "sub"
|
|
32
|
+
AUDIENCE = "aud"
|
|
33
|
+
EXPIRATION = "exp"
|
|
34
|
+
ISSUED_AT = "iat"
|
|
35
|
+
AUTH_TIME = "auth_time"
|
|
36
|
+
NONCE = "nonce"
|
|
37
|
+
AT_HASH = "at_hash"
|
|
38
|
+
DS_HASH = "ds_hash"
|
|
39
|
+
ACR = "acr"
|
|
40
|
+
AMR = "amr"
|
|
41
|
+
AZP = "azp"
|
|
42
|
+
|
|
43
|
+
def key(self) -> str:
|
|
44
|
+
return str(self.value)
|