Skip to content

Commit 5f9f3e1

Browse files
Merge pull request #203 from supertokens/fix/clear-cookie-on-revoke
fix: Clear cookies when revoke_session is called
2 parents 59e1a46 + e658c43 commit 5f9f3e1

File tree

3 files changed

+78
-8
lines changed

3 files changed

+78
-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: 70 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,18 +12,29 @@
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
2127
from supertokens_python.recipe.session.asyncio import (
2228
get_all_session_handles_for_user,
2329
get_session_information,
30+
regenerate_access_token,
31+
)
32+
from supertokens_python.recipe.session.asyncio import (
33+
revoke_session as asyncio_revoke_session,
34+
)
35+
from supertokens_python.recipe.session.asyncio import (
2436
update_access_token_payload,
2537
update_session_data,
26-
regenerate_access_token,
2738
)
2839
from supertokens_python.recipe.session.recipe_implementation import RecipeImplementation
2940
from supertokens_python.recipe.session.session_functions import (
@@ -32,7 +43,6 @@
3243
refresh_session,
3344
revoke_session,
3445
)
35-
3646
from tests.utils import clean_st, reset, setup_st, start_st
3747

3848

@@ -211,3 +221,60 @@ async def test_creating_many_sessions_for_one_user_and_looping():
211221
assert is_updated is False
212222
is_updated = await update_session_data("invalidHandle", {"foo": "bar"})
213223
assert is_updated is False
224+
225+
226+
@fixture(scope="function")
227+
async def driver_config_client():
228+
app = FastAPI()
229+
app.add_middleware(get_middleware())
230+
231+
@app.get("/")
232+
async def home(_request: Request): # type: ignore
233+
return {"hello": "world"}
234+
235+
return TestClient(app)
236+
237+
238+
@mark.asyncio
239+
async def test_signout_api_works_even_if_session_is_deleted_after_creation(
240+
driver_config_client: TestClient,
241+
):
242+
init(
243+
supertokens_config=SupertokensConfig("http://localhost:3567"),
244+
app_info=InputAppInfo(
245+
app_name="SuperTokens Demo",
246+
api_domain="https://api.supertokens.io",
247+
website_domain="supertokens.io",
248+
),
249+
framework="fastapi",
250+
recipe_list=[session.init(anti_csrf="VIA_TOKEN")],
251+
)
252+
start_st()
253+
254+
s = SessionRecipe.get_instance()
255+
if not isinstance(s.recipe_implementation, RecipeImplementation):
256+
raise Exception("Should never come here")
257+
user_id = "user_id"
258+
259+
response = await create_new_session(s.recipe_implementation, user_id, {}, {})
260+
261+
session_handle = response["session"]["handle"]
262+
263+
revoked = await asyncio_revoke_session(session_handle)
264+
assert revoked
265+
266+
signout_response = driver_config_client.post(
267+
url="/auth/signout",
268+
cookies={
269+
"sAccessToken": response["accessToken"]["token"],
270+
"sIdRefreshToken": response["idRefreshToken"]["token"],
271+
},
272+
headers={"anti-csrf": response.get("antiCsrfToken", "")},
273+
)
274+
275+
assert signout_response.json() == {"status": "OK"}
276+
277+
assert (
278+
signout_response.headers["set-cookie"]
279+
== """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"""
280+
)

0 commit comments

Comments
 (0)