Cross-Site cookies enabled
This commit is contained in:
parent
130bdfb7cc
commit
35693a61e3
1 changed files with 25 additions and 8 deletions
|
|
@ -24,6 +24,11 @@ REFRESH_TOKEN_EXPIRE_DAYS = int(APP_CONFIG.get("APP_REFRESH_TOKEN_EXPIRY", "7"))
|
|||
APP_API_URL = APP_CONFIG.get("APP_API_URL", "http://localhost:8000")
|
||||
USE_SECURE_COOKIES = APP_API_URL.startswith("https://") if APP_API_URL else False
|
||||
|
||||
# Cross-origin SPA (any host) + API (gateway host): SameSite=None + Secure is required so the
|
||||
# browser sends cookies on credentialed XHR/fetch. HTTP localhost uses Lax (None without Secure is rejected).
|
||||
COOKIE_SAMESITE = "none" if USE_SECURE_COOKIES else "lax"
|
||||
COOKIE_SAMESITE_SET_COOKIE = "None" if USE_SECURE_COOKIES else "Lax"
|
||||
|
||||
|
||||
def createAccessToken(data: dict, expiresDelta: Optional[timedelta] = None) -> Tuple[str, "datetime"]:
|
||||
"""Create a JWT access token and return (token, expiresAt)."""
|
||||
|
|
@ -60,7 +65,7 @@ def setAccessTokenCookie(response: Response, token: str, expiresDelta: Optional[
|
|||
value=token,
|
||||
httponly=True,
|
||||
secure=USE_SECURE_COOKIES, # Only secure in production (HTTPS)
|
||||
samesite="strict",
|
||||
samesite=COOKIE_SAMESITE,
|
||||
path="/",
|
||||
max_age=maxAge
|
||||
)
|
||||
|
|
@ -73,7 +78,7 @@ def setRefreshTokenCookie(response: Response, token: str) -> None:
|
|||
value=token,
|
||||
httponly=True,
|
||||
secure=USE_SECURE_COOKIES, # Only secure in production (HTTPS)
|
||||
samesite="strict",
|
||||
samesite=COOKIE_SAMESITE,
|
||||
path="/",
|
||||
max_age=REFRESH_TOKEN_EXPIRE_DAYS * 24 * 60 * 60
|
||||
)
|
||||
|
|
@ -90,11 +95,17 @@ def clearAccessTokenCookie(response: Response) -> None:
|
|||
# Primary method: Raw Set-Cookie header for guaranteed deletion
|
||||
response.headers.append(
|
||||
"Set-Cookie",
|
||||
f"auth_token=deleted; Path=/; Max-Age=0; Expires=Thu, 01 Jan 1970 00:00:00 GMT; HttpOnly{secure_flag}; SameSite=Strict"
|
||||
f"auth_token=deleted; Path=/; Max-Age=0; Expires=Thu, 01 Jan 1970 00:00:00 GMT; HttpOnly{secure_flag}; SameSite={COOKIE_SAMESITE_SET_COOKIE}"
|
||||
)
|
||||
|
||||
# Fallback: Also use FastAPI's built-in method
|
||||
response.delete_cookie(key="auth_token", path="/")
|
||||
# Fallback: Also use FastAPI's built-in method (match SameSite/Secure for invalidation)
|
||||
response.delete_cookie(
|
||||
key="auth_token",
|
||||
path="/",
|
||||
secure=USE_SECURE_COOKIES,
|
||||
httponly=True,
|
||||
samesite=COOKIE_SAMESITE,
|
||||
)
|
||||
|
||||
|
||||
def clearRefreshTokenCookie(response: Response) -> None:
|
||||
|
|
@ -108,10 +119,16 @@ def clearRefreshTokenCookie(response: Response) -> None:
|
|||
# Primary method: Raw Set-Cookie header for guaranteed deletion
|
||||
response.headers.append(
|
||||
"Set-Cookie",
|
||||
f"refresh_token=deleted; Path=/; Max-Age=0; Expires=Thu, 01 Jan 1970 00:00:00 GMT; HttpOnly{secure_flag}; SameSite=Strict"
|
||||
f"refresh_token=deleted; Path=/; Max-Age=0; Expires=Thu, 01 Jan 1970 00:00:00 GMT; HttpOnly{secure_flag}; SameSite={COOKIE_SAMESITE_SET_COOKIE}"
|
||||
)
|
||||
|
||||
# Fallback: Also use FastAPI's built-in method
|
||||
response.delete_cookie(key="refresh_token", path="/")
|
||||
# Fallback: Also use FastAPI's built-in method (match SameSite/Secure for invalidation)
|
||||
response.delete_cookie(
|
||||
key="refresh_token",
|
||||
path="/",
|
||||
secure=USE_SECURE_COOKIES,
|
||||
httponly=True,
|
||||
samesite=COOKIE_SAMESITE,
|
||||
)
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue