Skip to content

Commit 9402662

Browse files
committed
fix: Clear cookies when revoke_session is called
1 parent aa4bc27 commit 9402662

File tree

3 files changed

+91
-8
lines changed

3 files changed

+91
-8
lines changed

CHANGELOG.md

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1414
- Use [black](https://github.com/psf/black) instead of `autopep8` to format code.
1515
- Add frontend integration tests for `django2x`
1616

17+
### Bug fix:
18+
19+
- Clears cookies when `revoke_session` is called using the session container, even if the session did not exist from before: https://github.com/supertokens/supertokens-node/issues/343
20+
1721
### Breaking changes:
22+
- Change request arg type in session recipe functions from Any to BaseRequest.
1823
- Changes session function recipe interfaces to not throw an `UNAUTHORISED` error when the input is a session_handle: https://github.com/supertokens/backend/issues/83
1924
- `get_session_information` now returns `None` if the session does not exist.
2025
- `update_session_data` now returns `False` if the input `session_handle` does not exist.
@@ -71,8 +76,6 @@ init(
7176
)
7277
```
7378

74-
### Breaking change
75-
- Change request arg type in session recipe functions from Any to BaseRequest.
7679

7780
### Documentation
7881
- Add more details in the `CONTRIBUTING.md` to make it beginner friendly.

supertokens_python/recipe/session/session_class.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,10 @@ class Session(SessionContainer):
2222
async def revoke_session(self, user_context: Union[Any, None] = None) -> None:
2323
if user_context is None:
2424
user_context = {}
25-
if await self.recipe_implementation.revoke_session(
25+
await self.recipe_implementation.revoke_session(
2626
self.session_handle, user_context
27-
):
28-
self.remove_cookies = True
27+
)
28+
self.remove_cookies = True
2929

3030
async def get_session_data(
3131
self, user_context: Union[Dict[str, Any], None] = None

tests/test_session.py

Lines changed: 83 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,18 +12,32 @@
1212
# License for the specific language governing permissions and limitations
1313
# under the License.
1414

15-
from pytest import mark
1615
from typing import List
16+
17+
from fastapi import FastAPI
18+
from fastapi.requests import Request
19+
from fastapi.testclient import TestClient
20+
from pytest import fixture, mark
21+
1722
from supertokens_python import InputAppInfo, SupertokensConfig, init
23+
from supertokens_python.framework.fastapi.fastapi_middleware import get_middleware
1824
from supertokens_python.process_state import AllowedProcessStates, ProcessState
1925
from supertokens_python.recipe import session
2026
from supertokens_python.recipe.session import SessionRecipe
27+
from supertokens_python.recipe.session.asyncio import (
28+
create_new_session as asyncio_create_new_session,
29+
)
2130
from supertokens_python.recipe.session.asyncio import (
2231
get_all_session_handles_for_user,
2332
get_session_information,
33+
regenerate_access_token,
34+
)
35+
from supertokens_python.recipe.session.asyncio import (
36+
revoke_session as asyncio_revoke_session,
37+
)
38+
from supertokens_python.recipe.session.asyncio import (
2439
update_access_token_payload,
2540
update_session_data,
26-
regenerate_access_token,
2741
)
2842
from supertokens_python.recipe.session.recipe_implementation import RecipeImplementation
2943
from supertokens_python.recipe.session.session_functions import (
@@ -32,7 +46,6 @@
3246
refresh_session,
3347
revoke_session,
3448
)
35-
3649
from tests.utils import clean_st, reset, setup_st, start_st
3750

3851

@@ -211,3 +224,70 @@ async def test_creating_many_sessions_for_one_user_and_looping():
211224
assert is_updated is False
212225
is_updated = await update_session_data("invalidHandle", {"foo": "bar"})
213226
assert is_updated is False
227+
228+
229+
@fixture(scope="function")
230+
async def driver_config_client():
231+
app = FastAPI()
232+
app.add_middleware(get_middleware())
233+
234+
@app.get("/create")
235+
async def create(request: Request): # type: ignore
236+
session = await asyncio_create_new_session(request, "", {}, {})
237+
session_handle = session.get_handle()
238+
return {"session_handle": session_handle, "access_token": session.access_token}
239+
240+
@app.get("/revoke")
241+
async def revoke(request: Request): # type: ignore
242+
# session_handle = request.json()["session_handle"]
243+
# await asyncio_get_session(request, True, True)
244+
session = await asyncio_create_new_session(request, "", {}, {})
245+
session_handle = session.get_handle()
246+
return {"session_handle": session_handle, "access_token": session.access_token}
247+
248+
return TestClient(app)
249+
250+
251+
@mark.asyncio
252+
async def test_signout_api_works_even_if_session_is_deleted_after_creation(
253+
driver_config_client: TestClient,
254+
):
255+
init(
256+
supertokens_config=SupertokensConfig("http://localhost:3567"),
257+
app_info=InputAppInfo(
258+
app_name="SuperTokens Demo",
259+
api_domain="https://api.supertokens.io",
260+
website_domain="supertokens.io",
261+
),
262+
framework="fastapi",
263+
recipe_list=[session.init(anti_csrf="VIA_TOKEN")],
264+
)
265+
start_st()
266+
267+
s = SessionRecipe.get_instance()
268+
if not isinstance(s.recipe_implementation, RecipeImplementation):
269+
raise Exception("Should never come here")
270+
user_id = "user_id"
271+
272+
response = await create_new_session(s.recipe_implementation, user_id, {}, {})
273+
274+
session_handle = response["session"]["handle"]
275+
276+
revoked = await asyncio_revoke_session(session_handle)
277+
assert revoked
278+
279+
signout_response = driver_config_client.post(
280+
url="/auth/signout",
281+
cookies={
282+
"sAccessToken": response["accessToken"]["token"],
283+
"sIdRefreshToken": response["idRefreshToken"]["token"],
284+
},
285+
headers={"anti-csrf": response.get("antiCsrfToken", "")},
286+
)
287+
288+
assert signout_response.json() == {"status": "OK"}
289+
290+
assert (
291+
signout_response.headers["set-cookie"]
292+
== """sAccessToken=""; expires=Thu, 01 Jan 1970 00:00:00 GMT; HttpOnly; Path=/; SameSite=lax; Secure, sIdRefreshToken=""; expires=Thu, 01 Jan 1970 00:00:00 GMT; HttpOnly; Path=/; SameSite=lax; Secure, sRefreshToken=""; expires=Thu, 01 Jan 1970 00:00:00 GMT; HttpOnly; Path=/auth/session/refresh; SameSite=lax; Secure"""
293+
)

0 commit comments

Comments
 (0)