[0.9.28] - OAuth/Auth with httpOnly cookie
All checks were successful
Deploy on push / deploy (push) Successful in 4m32s
All checks were successful
Deploy on push / deploy (push) Successful in 4m32s
This commit is contained in:
@@ -9,7 +9,14 @@ from starlette.responses import JSONResponse
|
||||
|
||||
from auth.utils import extract_token_from_request, get_auth_token_from_context, get_user_data_by_token
|
||||
from services.auth import auth_service
|
||||
from settings import SESSION_COOKIE_NAME
|
||||
from settings import (
|
||||
SESSION_COOKIE_DOMAIN,
|
||||
SESSION_COOKIE_HTTPONLY,
|
||||
SESSION_COOKIE_MAX_AGE,
|
||||
SESSION_COOKIE_NAME,
|
||||
SESSION_COOKIE_SAMESITE,
|
||||
SESSION_COOKIE_SECURE,
|
||||
)
|
||||
from storage.schema import mutation, query, type_author
|
||||
from utils.logger import root_logger as logger
|
||||
|
||||
@@ -84,20 +91,36 @@ async def login(_: None, info: GraphQLResolveInfo, **kwargs: Any) -> dict[str, A
|
||||
|
||||
result = await auth_service.login(email, password, request)
|
||||
|
||||
# Устанавливаем cookie если есть токен
|
||||
if result.get("success") and result.get("token") and request:
|
||||
# Устанавливаем httpOnly cookie если есть токен
|
||||
if result.get("success") and result.get("token"):
|
||||
try:
|
||||
if not hasattr(info.context, "response"):
|
||||
response = info.context.get("response")
|
||||
if not response:
|
||||
response = JSONResponse({})
|
||||
response.set_cookie(
|
||||
key=SESSION_COOKIE_NAME,
|
||||
value=result["token"],
|
||||
httponly=True,
|
||||
secure=True,
|
||||
samesite="strict",
|
||||
max_age=86400 * 30,
|
||||
)
|
||||
info.context["response"] = response
|
||||
|
||||
response.set_cookie(
|
||||
key=SESSION_COOKIE_NAME,
|
||||
value=result["token"],
|
||||
httponly=SESSION_COOKIE_HTTPONLY,
|
||||
secure=SESSION_COOKIE_SECURE,
|
||||
samesite=SESSION_COOKIE_SAMESITE
|
||||
if SESSION_COOKIE_SAMESITE in ["strict", "lax", "none"]
|
||||
else "none",
|
||||
max_age=SESSION_COOKIE_MAX_AGE,
|
||||
path="/",
|
||||
domain=SESSION_COOKIE_DOMAIN, # ✅ КРИТИЧНО для поддоменов
|
||||
)
|
||||
|
||||
logger.info(
|
||||
f"✅ Email/Password: httpOnly cookie установлен для пользователя {result.get('author', {}).get('id')}"
|
||||
)
|
||||
|
||||
# 💋 НЕ возвращаем токен клиенту - он в httpOnly cookie
|
||||
result_without_token = result.copy()
|
||||
result_without_token["token"] = None # Скрываем токен от JavaScript
|
||||
return result_without_token
|
||||
|
||||
except Exception as cookie_error:
|
||||
logger.warning(f"Не удалось установить cookie: {cookie_error}")
|
||||
|
||||
@@ -129,7 +152,11 @@ async def logout(_: None, info: GraphQLResolveInfo, **kwargs: Any) -> dict[str,
|
||||
# Удаляем cookie
|
||||
if request and hasattr(info.context, "response"):
|
||||
try:
|
||||
info.context["response"].delete_cookie(SESSION_COOKIE_NAME)
|
||||
info.context["response"].delete_cookie(
|
||||
key=SESSION_COOKIE_NAME,
|
||||
path="/",
|
||||
domain=SESSION_COOKIE_DOMAIN, # ✅ КРИТИЧНО: тот же domain что при установке
|
||||
)
|
||||
except Exception as e:
|
||||
logger.warning(f"Не удалось удалить cookie: {e}")
|
||||
|
||||
@@ -174,10 +201,14 @@ async def refresh_token(_: None, info: GraphQLResolveInfo, **kwargs: Any) -> dic
|
||||
info.context["response"].set_cookie(
|
||||
key=SESSION_COOKIE_NAME,
|
||||
value=result["token"],
|
||||
httponly=True,
|
||||
secure=True,
|
||||
samesite="strict",
|
||||
max_age=86400 * 30,
|
||||
httponly=SESSION_COOKIE_HTTPONLY,
|
||||
secure=SESSION_COOKIE_SECURE,
|
||||
samesite=SESSION_COOKIE_SAMESITE
|
||||
if SESSION_COOKIE_SAMESITE in ["strict", "lax", "none"]
|
||||
else "none",
|
||||
max_age=SESSION_COOKIE_MAX_AGE,
|
||||
path="/",
|
||||
domain=SESSION_COOKIE_DOMAIN, # ✅ КРИТИЧНО для поддоменов
|
||||
)
|
||||
except Exception as e:
|
||||
logger.warning(f"Не удалось обновить cookie: {e}")
|
||||
|
||||
Reference in New Issue
Block a user