Skip to content

Commit f7fed4f

Browse files
committed
Fix the automatic logout functionality when the backend returns 401 or 403 error code
1 parent 1c7f76b commit f7fed4f

File tree

5 files changed

+24
-21
lines changed

5 files changed

+24
-21
lines changed

backend/app/api/deps.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
from collections.abc import Generator
2-
from typing import Annotated, Optional
2+
from typing import Annotated
33

44
import jwt
55
from fastapi import Depends, HTTPException, status, Cookie

backend/app/api/routes/login.py

Lines changed: 3 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ def login_access_token(
2525
session: SessionDep, form_data: Annotated[OAuth2PasswordRequestForm, Depends()]
2626
) -> JSONResponse:
2727
"""
28-
OAuth2 compatible token login, get an access token for future requests (sent in a HTTP-only cookie)
28+
OAuth2-compatible token login: get an access token for future requests (sent in an HTTP-only cookie)
2929
"""
3030
user = crud.authenticate(
3131
session=session, email=form_data.username, password=form_data.password
@@ -35,7 +35,7 @@ def login_access_token(
3535
elif not user.is_active:
3636
raise HTTPException(status_code=400, detail="Inactive user")
3737
access_token_expires = timedelta(minutes=settings.ACCESS_TOKEN_EXPIRE_MINUTES)
38-
return security.set_response_cookie(user.id, access_token_expires)
38+
return security.set_auth_cookie(user.id, access_token_expires)
3939

4040

4141
@router.post("/login/test-token", response_model=UserPublic)
@@ -124,15 +124,4 @@ def logout() -> JSONResponse:
124124
"""
125125
Delete the HTTP-only cookie during logout
126126
"""
127-
128-
response = JSONResponse(content={"message": "Logout successful"})
129-
130-
response.delete_cookie(
131-
key="http_only_auth_cookie",
132-
path="/",
133-
domain=None,
134-
httponly=True,
135-
samesite="lax",
136-
secure=False, # Should be True in production
137-
)
138-
return response
127+
return security.delete_auth_cookie()

backend/app/core/security.py

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import os
12
from datetime import datetime, timedelta, timezone
23
from typing import Any
34
import jwt
@@ -18,19 +19,34 @@ def create_access_token(subject: str | Any, expires_delta: timedelta) -> str:
1819
return encoded_jwt
1920

2021

21-
def set_response_cookie(subject: str | Any, expires_delta: timedelta) -> Response:
22+
def set_auth_cookie(subject: str | Any, expires_delta: timedelta) -> Response:
2223
access_token = create_access_token(subject, expires_delta)
2324
response = JSONResponse(
2425
content={"message": "Login successful"}
2526
)
27+
# Note: The secure flag on cookies ensures they're only sent over encrypted HTTPS connections. For local development (HTTP) set it to False
2628
response.set_cookie(
2729
key="http_only_auth_cookie",
2830
value=access_token,
2931
httponly=True,
3032
max_age=3600,
3133
expires=3600,
3234
samesite="lax",
33-
secure=False,
35+
secure=True,
36+
)
37+
return response
38+
39+
40+
def delete_auth_cookie() -> Response:
41+
response = JSONResponse(content={"message": "Logout successful"})
42+
43+
response.delete_cookie(
44+
key="http_only_auth_cookie",
45+
path="/",
46+
domain=None,
47+
httponly=True,
48+
samesite="lax",
49+
secure=False, # Should be True in production
3450
)
3551
return response
3652

frontend/src/client/sdk.gen.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,7 @@ export class LoginService {
232232
* @throws ApiError
233233
*/
234234
public static testToken(): CancelablePromise<LoginTestTokenResponse> {
235+
console.log("test token")
235236
return __request(OpenAPI, {
236237
method: "POST",
237238
url: "/api/v1/login/test-token",

frontend/src/main.tsx

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,10 @@ import { ApiError, OpenAPI } from "./client"
1313
import { CustomProvider } from "./components/ui/provider"
1414

1515
OpenAPI.BASE = import.meta.env.VITE_API_URL
16-
OpenAPI.TOKEN = async () => {
17-
return localStorage.getItem("access_token") || ""
18-
}
1916

2017
const handleApiError = (error: Error) => {
2118
if (error instanceof ApiError && [401, 403].includes(error.status)) {
22-
localStorage.removeItem("access_token")
19+
localStorage.removeItem("is_authenticated")
2320
window.location.href = "/login"
2421
}
2522
}

0 commit comments

Comments
 (0)