Skip to content

Commit ef1b610

Browse files
authored
Merge pull request #211 from supertokens/feat/session-grants-refactor
feat: Refactor session claims and tests
2 parents 6d297b0 + 9a0886c commit ef1b610

24 files changed

+717
-200
lines changed

supertokens_python/recipe/session/api/implementation.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
)
2424
from supertokens_python.types import MaybeAwaitable
2525
from supertokens_python.utils import normalise_http_method
26+
from ..utils import get_required_claim_validators
2627

2728
if TYPE_CHECKING:
2829
from supertokens_python.recipe.session.interfaces import APIOptions
@@ -67,7 +68,7 @@ async def verify_session(
6768
session_required: bool,
6869
override_global_claim_validators: Optional[
6970
Callable[
70-
[SessionContainer, List[SessionClaimValidator], Dict[str, Any]],
71+
[List[SessionClaimValidator], SessionContainer, Dict[str, Any]],
7172
MaybeAwaitable[List[SessionClaimValidator]],
7273
]
7374
],
@@ -91,10 +92,15 @@ async def verify_session(
9192
)
9293

9394
if session is not None:
94-
await api_options.recipe_implementation.assert_claims(
95+
claim_validators = await get_required_claim_validators(
9596
session,
9697
override_global_claim_validators,
9798
user_context,
9899
)
100+
await api_options.recipe_implementation.assert_claims(
101+
session,
102+
claim_validators,
103+
user_context,
104+
)
99105

100106
return session

supertokens_python/recipe/session/asyncio/__init__.py

Lines changed: 117 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,15 @@
2222
SessionInformationResult,
2323
SessionClaim,
2424
SessionClaimValidator,
25+
SessionDoesntExistError,
26+
ValidateClaimsOkResult,
27+
JSONObject,
28+
GetClaimValueOkResult,
2529
)
2630
from supertokens_python.recipe.session.recipe import SessionRecipe
2731
from supertokens_python.types import MaybeAwaitable
28-
from supertokens_python.utils import FRAMEWORKS
32+
from supertokens_python.utils import FRAMEWORKS, resolve
33+
from ..utils import get_required_claim_validators
2934
from ...jwt.interfaces import (
3035
CreateJwtOkResult,
3136
CreateJwtResultUnsupportedAlgorithm,
@@ -53,11 +58,118 @@ async def create_new_session(
5358
)
5459

5560

61+
async def validate_claims_for_session_handle(
62+
session_handle: str,
63+
override_global_claim_validators: Optional[
64+
Callable[
65+
[
66+
List[SessionClaimValidator],
67+
SessionInformationResult,
68+
Dict[str, Any],
69+
], # Prev. 2nd arg was SessionContainer
70+
MaybeAwaitable[List[SessionClaimValidator]],
71+
]
72+
] = None,
73+
user_context: Union[None, Dict[str, Any]] = None,
74+
) -> Union[SessionDoesntExistError, ValidateClaimsOkResult]:
75+
if user_context is None:
76+
user_context = {}
77+
78+
recipe_impl = SessionRecipe.get_instance().recipe_implementation
79+
session_info = await recipe_impl.get_session_information(
80+
session_handle, user_context
81+
)
82+
83+
if session_info is None:
84+
return SessionDoesntExistError()
85+
86+
claim_validators_added_by_other_recipes = (
87+
SessionRecipe.get_claim_validators_added_by_other_recipes()
88+
)
89+
global_claim_validators = await resolve(
90+
recipe_impl.get_global_claim_validators(
91+
session_info.user_id,
92+
claim_validators_added_by_other_recipes,
93+
user_context,
94+
)
95+
)
96+
97+
if override_global_claim_validators is not None:
98+
claim_validators = await resolve(
99+
override_global_claim_validators(
100+
global_claim_validators, session_info, user_context
101+
)
102+
)
103+
else:
104+
claim_validators = global_claim_validators
105+
106+
return await recipe_impl.validate_claims_for_session_handle(
107+
session_info, claim_validators, user_context
108+
)
109+
110+
111+
async def validate_claims_in_jwt_payload(
112+
user_id: str,
113+
jwt_payload: JSONObject,
114+
override_global_claim_validators: Optional[
115+
Callable[
116+
[
117+
List[SessionClaimValidator],
118+
str,
119+
Dict[str, Any],
120+
], # Prev. 2nd arg was SessionContainer
121+
MaybeAwaitable[List[SessionClaimValidator]],
122+
]
123+
] = None,
124+
user_context: Union[None, Dict[str, Any]] = None,
125+
):
126+
if user_context is None:
127+
user_context = {}
128+
129+
recipe_impl = SessionRecipe.get_instance().recipe_implementation
130+
131+
claim_validators_added_by_other_recipes = (
132+
SessionRecipe.get_claim_validators_added_by_other_recipes()
133+
)
134+
global_claim_validators = await resolve(
135+
recipe_impl.get_global_claim_validators(
136+
user_id,
137+
claim_validators_added_by_other_recipes,
138+
user_context,
139+
)
140+
)
141+
142+
if override_global_claim_validators is not None:
143+
claim_validators = await resolve(
144+
override_global_claim_validators(
145+
global_claim_validators, user_id, user_context
146+
)
147+
)
148+
else:
149+
claim_validators = global_claim_validators
150+
151+
return await recipe_impl.validate_claims_in_jwt_payload(
152+
user_id, jwt_payload, claim_validators, user_context
153+
)
154+
155+
156+
async def fetch_and_set_claim(
157+
session_handle: str,
158+
claim: SessionClaim[Any],
159+
user_context: Union[None, Dict[str, Any]] = None,
160+
) -> bool:
161+
if user_context is None:
162+
user_context = {}
163+
return await SessionRecipe.get_instance().recipe_implementation.fetch_and_set_claim(
164+
session_handle, claim, user_context
165+
)
166+
167+
56168
async def get_claim_value(
57169
session_handle: str,
58170
claim: SessionClaim[_T],
59171
user_context: Union[None, Dict[str, Any]] = None,
60-
) -> Union[_T, None]:
172+
) -> Union[SessionDoesntExistError, GetClaimValueOkResult[_T]]:
61173
if user_context is None:
62174
user_context = {}
63175
return await SessionRecipe.get_instance().recipe_implementation.get_claim_value(
@@ -96,7 +208,7 @@ async def get_session(
96208
session_required: bool = True,
97209
override_global_claim_validators: Optional[
98210
Callable[
99-
[SessionContainer, List[SessionClaimValidator], Dict[str, Any]],
211+
[List[SessionClaimValidator], SessionContainer, Dict[str, Any]],
100212
MaybeAwaitable[List[SessionClaimValidator]],
101213
]
102214
] = None,
@@ -119,9 +231,10 @@ async def get_session(
119231
)
120232

121233
if session is not None:
122-
await session_recipe_impl.assert_claims(
234+
claim_validators = await get_required_claim_validators(
123235
session, override_global_claim_validators, user_context
124236
)
237+
await session_recipe_impl.assert_claims(session, claim_validators, user_context)
125238

126239
return session
127240

supertokens_python/recipe/session/claim_base_classes/primitive_claim.py

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ def should_refetch(
5353
):
5454
return claim.get_value_from_payload(payload, user_context) is None
5555

56-
def validate(
56+
async def validate(
5757
self,
5858
payload: JSONObject,
5959
user_context: Union[Dict[str, Any], None] = None,
@@ -93,23 +93,26 @@ def should_refetch(
9393
claim.get_value_from_payload(payload, user_context) is None
9494
) or (payload[claim.key]["t"] < time.time() - max_age_in_sec * 1000)
9595

96-
def validate(
96+
async def validate(
9797
self,
9898
payload: JSONObject,
9999
user_context: Union[Dict[str, Any], None] = None,
100100
):
101101
claim_val = claim.get_value_from_payload(payload, user_context)
102-
if claim_val != val:
102+
if claim_val is None:
103103
return {
104104
"isValid": False,
105105
"reason": {
106-
"message": "wrong value",
106+
"message": "value does not exist",
107107
"expectedValue": val,
108108
"actualValue": claim_val,
109109
},
110110
}
111111

112-
age_in_sec = (time.time() - payload[claim.key]["t"]) / 1000
112+
age_in_sec = (
113+
time.time()
114+
- float(claim.get_last_refetch_time(payload, user_context) or 0)
115+
) / 1000
113116
if age_in_sec > max_age_in_sec:
114117
return {
115118
"isValid": False,
@@ -119,6 +122,15 @@ def validate(
119122
"maxAgeInSeconds": max_age_in_sec,
120123
},
121124
}
125+
if claim_val != val:
126+
return {
127+
"isValid": False,
128+
"reason": {
129+
"message": "wrong value",
130+
"expectedValue": val,
131+
"actualValue": claim_val,
132+
},
133+
}
122134

123135
return {"isValid": True}
124136

supertokens_python/recipe/session/framework/django/asyncio/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ def verify_session(
3131
user_context: Union[None, Dict[str, Any]] = None,
3232
override_global_claim_validators: Optional[
3333
Callable[
34-
[SessionContainer, List[SessionClaimValidator], Dict[str, Any]],
34+
[List[SessionClaimValidator], SessionContainer, Dict[str, Any]],
3535
MaybeAwaitable[List[SessionClaimValidator]],
3636
]
3737
] = None,

supertokens_python/recipe/session/framework/django/syncio/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ def verify_session(
3232
user_context: Union[None, Dict[str, Any]] = None,
3333
override_global_claim_validators: Optional[
3434
Callable[
35-
[SessionContainer, List[SessionClaimValidator], Dict[str, Any]],
35+
[List[SessionClaimValidator], SessionContainer, Dict[str, Any]],
3636
MaybeAwaitable[List[SessionClaimValidator]],
3737
]
3838
] = None,

supertokens_python/recipe/session/framework/fastapi/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ def verify_session(
2626
user_context: Union[None, Dict[str, Any]] = None,
2727
override_global_claim_validators: Optional[
2828
Callable[
29-
[SessionContainer, List[SessionClaimValidator], Dict[str, Any]],
29+
[List[SessionClaimValidator], SessionContainer, Dict[str, Any]],
3030
MaybeAwaitable[List[SessionClaimValidator]],
3131
]
3232
] = None,

supertokens_python/recipe/session/framework/flask/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ def verify_session(
2929
user_context: Union[None, Dict[str, Any]] = None,
3030
override_global_claim_validators: Optional[
3131
Callable[
32-
[SessionContainer, List[SessionClaimValidator], Dict[str, Any]],
32+
[List[SessionClaimValidator], SessionContainer, Dict[str, Any]],
3333
MaybeAwaitable[List[SessionClaimValidator]],
3434
]
3535
] = None,

0 commit comments

Comments
 (0)