13
13
# under the License.
14
14
from typing import Any , Dict , List , Union , TypeVar , Callable , Optional
15
15
16
+ from supertokens_python .exceptions import SuperTokensError
17
+ from supertokens_python .framework .request import BaseRequest
16
18
from supertokens_python .recipe .openid .interfaces import (
17
19
GetOpenIdDiscoveryConfigurationResult ,
18
20
)
26
28
ClaimsValidationResult ,
27
29
JSONObject ,
28
30
GetClaimValueOkResult ,
31
+ GetSessionUnauthorizedErrorResult ,
32
+ GetSessionTryRefreshTokenErrorResult ,
33
+ GetSessionClaimValidationErrorResult ,
34
+ GetSessionClaimValidationErrorResponseObject ,
35
+ CreateNewSessionResult ,
36
+ GetSessionOkResult ,
37
+ RefreshSessionOkResult ,
38
+ RefreshSessionUnauthorizedResult ,
39
+ RefreshSessionTokenTheftErrorResult ,
29
40
)
30
41
from supertokens_python .recipe .session .recipe import SessionRecipe
42
+ from supertokens_python .recipe .session .session_request_functions import (
43
+ get_session_from_request ,
44
+ create_new_session_in_request ,
45
+ refresh_session_in_request ,
46
+ )
31
47
from supertokens_python .types import MaybeAwaitable
32
48
from supertokens_python .utils import FRAMEWORKS , resolve , deprecated_warn
49
+ from ..exceptions import InvalidClaimsError
33
50
from ..utils import get_required_claim_validators
34
51
from ...jwt .interfaces import (
35
52
CreateJwtOkResult ,
@@ -54,6 +71,36 @@ async def create_new_session(
54
71
if access_token_payload is None :
55
72
access_token_payload = {}
56
73
74
+ recipe_instance = SessionRecipe .get_instance ()
75
+ config = recipe_instance .config
76
+ app_info = recipe_instance .app_info
77
+
78
+ return await create_new_session_in_request (
79
+ request ,
80
+ user_context ,
81
+ recipe_instance ,
82
+ access_token_payload ,
83
+ user_id ,
84
+ config ,
85
+ app_info ,
86
+ session_data_in_database ,
87
+ )
88
+
89
+
90
+ async def create_new_session_without_request_response (
91
+ user_id : str ,
92
+ access_token_payload : Union [Dict [str , Any ], None ] = None ,
93
+ session_data_in_database : Union [Dict [str , Any ], None ] = None ,
94
+ disable_anti_csrf : bool = False ,
95
+ user_context : Union [None , Dict [str , Any ]] = None ,
96
+ ) -> CreateNewSessionResult :
97
+ if user_context is None :
98
+ user_context = {}
99
+ if session_data_in_database is None :
100
+ session_data_in_database = {}
101
+ if access_token_payload is None :
102
+ access_token_payload = {}
103
+
57
104
claims_added_by_other_recipes = (
58
105
SessionRecipe .get_instance ().get_claims_added_by_other_recipes ()
59
106
)
@@ -63,16 +110,11 @@ async def create_new_session(
63
110
update = await claim .build (user_id , user_context )
64
111
final_access_token_payload = {** final_access_token_payload , ** update }
65
112
66
- if not hasattr (request , "wrapper_used" ) or not request .wrapper_used :
67
- request = FRAMEWORKS [
68
- SessionRecipe .get_instance ().app_info .framework
69
- ].wrap_request (request )
70
-
71
113
return await SessionRecipe .get_instance ().recipe_implementation .create_new_session (
72
- request ,
73
114
user_id ,
74
115
final_access_token_payload ,
75
116
session_data_in_database ,
117
+ disable_anti_csrf ,
76
118
user_context = user_context ,
77
119
)
78
120
@@ -236,9 +278,10 @@ async def remove_claim(
236
278
237
279
238
280
async def get_session (
239
- request : Any ,
240
- anti_csrf_check : Union [bool , None ] = None ,
241
- session_required : bool = True ,
281
+ request : BaseRequest ,
282
+ session_required : Optional [bool ] = None ,
283
+ anti_csrf_check : Optional [bool ] = None ,
284
+ check_database : Optional [bool ] = None ,
242
285
override_global_claim_validators : Optional [
243
286
Callable [
244
287
[List [SessionClaimValidator ], SessionContainer , Dict [str , Any ]],
@@ -249,40 +292,135 @@ async def get_session(
249
292
) -> Union [SessionContainer , None ]:
250
293
if user_context is None :
251
294
user_context = {}
252
- if not hasattr (request , "wrapper_used" ) or not request .wrapper_used :
253
- request = FRAMEWORKS [
254
- SessionRecipe .get_instance ().app_info .framework
255
- ].wrap_request (request )
256
295
257
- session_recipe_impl = SessionRecipe .get_instance ().recipe_implementation
258
- session = await session_recipe_impl .get_session (
296
+ recipe_instance = SessionRecipe .get_instance ()
297
+ recipe_interface_impl = recipe_instance .recipe_implementation
298
+ config = recipe_instance .config
299
+
300
+ return await get_session_from_request (
259
301
request ,
302
+ config ,
303
+ recipe_interface_impl ,
304
+ session_required = session_required ,
305
+ anti_csrf_check = anti_csrf_check ,
306
+ check_database = check_database ,
307
+ override_global_claim_validators = override_global_claim_validators ,
308
+ user_context = user_context ,
309
+ )
310
+
311
+
312
+ async def get_session_without_request_response (
313
+ access_token : str ,
314
+ anti_csrf_token : Optional [str ] = None ,
315
+ anti_csrf_check : Optional [bool ] = None ,
316
+ check_database : Optional [bool ] = None ,
317
+ override_global_claim_validators : Optional [
318
+ Callable [
319
+ [List [SessionClaimValidator ], SessionContainer , Dict [str , Any ]],
320
+ MaybeAwaitable [List [SessionClaimValidator ]],
321
+ ]
322
+ ] = None ,
323
+ user_context : Union [None , Dict [str , Any ]] = None ,
324
+ ) -> Union [
325
+ GetSessionOkResult ,
326
+ GetSessionUnauthorizedErrorResult ,
327
+ GetSessionTryRefreshTokenErrorResult ,
328
+ GetSessionClaimValidationErrorResult ,
329
+ ]:
330
+ """Tries to validate an access token and build a Session object from it.
331
+
332
+ Notes about anti-csrf checking:
333
+ - if the `antiCsrf` is set to VIA_HEADER in the Session recipe config you have to handle anti-csrf checking before calling this function and set antiCsrfCheck to false in the options.
334
+ - you can disable anti-csrf checks by setting antiCsrf to NONE in the Session recipe config. We only recommend this if you are always getting the access-token from the Authorization header.
335
+ - if the antiCsrf check fails the returned status will be TRY_REFRESH_TOKEN_ERROR
336
+
337
+ Args:
338
+ - access_token: The access token extracted from the authorization header or cookies
339
+ - anti_csrf_token: The anti-csrf token extracted from the authorization header or cookies. Can be undefined if antiCsrfCheck is false
340
+ - anti_csrf_check: If true, anti-csrf checking will be done. If false, it will be skipped. Defaults behaviour to check.
341
+ - check_database: If true, the session will be checked in the database. If false, it will be skipped. Defaults behaviour to skip.
342
+ - override_global_claim_validators: Alter the
343
+ - user_context: user context
344
+
345
+ Returned values:
346
+ - GetSessionOkResult: The session was successfully validated, including claim validation
347
+ - GetSessionClaimValidationErrorResult: While the access token is valid, one or more claim validators have failed. Our frontend SDKs expect a 403 response the contents matching the value returned from this function.
348
+ - GetSessionTryRefreshTokenErrorResult: This means, that the access token structure was valid, but it didn't pass validation for some reason and the user should call the refresh API.
349
+ - You can send a 401 response to trigger this behaviour if you are using our frontend SDKs
350
+ - GetSessionUnauthorizedErrorResult: This means that the access token likely doesn't belong to a SuperTokens session. If this is unexpected, it's best handled by sending a 401 response.
351
+ """
352
+ if user_context is None :
353
+ user_context = {}
354
+
355
+ recipe_interface_impl = SessionRecipe .get_instance ().recipe_implementation
356
+
357
+ res = await recipe_interface_impl .get_session (
358
+ access_token ,
359
+ anti_csrf_token ,
260
360
anti_csrf_check ,
261
- session_required ,
361
+ check_database ,
362
+ override_global_claim_validators ,
262
363
user_context ,
263
364
)
264
365
265
- if session is not None :
366
+ if isinstance ( res , GetSessionOkResult ) :
266
367
claim_validators = await get_required_claim_validators (
267
- session , override_global_claim_validators , user_context
368
+ res . session , override_global_claim_validators , user_context
268
369
)
269
- await session .assert_claims (claim_validators , user_context )
370
+ try :
371
+ await res .session .assert_claims (claim_validators , user_context )
372
+ except SuperTokensError as e :
373
+ if isinstance (e , InvalidClaimsError ):
374
+ return GetSessionClaimValidationErrorResult (
375
+ error = e ,
376
+ response = GetSessionClaimValidationErrorResponseObject (
377
+ message = "invalid claim" , claim_validation_errors = e .payload
378
+ ),
379
+ )
380
+ raise e
270
381
271
- return session
382
+ return res
272
383
273
384
274
385
async def refresh_session (
275
- request : Any , user_context : Union [None , Dict [str , Any ]] = None
386
+ request : Any ,
387
+ user_context : Union [None , Dict [str , Any ]] = None ,
276
388
) -> SessionContainer :
277
389
if user_context is None :
278
390
user_context = {}
391
+
279
392
if not hasattr (request , "wrapper_used" ) or not request .wrapper_used :
280
393
request = FRAMEWORKS [
281
394
SessionRecipe .get_instance ().app_info .framework
282
395
].wrap_request (request )
283
396
397
+ recipe_instance = SessionRecipe .get_instance ()
398
+ config = recipe_instance .config
399
+ recipe_interface_impl = recipe_instance .recipe_implementation
400
+
401
+ return await refresh_session_in_request (
402
+ request ,
403
+ user_context ,
404
+ config ,
405
+ recipe_interface_impl ,
406
+ )
407
+
408
+
409
+ async def refresh_session_without_request_response (
410
+ refresh_token : str ,
411
+ disable_anti_csrf : bool = False ,
412
+ anti_csrf_token : Optional [str ] = None ,
413
+ user_context : Optional [Dict [str , Any ]] = None ,
414
+ ) -> Union [
415
+ RefreshSessionOkResult ,
416
+ RefreshSessionUnauthorizedResult ,
417
+ RefreshSessionTokenTheftErrorResult ,
418
+ ]:
419
+ if user_context is None :
420
+ user_context = {}
421
+
284
422
return await SessionRecipe .get_instance ().recipe_implementation .refresh_session (
285
- request , user_context
423
+ refresh_token , anti_csrf_token , disable_anti_csrf , user_context
286
424
)
287
425
288
426
0 commit comments