From 412923dc915065fd264228ad18db7991db88b7dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antti=20Pyykk=C3=B6nen?= Date: Thu, 23 Jan 2025 16:16:50 +0200 Subject: [PATCH] feat: separate cookie settings between session & auth cookies Introducing two new env config options to control cookies settings regarding authentication. These values are taken into use when setting 'token' and 'oauth_id_token'. To maintain backwards compatibility, the original session cookie values are used as fallback. Separation is done to prevent issues with the session cookie. When the config value was set as 'strict', the oauth flow was broken (since the session cookie was not provided after the callback). Providing a separate config for auth & session cookies allows us to keep the 'strict' settings for auth related cookies, while also allowing the session cookie to behave as intended (e.g., by configuring it as 'lax'). The original config was added in commit #af4f8aa. However a later commit #a2e889c reused this config option for other type of cookies, which was not the original intent. --- backend/open_webui/env.py | 17 +++++++++-------- backend/open_webui/routers/auths.py | 16 ++++++++-------- backend/open_webui/utils/oauth.py | 10 +++++----- 3 files changed, 22 insertions(+), 21 deletions(-) diff --git a/backend/open_webui/env.py b/backend/open_webui/env.py index 77e632ccc..b589e9490 100644 --- a/backend/open_webui/env.py +++ b/backend/open_webui/env.py @@ -356,15 +356,16 @@ WEBUI_SECRET_KEY = os.environ.get( ), # DEPRECATED: remove at next major version ) -WEBUI_SESSION_COOKIE_SAME_SITE = os.environ.get( - "WEBUI_SESSION_COOKIE_SAME_SITE", - os.environ.get("WEBUI_SESSION_COOKIE_SAME_SITE", "lax"), -) +WEBUI_SESSION_COOKIE_SAME_SITE = os.environ.get("WEBUI_SESSION_COOKIE_SAME_SITE", "lax") -WEBUI_SESSION_COOKIE_SECURE = os.environ.get( - "WEBUI_SESSION_COOKIE_SECURE", - os.environ.get("WEBUI_SESSION_COOKIE_SECURE", "false").lower() == "true", -) +WEBUI_SESSION_COOKIE_SECURE = os.environ.get("WEBUI_SESSION_COOKIE_SECURE", "false").lower() == "true" + +WEBUI_AUTH_COOKIE_SAME_SITE = os.environ.get("WEBUI_AUTH_COOKIE_SAME_SITE", WEBUI_SESSION_COOKIE_SAME_SITE) + +WEBUI_AUTH_COOKIE_SECURE = os.environ.get( + "WEBUI_AUTH_COOKIE_SECURE", + os.environ.get("WEBUI_SESSION_COOKIE_SECURE", "false") +).lower() == "true" if WEBUI_AUTH and WEBUI_SECRET_KEY == "": raise ValueError(ERROR_MESSAGES.ENV_VAR_NOT_FOUND) diff --git a/backend/open_webui/routers/auths.py b/backend/open_webui/routers/auths.py index 47baeb0ac..d7c4fa013 100644 --- a/backend/open_webui/routers/auths.py +++ b/backend/open_webui/routers/auths.py @@ -25,8 +25,8 @@ from open_webui.env import ( WEBUI_AUTH, WEBUI_AUTH_TRUSTED_EMAIL_HEADER, WEBUI_AUTH_TRUSTED_NAME_HEADER, - WEBUI_SESSION_COOKIE_SAME_SITE, - WEBUI_SESSION_COOKIE_SECURE, + WEBUI_AUTH_COOKIE_SAME_SITE, + WEBUI_AUTH_COOKIE_SECURE, SRC_LOG_LEVELS, ) from fastapi import APIRouter, Depends, HTTPException, Request, status @@ -95,8 +95,8 @@ async def get_session_user( value=token, expires=datetime_expires_at, httponly=True, # Ensures the cookie is not accessible via JavaScript - samesite=WEBUI_SESSION_COOKIE_SAME_SITE, - secure=WEBUI_SESSION_COOKIE_SECURE, + samesite=WEBUI_AUTH_COOKIE_SAME_SITE, + secure=WEBUI_AUTH_COOKIE_SECURE, ) user_permissions = get_permissions( @@ -378,8 +378,8 @@ async def signin(request: Request, response: Response, form_data: SigninForm): value=token, expires=datetime_expires_at, httponly=True, # Ensures the cookie is not accessible via JavaScript - samesite=WEBUI_SESSION_COOKIE_SAME_SITE, - secure=WEBUI_SESSION_COOKIE_SECURE, + samesite=WEBUI_AUTH_COOKIE_SAME_SITE, + secure=WEBUI_AUTH_COOKIE_SECURE, ) user_permissions = get_permissions( @@ -473,8 +473,8 @@ async def signup(request: Request, response: Response, form_data: SignupForm): value=token, expires=datetime_expires_at, httponly=True, # Ensures the cookie is not accessible via JavaScript - samesite=WEBUI_SESSION_COOKIE_SAME_SITE, - secure=WEBUI_SESSION_COOKIE_SECURE, + samesite=WEBUI_AUTH_COOKIE_SAME_SITE, + secure=WEBUI_AUTH_COOKIE_SECURE, ) if request.app.state.config.WEBHOOK_URL: diff --git a/backend/open_webui/utils/oauth.py b/backend/open_webui/utils/oauth.py index 1ae6d4aa7..b336f0631 100644 --- a/backend/open_webui/utils/oauth.py +++ b/backend/open_webui/utils/oauth.py @@ -35,7 +35,7 @@ from open_webui.config import ( AppConfig, ) from open_webui.constants import ERROR_MESSAGES, WEBHOOK_MESSAGES -from open_webui.env import WEBUI_SESSION_COOKIE_SAME_SITE, WEBUI_SESSION_COOKIE_SECURE +from open_webui.env import WEBUI_AUTH_COOKIE_SAME_SITE, WEBUI_AUTH_COOKIE_SECURE from open_webui.utils.misc import parse_duration from open_webui.utils.auth import get_password_hash, create_token from open_webui.utils.webhook import post_webhook @@ -323,8 +323,8 @@ class OAuthManager: key="token", value=jwt_token, httponly=True, # Ensures the cookie is not accessible via JavaScript - samesite=WEBUI_SESSION_COOKIE_SAME_SITE, - secure=WEBUI_SESSION_COOKIE_SECURE, + samesite=WEBUI_AUTH_COOKIE_SAME_SITE, + secure=WEBUI_AUTH_COOKIE_SECURE, ) if ENABLE_OAUTH_SIGNUP.value: @@ -333,8 +333,8 @@ class OAuthManager: key="oauth_id_token", value=oauth_id_token, httponly=True, - samesite=WEBUI_SESSION_COOKIE_SAME_SITE, - secure=WEBUI_SESSION_COOKIE_SECURE, + samesite=WEBUI_AUTH_COOKIE_SAME_SITE, + secure=WEBUI_AUTH_COOKIE_SECURE, ) # Redirect back to the frontend with the JWT token redirect_url = f"{request.base_url}auth#token={jwt_token}"