Skip to content

Commit af632ac

Browse files
committed
adding dev-v0.14.4 tag to this commit to ensure building
1 parent afaa56e commit af632ac

File tree

13 files changed

+600
-431
lines changed

13 files changed

+600
-431
lines changed

html/supertokens_python/constants.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ <h1 class="title">Module <code>supertokens_python.constants</code></h1>
4242
from __future__ import annotations
4343

4444
SUPPORTED_CDI_VERSIONS = [&#34;2.21&#34;]
45-
VERSION = &#34;0.14.3&#34;
45+
VERSION = &#34;0.14.4&#34;
4646
TELEMETRY = &#34;/telemetry&#34;
4747
USER_COUNT = &#34;/users/count&#34;
4848
USER_DELETE = &#34;/user/remove&#34;

html/supertokens_python/recipe/emailpassword/emaildelivery/services/smtp/password_reset_email.html

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,10 @@ <h1 class="title">Module <code>supertokens_python.recipe.emailpassword.emaildeli
3838
&lt;title&gt;*|MC:SUBJECT|*&lt;/title&gt;
3939

4040
&lt;style type=&#34;text/css&#34;&gt;
41+
body {
42+
max-width: 100vw;
43+
overflow: hidden;
44+
}
4145
p {
4246
margin: 10px 0;
4347
padding: 0;

html/supertokens_python/recipe/jwt/recipe_implementation.html

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ <h1 class="title">Module <code>supertokens_python.recipe.jwt.recipe_implementati
8080
data = {
8181
&#34;payload&#34;: payload,
8282
&#34;validity&#34;: validity_seconds,
83-
&#34;use_static_signing_key&#34;: use_static_signing_key is not False,
83+
&#34;useStaticSigningKey&#34;: use_static_signing_key is not False,
8484
&#34;algorithm&#34;: &#34;RS256&#34;,
8585
&#34;jwksDomain&#34;: self.app_info.api_domain.get_as_string_dangerous(),
8686
}
@@ -147,7 +147,7 @@ <h2 class="section-title" id="header-classes">Classes</h2>
147147
data = {
148148
&#34;payload&#34;: payload,
149149
&#34;validity&#34;: validity_seconds,
150-
&#34;use_static_signing_key&#34;: use_static_signing_key is not False,
150+
&#34;useStaticSigningKey&#34;: use_static_signing_key is not False,
151151
&#34;algorithm&#34;: &#34;RS256&#34;,
152152
&#34;jwksDomain&#34;: self.app_info.api_domain.get_as_string_dangerous(),
153153
}
@@ -202,7 +202,7 @@ <h3>Methods</h3>
202202
data = {
203203
&#34;payload&#34;: payload,
204204
&#34;validity&#34;: validity_seconds,
205-
&#34;use_static_signing_key&#34;: use_static_signing_key is not False,
205+
&#34;useStaticSigningKey&#34;: use_static_signing_key is not False,
206206
&#34;algorithm&#34;: &#34;RS256&#34;,
207207
&#34;jwksDomain&#34;: self.app_info.api_domain.get_as_string_dangerous(),
208208
}

html/supertokens_python/recipe/session/access_token.html

Lines changed: 60 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -41,16 +41,15 @@ <h1 class="title">Module <code>supertokens_python.recipe.session.access_token</c
4141
# under the License.
4242
from __future__ import annotations
4343

44-
from typing import Any, Dict, List, Optional, Union
44+
from typing import Any, Dict, Optional, Union
4545

4646
import jwt
47-
from jwt.exceptions import DecodeError, PyJWKClientError
47+
from jwt.exceptions import DecodeError
4848

4949
from supertokens_python.logger import log_debug_message
5050
from supertokens_python.utils import get_timestamp_ms
5151

5252
from .exceptions import raise_try_refresh_token_exception
53-
from .jwks import JWKClient, JWKSRequestError, PyJWK
5453
from .jwt import ParsedJWTInfo
5554

5655

@@ -71,47 +70,44 @@ <h1 class="title">Module <code>supertokens_python.recipe.session.access_token</c
7170
return None
7271

7372

73+
from supertokens_python.recipe.session.jwks import get_latest_keys
74+
75+
7476
def get_info_from_access_token(
7577
jwt_info: ParsedJWTInfo,
76-
jwk_clients: List[JWKClient],
7778
do_anti_csrf_check: bool,
7879
):
7980
try:
8081
payload: Optional[Dict[str, Any]] = None
81-
client: Optional[JWKClient] = None
82-
keys: Optional[List[PyJWK]] = None
83-
84-
# Get the keys from the first available client
85-
for c in jwk_clients:
86-
try:
87-
client = c
88-
keys = c.get_latest_keys()
89-
break
90-
except JWKSRequestError:
91-
continue
92-
93-
if keys is None or client is None:
94-
raise PyJWKClientError(&#34;No key found&#34;)
95-
96-
if jwt_info.version &lt; 3:
82+
decode_algo = (
83+
jwt_info.parsed_header[&#34;alg&#34;]
84+
if jwt_info.parsed_header is not None
85+
else &#34;RS256&#34;
86+
)
87+
88+
if jwt_info.version &gt;= 3:
89+
matching_keys = get_latest_keys(jwt_info.kid)
90+
payload = jwt.decode( # type: ignore
91+
jwt_info.raw_token_string,
92+
matching_keys[0].key, # type: ignore
93+
algorithms=[decode_algo],
94+
options={&#34;verify_signature&#34;: True, &#34;verify_exp&#34;: True},
95+
)
96+
else:
9797
# It won&#39;t have kid. So we&#39;ll have to try the token against all the keys from all the jwk_clients
9898
# If any of them work, we&#39;ll use that payload
99-
for k in keys:
99+
for k in get_latest_keys():
100100
try:
101-
payload = jwt.decode(jwt_info.raw_token_string, k.key, algorithms=[&#34;RS256&#34;]) # type: ignore
101+
payload = jwt.decode( # type: ignore
102+
jwt_info.raw_token_string,
103+
k.key, # type: ignore
104+
algorithms=[decode_algo],
105+
options={&#34;verify_signature&#34;: True, &#34;verify_exp&#34;: True},
106+
)
102107
break
103108
except DecodeError:
104109
pass
105110

106-
elif jwt_info.version &gt;= 3:
107-
matching_key = client.get_matching_key_from_jwt(jwt_info.raw_token_string)
108-
payload = jwt.decode( # type: ignore
109-
jwt_info.raw_token_string,
110-
matching_key.key, # type: ignore
111-
algorithms=[&#34;RS256&#34;],
112-
options={&#34;verify_signature&#34;: True, &#34;verify_exp&#34;: True},
113-
)
114-
115111
if payload is None:
116112
raise DecodeError(&#34;Could not decode the token&#34;)
117113

@@ -138,7 +134,7 @@ <h1 class="title">Module <code>supertokens_python.recipe.session.access_token</c
138134
if anti_csrf_token is None and do_anti_csrf_check:
139135
raise Exception(&#34;Access token does not contain the anti-csrf token&#34;)
140136

141-
assert isinstance(expiry_time, int)
137+
assert isinstance(expiry_time, (float, int))
142138

143139
if expiry_time &lt; get_timestamp_ms():
144140
raise Exception(&#34;Access token expired&#34;)
@@ -165,8 +161,8 @@ <h1 class="title">Module <code>supertokens_python.recipe.session.access_token</c
165161
if version &gt;= 3:
166162
if (
167163
not isinstance(payload.get(&#34;sub&#34;), str)
168-
or not isinstance(payload.get(&#34;exp&#34;), int)
169-
or not isinstance(payload.get(&#34;iat&#34;), int)
164+
or not isinstance(payload.get(&#34;exp&#34;), (int, float))
165+
or not isinstance(payload.get(&#34;iat&#34;), (int, float))
170166
or not isinstance(payload.get(&#34;sessionHandle&#34;), str)
171167
or not isinstance(payload.get(&#34;refreshTokenHash1&#34;), str)
172168
):
@@ -181,8 +177,8 @@ <h1 class="title">Module <code>supertokens_python.recipe.session.access_token</c
181177
not isinstance(payload.get(&#34;sessionHandle&#34;), str)
182178
or payload.get(&#34;userData&#34;) is None
183179
or not isinstance(payload.get(&#34;refreshTokenHash1&#34;), str)
184-
or not isinstance(payload.get(&#34;expiryTime&#34;), int)
185-
or not isinstance(payload.get(&#34;timeCreated&#34;), int)
180+
or not isinstance(payload.get(&#34;expiryTime&#34;), (float, int))
181+
or not isinstance(payload.get(&#34;timeCreated&#34;), (float, int))
186182
):
187183
log_debug_message(
188184
&#34;validateAccessTokenStructure: Access token is using version &lt; 3&#34;
@@ -201,7 +197,7 @@ <h1 class="title">Module <code>supertokens_python.recipe.session.access_token</c
201197
<h2 class="section-title" id="header-functions">Functions</h2>
202198
<dl>
203199
<dt id="supertokens_python.recipe.session.access_token.get_info_from_access_token"><code class="name flex">
204-
<span>def <span class="ident">get_info_from_access_token</span></span>(<span>jwt_info: ParsedJWTInfo, jwk_clients: List[JWKClient], do_anti_csrf_check: bool)</span>
200+
<span>def <span class="ident">get_info_from_access_token</span></span>(<span>jwt_info: ParsedJWTInfo, do_anti_csrf_check: bool)</span>
205201
</code></dt>
206202
<dd>
207203
<div class="desc"></div>
@@ -211,45 +207,39 @@ <h2 class="section-title" id="header-functions">Functions</h2>
211207
</summary>
212208
<pre><code class="python">def get_info_from_access_token(
213209
jwt_info: ParsedJWTInfo,
214-
jwk_clients: List[JWKClient],
215210
do_anti_csrf_check: bool,
216211
):
217212
try:
218213
payload: Optional[Dict[str, Any]] = None
219-
client: Optional[JWKClient] = None
220-
keys: Optional[List[PyJWK]] = None
221-
222-
# Get the keys from the first available client
223-
for c in jwk_clients:
224-
try:
225-
client = c
226-
keys = c.get_latest_keys()
227-
break
228-
except JWKSRequestError:
229-
continue
230-
231-
if keys is None or client is None:
232-
raise PyJWKClientError(&#34;No key found&#34;)
233-
234-
if jwt_info.version &lt; 3:
214+
decode_algo = (
215+
jwt_info.parsed_header[&#34;alg&#34;]
216+
if jwt_info.parsed_header is not None
217+
else &#34;RS256&#34;
218+
)
219+
220+
if jwt_info.version &gt;= 3:
221+
matching_keys = get_latest_keys(jwt_info.kid)
222+
payload = jwt.decode( # type: ignore
223+
jwt_info.raw_token_string,
224+
matching_keys[0].key, # type: ignore
225+
algorithms=[decode_algo],
226+
options={&#34;verify_signature&#34;: True, &#34;verify_exp&#34;: True},
227+
)
228+
else:
235229
# It won&#39;t have kid. So we&#39;ll have to try the token against all the keys from all the jwk_clients
236230
# If any of them work, we&#39;ll use that payload
237-
for k in keys:
231+
for k in get_latest_keys():
238232
try:
239-
payload = jwt.decode(jwt_info.raw_token_string, k.key, algorithms=[&#34;RS256&#34;]) # type: ignore
233+
payload = jwt.decode( # type: ignore
234+
jwt_info.raw_token_string,
235+
k.key, # type: ignore
236+
algorithms=[decode_algo],
237+
options={&#34;verify_signature&#34;: True, &#34;verify_exp&#34;: True},
238+
)
240239
break
241240
except DecodeError:
242241
pass
243242

244-
elif jwt_info.version &gt;= 3:
245-
matching_key = client.get_matching_key_from_jwt(jwt_info.raw_token_string)
246-
payload = jwt.decode( # type: ignore
247-
jwt_info.raw_token_string,
248-
matching_key.key, # type: ignore
249-
algorithms=[&#34;RS256&#34;],
250-
options={&#34;verify_signature&#34;: True, &#34;verify_exp&#34;: True},
251-
)
252-
253243
if payload is None:
254244
raise DecodeError(&#34;Could not decode the token&#34;)
255245

@@ -276,7 +266,7 @@ <h2 class="section-title" id="header-functions">Functions</h2>
276266
if anti_csrf_token is None and do_anti_csrf_check:
277267
raise Exception(&#34;Access token does not contain the anti-csrf token&#34;)
278268

279-
assert isinstance(expiry_time, int)
269+
assert isinstance(expiry_time, (float, int))
280270

281271
if expiry_time &lt; get_timestamp_ms():
282272
raise Exception(&#34;Access token expired&#34;)
@@ -347,8 +337,8 @@ <h2 class="section-title" id="header-functions">Functions</h2>
347337
if version &gt;= 3:
348338
if (
349339
not isinstance(payload.get(&#34;sub&#34;), str)
350-
or not isinstance(payload.get(&#34;exp&#34;), int)
351-
or not isinstance(payload.get(&#34;iat&#34;), int)
340+
or not isinstance(payload.get(&#34;exp&#34;), (int, float))
341+
or not isinstance(payload.get(&#34;iat&#34;), (int, float))
352342
or not isinstance(payload.get(&#34;sessionHandle&#34;), str)
353343
or not isinstance(payload.get(&#34;refreshTokenHash1&#34;), str)
354344
):
@@ -363,8 +353,8 @@ <h2 class="section-title" id="header-functions">Functions</h2>
363353
not isinstance(payload.get(&#34;sessionHandle&#34;), str)
364354
or payload.get(&#34;userData&#34;) is None
365355
or not isinstance(payload.get(&#34;refreshTokenHash1&#34;), str)
366-
or not isinstance(payload.get(&#34;expiryTime&#34;), int)
367-
or not isinstance(payload.get(&#34;timeCreated&#34;), int)
356+
or not isinstance(payload.get(&#34;expiryTime&#34;), (float, int))
357+
or not isinstance(payload.get(&#34;timeCreated&#34;), (float, int))
368358
):
369359
log_debug_message(
370360
&#34;validateAccessTokenStructure: Access token is using version &lt; 3&#34;

html/supertokens_python/recipe/session/api/implementation.html

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,8 @@ <h1 class="title">Module <code>supertokens_python.recipe.session.api.implementat
101101
) -&gt; Union[SessionContainer, None]:
102102
method = normalise_http_method(api_options.request.method())
103103
if method in (&#34;options&#34;, &#34;trace&#34;):
104+
if session_required:
105+
raise Exception(f&#34;verify_session cannot be used with {method} method&#34;)
104106
return None
105107
incoming_path = NormalisedURLPath(api_options.request.get_path())
106108
refresh_token_path = api_options.config.refresh_token_path
@@ -181,6 +183,8 @@ <h2 class="section-title" id="header-classes">Classes</h2>
181183
) -&gt; Union[SessionContainer, None]:
182184
method = normalise_http_method(api_options.request.method())
183185
if method in (&#34;options&#34;, &#34;trace&#34;):
186+
if session_required:
187+
raise Exception(f&#34;verify_session cannot be used with {method} method&#34;)
184188
return None
185189
incoming_path = NormalisedURLPath(api_options.request.get_path())
186190
refresh_token_path = api_options.config.refresh_token_path
@@ -276,6 +280,8 @@ <h3>Methods</h3>
276280
) -&gt; Union[SessionContainer, None]:
277281
method = normalise_http_method(api_options.request.method())
278282
if method in (&#34;options&#34;, &#34;trace&#34;):
283+
if session_required:
284+
raise Exception(f&#34;verify_session cannot be used with {method} method&#34;)
279285
return None
280286
incoming_path = NormalisedURLPath(api_options.request.get_path())
281287
refresh_token_path = api_options.config.refresh_token_path

html/supertokens_python/recipe/session/constants.html

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,7 @@ <h1 class="title">Module <code>supertokens_python.recipe.session.constants</code
6161

6262
available_token_transfer_methods: List[TokenTransferMethod] = [&#34;cookie&#34;, &#34;header&#34;]
6363

64-
JWKCacheMaxAgeInMs = 60 * 1000 # 1min
65-
JWKRequestCooldownInMs = 500 # 0.5s
64+
JWKCacheMaxAgeInMs = 60 * 1000 # 60s
6665
protected_props = [
6766
&#34;sub&#34;,
6867
&#34;iat&#34;,

html/supertokens_python/recipe/session/framework/flask/index.html

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -89,8 +89,9 @@ <h1 class="title">Module <code>supertokens_python.recipe.session.framework.flask
8989
baseRequest.set_session_as_none()
9090
else:
9191
baseRequest.set_session(session)
92-
response = make_response(f(*args, **kwargs))
93-
return response
92+
93+
response = f(*args, **kwargs)
94+
return make_response(response) if response is not None else None
9495

9596
return cast(_T, wrapped_function)
9697

@@ -151,8 +152,9 @@ <h2 class="section-title" id="header-functions">Functions</h2>
151152
baseRequest.set_session_as_none()
152153
else:
153154
baseRequest.set_session(session)
154-
response = make_response(f(*args, **kwargs))
155-
return response
155+
156+
response = f(*args, **kwargs)
157+
return make_response(response) if response is not None else None
156158

157159
return cast(_T, wrapped_function)
158160

html/supertokens_python/recipe/session/interfaces.html

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,6 @@ <h1 class="title">Module <code>supertokens_python.recipe.session.interfaces</cod
6464

6565
if TYPE_CHECKING:
6666
from supertokens_python.framework import BaseRequest
67-
from .jwks import JWKClient
6867

6968
from supertokens_python.framework import BaseResponse
7069

@@ -156,8 +155,6 @@ <h1 class="title">Module <code>supertokens_python.recipe.session.interfaces</cod
156155

157156

158157
class RecipeInterface(ABC): # pylint: disable=too-many-public-methods
159-
JWK_clients: List[JWKClient] = []
160-
161158
def __init__(self):
162159
pass
163160

@@ -1008,8 +1005,6 @@ <h3>Class variables</h3>
10081005
<span>Expand source code</span>
10091006
</summary>
10101007
<pre><code class="python">class RecipeInterface(ABC): # pylint: disable=too-many-public-methods
1011-
JWK_clients: List[JWKClient] = []
1012-
10131008
def __init__(self):
10141009
pass
10151010

@@ -1183,13 +1178,6 @@ <h3>Subclasses</h3>
11831178
<ul class="hlist">
11841179
<li><a title="supertokens_python.recipe.session.recipe_implementation.RecipeImplementation" href="recipe_implementation.html#supertokens_python.recipe.session.recipe_implementation.RecipeImplementation">RecipeImplementation</a></li>
11851180
</ul>
1186-
<h3>Class variables</h3>
1187-
<dl>
1188-
<dt id="supertokens_python.recipe.session.interfaces.RecipeInterface.JWK_clients"><code class="name">var <span class="ident">JWK_clients</span> : List[JWKClient]</code></dt>
1189-
<dd>
1190-
<div class="desc"></div>
1191-
</dd>
1192-
</dl>
11931181
<h3>Methods</h3>
11941182
<dl>
11951183
<dt id="supertokens_python.recipe.session.interfaces.RecipeInterface.create_new_session"><code class="name flex">
@@ -2697,7 +2685,6 @@ <h4><code><a title="supertokens_python.recipe.session.interfaces.GetSessionToken
26972685
<li>
26982686
<h4><code><a title="supertokens_python.recipe.session.interfaces.RecipeInterface" href="#supertokens_python.recipe.session.interfaces.RecipeInterface">RecipeInterface</a></code></h4>
26992687
<ul class="">
2700-
<li><code><a title="supertokens_python.recipe.session.interfaces.RecipeInterface.JWK_clients" href="#supertokens_python.recipe.session.interfaces.RecipeInterface.JWK_clients">JWK_clients</a></code></li>
27012688
<li><code><a title="supertokens_python.recipe.session.interfaces.RecipeInterface.create_new_session" href="#supertokens_python.recipe.session.interfaces.RecipeInterface.create_new_session">create_new_session</a></code></li>
27022689
<li><code><a title="supertokens_python.recipe.session.interfaces.RecipeInterface.fetch_and_set_claim" href="#supertokens_python.recipe.session.interfaces.RecipeInterface.fetch_and_set_claim">fetch_and_set_claim</a></code></li>
27032690
<li><code><a title="supertokens_python.recipe.session.interfaces.RecipeInterface.get_all_session_handles_for_user" href="#supertokens_python.recipe.session.interfaces.RecipeInterface.get_all_session_handles_for_user">get_all_session_handles_for_user</a></code></li>

0 commit comments

Comments
 (0)