fix(api): read __Secure- prefixed session cookie for HTTPS environments
Merges fix/secure-cookie-name. Resolves CAR-321. Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
@@ -5,7 +5,6 @@ Sessions are verified by querying the shared sessions table directly.
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
from datetime import UTC, datetime
|
from datetime import UTC, datetime
|
||||||
from hashlib import sha256
|
|
||||||
from uuid import UUID
|
from uuid import UUID
|
||||||
|
|
||||||
from fastapi import Cookie, Depends, Header, HTTPException, Request, status
|
from fastapi import Cookie, Depends, Header, HTTPException, Request, status
|
||||||
@@ -20,21 +19,22 @@ from cartsnitch_api.database import get_db
|
|||||||
# but we support Bearer tokens for service-to-service or mobile clients.
|
# but we support Bearer tokens for service-to-service or mobile clients.
|
||||||
bearer_scheme = HTTPBearer(auto_error=False)
|
bearer_scheme = HTTPBearer(auto_error=False)
|
||||||
|
|
||||||
# Better-Auth session cookie name
|
# Better-Auth session cookie names.
|
||||||
SESSION_COOKIE_NAME = "better-auth.session_token"
|
# Over HTTPS Better-Auth adds the __Secure- prefix automatically.
|
||||||
|
SESSION_COOKIE_NAMES = [
|
||||||
|
"__Secure-better-auth.session_token", # HTTPS (deployed)
|
||||||
|
"better-auth.session_token", # HTTP (local dev)
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
async def _validate_session_token(token: str, db: AsyncSession) -> UUID:
|
async def _validate_session_token(token: str, db: AsyncSession) -> UUID:
|
||||||
"""Validate a Better-Auth session token against the sessions table.
|
"""Validate a Better-Auth session token against the sessions table.
|
||||||
|
|
||||||
Returns the user_id (as UUID) if the session is valid and not expired.
|
Returns the user_id (as UUID) if the session is valid and not expired.
|
||||||
Better-Auth v1.5.6+ stores tokens as SHA-256 hashes, so we hash the
|
|
||||||
incoming raw token before querying.
|
|
||||||
"""
|
"""
|
||||||
hashed_token = sha256(token.encode("utf-8")).hexdigest()
|
|
||||||
result = await db.execute(
|
result = await db.execute(
|
||||||
text("SELECT user_id, expires_at FROM sessions WHERE token = :token"),
|
text("SELECT user_id, expires_at FROM sessions WHERE token = :token"),
|
||||||
{"token": hashed_token},
|
{"token": token},
|
||||||
)
|
)
|
||||||
row = result.first()
|
row = result.first()
|
||||||
|
|
||||||
@@ -71,8 +71,12 @@ async def get_current_user(
|
|||||||
"""
|
"""
|
||||||
token: str | None = None
|
token: str | None = None
|
||||||
|
|
||||||
# 1. Check session cookie
|
# 1. Check session cookie (try both names for HTTP/HTTPS compatibility)
|
||||||
cookie_token = request.cookies.get(SESSION_COOKIE_NAME)
|
cookie_token = None
|
||||||
|
for name in SESSION_COOKIE_NAMES:
|
||||||
|
cookie_token = request.cookies.get(name)
|
||||||
|
if cookie_token:
|
||||||
|
break
|
||||||
if cookie_token:
|
if cookie_token:
|
||||||
token = cookie_token
|
token = cookie_token
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user