Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions backend/chainlit/auth/cookie.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
)
_cookie_secure = _cookie_samesite == "none"
if _cookie_root_path := os.environ.get("CHAINLIT_ROOT_PATH", None):
_cookie_path = os.environ.get(_cookie_root_path, "/")
_cookie_path = os.environ.get("CHAINLIT_AUTH_COOKIE_PATH", _cookie_root_path)
else:
_cookie_path = os.environ.get("CHAINLIT_AUTH_COOKIE_PATH", "/")
_state_cookie_lifetime = int(
Expand Down Expand Up @@ -132,6 +132,7 @@ def set_auth_cookie(request: Request, response: Response, token: str):
response.set_cookie(
key=k,
value=chunk,
path=_cookie_path,
Comment thread
cubic-dev-ai[bot] marked this conversation as resolved.
httponly=True,
secure=_cookie_secure,
samesite=_cookie_samesite,
Expand All @@ -144,6 +145,7 @@ def set_auth_cookie(request: Request, response: Response, token: str):
response.set_cookie(
key=_auth_cookie_name,
value=token,
path=_cookie_path,
httponly=True,
secure=_cookie_secure,
samesite=_cookie_samesite,
Expand Down Expand Up @@ -178,6 +180,7 @@ def set_oauth_state_cookie(response: Response, token: str):
response.set_cookie(
_state_cookie_name,
token,
path=_cookie_path,
httponly=True,
samesite=_cookie_samesite,
secure=_cookie_secure,
Expand All @@ -196,4 +199,4 @@ def validate_oauth_state_cookie(request: Request, state: str):

def clear_oauth_state_cookie(response: Response):
"""Oauth complete, delete state token."""
response.delete_cookie(_state_cookie_name) # Do we set path here?
response.delete_cookie(_state_cookie_name, path=_cookie_path)
3 changes: 2 additions & 1 deletion backend/chainlit/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@

from chainlit.auth import create_jwt, decode_jwt, get_configuration, get_current_user
from chainlit.auth.cookie import (
_cookie_path,
clear_auth_cookie,
clear_oauth_state_cookie,
set_auth_cookie,
Expand Down Expand Up @@ -770,7 +771,7 @@ async def set_session_cookie(request: Request, response: Response):
response.set_cookie(
key="X-Chainlit-Session-id",
value=session_id,
path="/",
path=_cookie_path,
httponly=True,
secure=not is_local,
samesite="lax" if is_local else "none",
Expand Down
24 changes: 24 additions & 0 deletions backend/tests/auth/test_cookie.py
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,30 @@ def test_state_cookie_lifetime_custom(monkeypatch):
assert cookie_module._state_cookie_lifetime == 600


def test_cookie_path_defaults_to_root(monkeypatch):
"""When neither CHAINLIT_ROOT_PATH nor CHAINLIT_AUTH_COOKIE_PATH is set, _cookie_path defaults to '/'."""
monkeypatch.delenv("CHAINLIT_ROOT_PATH", raising=False)
monkeypatch.delenv("CHAINLIT_AUTH_COOKIE_PATH", raising=False)
importlib.reload(cookie_module)
assert cookie_module._cookie_path == "/"


def test_cookie_path_uses_root_path(monkeypatch):
"""When CHAINLIT_ROOT_PATH is set, _cookie_path uses its value."""
monkeypatch.setenv("CHAINLIT_ROOT_PATH", "/app1")
monkeypatch.delenv("CHAINLIT_AUTH_COOKIE_PATH", raising=False)
importlib.reload(cookie_module)
assert cookie_module._cookie_path == "/app1"


def test_cookie_path_explicit_overrides_root_path(monkeypatch):
"""CHAINLIT_AUTH_COOKIE_PATH takes precedence over CHAINLIT_ROOT_PATH."""
monkeypatch.setenv("CHAINLIT_ROOT_PATH", "/app1")
monkeypatch.setenv("CHAINLIT_AUTH_COOKIE_PATH", "/custom")
importlib.reload(cookie_module)
assert cookie_module._cookie_path == "/custom"


def test_clear_auth_cookie(client):
"""Test cookie clearing removes all chunks."""
# Set initial token
Expand Down