1"""
2oauthlib.openid.connect.core.request_validator
3~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4"""
5import logging
6
7from oauthlib.oauth2.rfc6749.request_validator import (
8 RequestValidator as OAuth2RequestValidator,
9)
10
11log = logging.getLogger(__name__)
12
13
14class RequestValidator(OAuth2RequestValidator):
15
16 def get_authorization_code_scopes(self, client_id, code, redirect_uri, request):
17 """ Extracts scopes from saved authorization code.
18
19 The scopes returned by this method is used to route token requests
20 based on scopes passed to Authorization Code requests.
21
22 With that the token endpoint knows when to include OpenIDConnect
23 id_token in token response only based on authorization code scopes.
24
25 Only code param should be sufficient to retrieve grant code from
26 any storage you are using, `client_id` and `redirect_uri` can have a
27 blank value `""` don't forget to check it before using those values
28 in a select query if a database is used.
29
30 :param client_id: Unicode client identifier
31 :param code: Unicode authorization code grant
32 :param redirect_uri: Unicode absolute URI
33 :return: A list of scope
34
35 Method is used by:
36 - Authorization Token Grant Dispatcher
37 """
38 raise NotImplementedError('Subclasses must implement this method.')
39
40 def get_authorization_code_nonce(self, client_id, code, redirect_uri, request):
41 """ Extracts nonce from saved authorization code.
42
43 If present in the Authentication Request, Authorization
44 Servers MUST include a nonce Claim in the ID Token with the
45 Claim Value being the nonce value sent in the Authentication
46 Request. Authorization Servers SHOULD perform no other
47 processing on nonce values used. The nonce value is a
48 case-sensitive string.
49
50 Only code param should be sufficient to retrieve grant code from
51 any storage you are using. However, `client_id` and `redirect_uri`
52 have been validated and can be used also.
53
54 :param client_id: Unicode client identifier
55 :param code: Unicode authorization code grant
56 :param redirect_uri: Unicode absolute URI
57 :return: Unicode nonce
58
59 Method is used by:
60 - Authorization Token Grant Dispatcher
61 """
62 raise NotImplementedError('Subclasses must implement this method.')
63
64 def get_jwt_bearer_token(self, token, token_handler, request):
65 """Get JWT Bearer token or OpenID Connect ID token
66
67 If using OpenID Connect this SHOULD call `oauthlib.oauth2.RequestValidator.get_id_token`
68
69 :param token: A Bearer token dict
70 :param token_handler: the token handler (BearerToken class)
71 :param request: OAuthlib request.
72 :type request: oauthlib.common.Request
73 :return: The JWT Bearer token or OpenID Connect ID token (a JWS signed JWT)
74
75 Method is used by JWT Bearer and OpenID Connect tokens:
76 - JWTToken.create_token
77 """
78 raise NotImplementedError('Subclasses must implement this method.')
79
80 def get_id_token(self, token, token_handler, request):
81 """Get OpenID Connect ID token
82
83 This method is OPTIONAL and is NOT RECOMMENDED.
84 `finalize_id_token` SHOULD be implemented instead. However, if you
85 want a full control over the minting of the `id_token`, you
86 MAY want to override `get_id_token` instead of using
87 `finalize_id_token`.
88
89 In the OpenID Connect workflows when an ID Token is requested this method is called.
90 Subclasses should implement the construction, signing and optional encryption of the
91 ID Token as described in the OpenID Connect spec.
92
93 In addition to the standard OAuth2 request properties, the request may also contain
94 these OIDC specific properties which are useful to this method:
95
96 - nonce, if workflow is implicit or hybrid and it was provided
97 - claims, if provided to the original Authorization Code request
98
99 The token parameter is a dict which may contain an ``access_token`` entry, in which
100 case the resulting ID Token *should* include a calculated ``at_hash`` claim.
101
102 Similarly, when the request parameter has a ``code`` property defined, the ID Token
103 *should* include a calculated ``c_hash`` claim.
104
105 http://openid.net/specs/openid-connect-core-1_0.html (sections `3.1.3.6`_, `3.2.2.10`_, `3.3.2.11`_)
106
107 .. _`3.1.3.6`: http://openid.net/specs/openid-connect-core-1_0.html#CodeIDToken
108 .. _`3.2.2.10`: http://openid.net/specs/openid-connect-core-1_0.html#ImplicitIDToken
109 .. _`3.3.2.11`: http://openid.net/specs/openid-connect-core-1_0.html#HybridIDToken
110
111 :param token: A Bearer token dict
112 :param token_handler: the token handler (BearerToken class)
113 :param request: OAuthlib request.
114 :type request: oauthlib.common.Request
115 :return: The ID Token (a JWS signed JWT)
116 """
117 return None
118
119 def finalize_id_token(self, id_token, token, token_handler, request):
120 """Finalize OpenID Connect ID token & Sign or Encrypt.
121
122 In the OpenID Connect workflows when an ID Token is requested
123 this method is called. Subclasses should implement the
124 construction, signing and optional encryption of the ID Token
125 as described in the OpenID Connect spec.
126
127 The `id_token` parameter is a dict containing a couple of OIDC
128 technical fields related to the specification. Prepopulated
129 attributes are:
130
131 - `aud`, equals to `request.client_id`.
132 - `iat`, equals to current time.
133 - `nonce`, if present, is equals to the `nonce` from the
134 authorization request.
135 - `at_hash`, hash of `access_token`, if relevant.
136 - `c_hash`, hash of `code`, if relevant.
137
138 This method MUST provide required fields as below:
139
140 - `iss`, REQUIRED. Issuer Identifier for the Issuer of the response.
141 - `sub`, REQUIRED. Subject Identifier
142 - `exp`, REQUIRED. Expiration time on or after which the ID
143 Token MUST NOT be accepted by the RP when performing
144 authentication with the OP.
145
146 Additional claims must be added, note that `request.scope`
147 should be used to determine the list of claims.
148
149 More information can be found at `OpenID Connect Core#Claims`_
150
151 .. _`OpenID Connect Core#Claims`: https://openid.net/specs/openid-connect-core-1_0.html#Claims
152
153 :param id_token: A dict containing technical fields of id_token
154 :param token: A Bearer token dict
155 :param token_handler: the token handler (BearerToken class)
156 :param request: OAuthlib request.
157 :type request: oauthlib.common.Request
158 :return: The ID Token (a JWS signed JWT or JWE encrypted JWT)
159 """
160 raise NotImplementedError('Subclasses must implement this method.')
161
162 def validate_jwt_bearer_token(self, token, scopes, request):
163 """Ensure the JWT Bearer token or OpenID Connect ID token are valids and authorized access to scopes.
164
165 If using OpenID Connect this SHOULD call `oauthlib.oauth2.RequestValidator.get_id_token`
166
167 If not using OpenID Connect this can `return None` to avoid 5xx rather 401/3 response.
168
169 OpenID connect core 1.0 describe how to validate an id_token:
170 - http://openid.net/specs/openid-connect-core-1_0.html#IDTokenValidation
171 - http://openid.net/specs/openid-connect-core-1_0.html#ImplicitIDTValidation
172 - http://openid.net/specs/openid-connect-core-1_0.html#HybridIDTValidation
173 - http://openid.net/specs/openid-connect-core-1_0.html#HybridIDTValidation2
174
175 :param token: Unicode Bearer token
176 :param scopes: List of scopes (defined by you)
177 :param request: OAuthlib request.
178 :type request: oauthlib.common.Request
179 :rtype: True or False
180
181 Method is indirectly used by all core OpenID connect JWT token issuing grant types:
182 - Authorization Code Grant
183 - Implicit Grant
184 - Hybrid Grant
185 """
186 raise NotImplementedError('Subclasses must implement this method.')
187
188 def validate_id_token(self, token, scopes, request):
189 """Ensure the id token is valid and authorized access to scopes.
190
191 OpenID connect core 1.0 describe how to validate an id_token:
192 - http://openid.net/specs/openid-connect-core-1_0.html#IDTokenValidation
193 - http://openid.net/specs/openid-connect-core-1_0.html#ImplicitIDTValidation
194 - http://openid.net/specs/openid-connect-core-1_0.html#HybridIDTValidation
195 - http://openid.net/specs/openid-connect-core-1_0.html#HybridIDTValidation2
196
197 :param token: Unicode Bearer token
198 :param scopes: List of scopes (defined by you)
199 :param request: OAuthlib request.
200 :type request: oauthlib.common.Request
201 :rtype: True or False
202
203 Method is indirectly used by all core OpenID connect JWT token issuing grant types:
204 - Authorization Code Grant
205 - Implicit Grant
206 - Hybrid Grant
207 """
208 raise NotImplementedError('Subclasses must implement this method.')
209
210 def validate_silent_authorization(self, request):
211 """Ensure the logged in user has authorized silent OpenID authorization.
212
213 Silent OpenID authorization allows access tokens and id tokens to be
214 granted to clients without any user prompt or interaction.
215
216 :param request: OAuthlib request.
217 :type request: oauthlib.common.Request
218 :rtype: True or False
219
220 Method is used by:
221 - OpenIDConnectAuthCode
222 - OpenIDConnectImplicit
223 - OpenIDConnectHybrid
224 """
225 raise NotImplementedError('Subclasses must implement this method.')
226
227 def validate_silent_login(self, request):
228 """Ensure session user has authorized silent OpenID login.
229
230 If no user is logged in or has not authorized silent login, this
231 method should return False.
232
233 If the user is logged in but associated with multiple accounts and
234 not selected which one to link to the token then this method should
235 raise an oauthlib.oauth2.AccountSelectionRequired error.
236
237 :param request: OAuthlib request.
238 :type request: oauthlib.common.Request
239 :rtype: True or False
240
241 Method is used by:
242 - OpenIDConnectAuthCode
243 - OpenIDConnectImplicit
244 - OpenIDConnectHybrid
245 """
246 raise NotImplementedError('Subclasses must implement this method.')
247
248 def validate_user_match(self, id_token_hint, scopes, claims, request):
249 """Ensure client supplied user id hint matches session user.
250
251 If the sub claim or id_token_hint is supplied then the session
252 user must match the given ID.
253
254 :param id_token_hint: User identifier string.
255 :param scopes: List of OAuth 2 scopes and OpenID claims (strings).
256 :param claims: OpenID Connect claims dict.
257 :param request: OAuthlib request.
258 :type request: oauthlib.common.Request
259 :rtype: True or False
260
261 Method is used by:
262 - OpenIDConnectAuthCode
263 - OpenIDConnectImplicit
264 - OpenIDConnectHybrid
265 """
266 raise NotImplementedError('Subclasses must implement this method.')
267
268 def get_userinfo_claims(self, request):
269 """Return the UserInfo claims in JSON or Signed or Encrypted.
270
271 The UserInfo Claims MUST be returned as the members of a JSON object
272 unless a signed or encrypted response was requested during Client
273 Registration. The Claims defined in Section 5.1 can be returned, as can
274 additional Claims not specified there.
275
276 For privacy reasons, OpenID Providers MAY elect to not return values for
277 some requested Claims.
278
279 If a Claim is not returned, that Claim Name SHOULD be omitted from the
280 JSON object representing the Claims; it SHOULD NOT be present with a
281 null or empty string value.
282
283 The sub (subject) Claim MUST always be returned in the UserInfo
284 Response.
285
286 Upon receipt of the UserInfo Request, the UserInfo Endpoint MUST return
287 the JSON Serialization of the UserInfo Response as in Section 13.3 in
288 the HTTP response body unless a different format was specified during
289 Registration [OpenID.Registration].
290
291 If the UserInfo Response is signed and/or encrypted, then the Claims are
292 returned in a JWT and the content-type MUST be application/jwt. The
293 response MAY be encrypted without also being signed. If both signing and
294 encryption are requested, the response MUST be signed then encrypted,
295 with the result being a Nested JWT, as defined in [JWT].
296
297 If signed, the UserInfo Response SHOULD contain the Claims iss (issuer)
298 and aud (audience) as members. The iss value SHOULD be the OP's Issuer
299 Identifier URL. The aud value SHOULD be or include the RP's Client ID
300 value.
301
302 :param request: OAuthlib request.
303 :type request: oauthlib.common.Request
304 :rtype: Claims as a dict OR JWT/JWS/JWE as a string
305
306 Method is used by:
307 UserInfoEndpoint
308 """
309
310 def refresh_id_token(self, request):
311 """Whether the id token should be refreshed. Default, True
312
313 :param request: OAuthlib request.
314 :type request: oauthlib.common.Request
315 :rtype: True or False
316
317 Method is used by:
318 RefreshTokenGrant
319 """
320 return True