refac: oauth session management

This commit is contained in:
Timothy Jaeryang Baek
2026-02-20 16:49:43 -06:00
parent f5e5632afc
commit ae05586fda
3 changed files with 24 additions and 4 deletions
+6
View File
@@ -557,6 +557,12 @@ OAUTH_SESSION_TOKEN_ENCRYPTION_KEY = os.environ.get(
"OAUTH_SESSION_TOKEN_ENCRYPTION_KEY", WEBUI_SECRET_KEY "OAUTH_SESSION_TOKEN_ENCRYPTION_KEY", WEBUI_SECRET_KEY
) )
# Maximum number of concurrent OAuth sessions per user per provider
# This prevents unbounded session growth while allowing multi-device usage
OAUTH_MAX_SESSIONS_PER_USER = int(
os.environ.get("OAUTH_MAX_SESSIONS_PER_USER", "10")
)
# Token Exchange Configuration # Token Exchange Configuration
# Allows external apps to exchange OAuth tokens for OpenWebUI tokens # Allows external apps to exchange OAuth tokens for OpenWebUI tokens
ENABLE_OAUTH_TOKEN_EXCHANGE = ( ENABLE_OAUTH_TOKEN_EXCHANGE = (
@@ -188,6 +188,7 @@ class OAuthSessionTable:
session = ( session = (
db.query(OAuthSession) db.query(OAuthSession)
.filter_by(provider=provider, user_id=user_id) .filter_by(provider=provider, user_id=user_id)
.order_by(OAuthSession.created_at.desc())
.first() .first()
) )
if session: if session:
+17 -4
View File
@@ -69,6 +69,7 @@ from open_webui.env import (
ENABLE_OAUTH_ID_TOKEN_COOKIE, ENABLE_OAUTH_ID_TOKEN_COOKIE,
ENABLE_OAUTH_EMAIL_FALLBACK, ENABLE_OAUTH_EMAIL_FALLBACK,
OAUTH_CLIENT_INFO_ENCRYPTION_KEY, OAUTH_CLIENT_INFO_ENCRYPTION_KEY,
OAUTH_MAX_SESSIONS_PER_USER,
) )
from open_webui.utils.misc import parse_duration from open_webui.utils.misc import parse_duration
from open_webui.utils.auth import get_password_hash, create_token from open_webui.utils.auth import get_password_hash, create_token
@@ -1679,11 +1680,23 @@ class OAuthManager:
if "expires_in" in token and "expires_at" not in token: if "expires_in" in token and "expires_at" not in token:
token["expires_at"] = datetime.now().timestamp() + token["expires_in"] token["expires_at"] = datetime.now().timestamp() + token["expires_in"]
# Clean up any existing sessions for this user/provider first # Enforce max concurrent sessions per user/provider to prevent
# unbounded growth while allowing multi-device usage
sessions = OAuthSessions.get_sessions_by_user_id(user.id, db=db) sessions = OAuthSessions.get_sessions_by_user_id(user.id, db=db)
for session in sessions: provider_sessions = sorted(
if session.provider == provider: [
OAuthSessions.delete_session_by_id(session.id, db=db) for session in sessions
if session.provider == provider
],
key=lambda session: session.created_at,
reverse=True,
)
# Keep the newest sessions up to the limit, prune the rest
if len(provider_sessions) >= OAUTH_MAX_SESSIONS_PER_USER:
for old_session in provider_sessions[
OAUTH_MAX_SESSIONS_PER_USER - 1 :
]:
OAuthSessions.delete_session_by_id(old_session.id, db=db)
session = OAuthSessions.create_session( session = OAuthSessions.create_session(
user_id=user.id, user_id=user.id,