import logging import time from typing import Any, Optional from urllib.parse import quote import jwt from open_webui.env import ( FORWARD_USER_INFO_HEADER_JWT, FORWARD_USER_INFO_HEADER_JWT_EXPIRES_SECONDS, FORWARD_USER_INFO_HEADER_JWT_SECRET, FORWARD_USER_INFO_HEADER_USER_EMAIL, FORWARD_USER_INFO_HEADER_USER_ID, FORWARD_USER_INFO_HEADER_USER_NAME, FORWARD_USER_INFO_HEADER_USER_ROLE, ) log = logging.getLogger(__name__) def _mint_forward_user_jwt(user: Any) -> str: now = int(time.time()) payload = { 'sub': str(user.id), 'email': str(user.email), 'name': str(user.name), 'role': str(user.role), 'iss': 'open-webui', 'iat': now, 'exp': now + FORWARD_USER_INFO_HEADER_JWT_EXPIRES_SECONDS, } return jwt.encode(payload, FORWARD_USER_INFO_HEADER_JWT_SECRET, algorithm='HS256') def include_user_info_headers(headers: dict, user: Optional[Any] = None) -> dict: """ Forward user identity to external backends: signed JWT in FORWARD_USER_INFO_HEADER_JWT if FORWARD_USER_INFO_HEADER_JWT_SECRET is set; otherwise the legacy X-OpenWebUI-User-* headers. """ if user is None: return headers if FORWARD_USER_INFO_HEADER_JWT_SECRET: try: token = _mint_forward_user_jwt(user) return {**headers, FORWARD_USER_INFO_HEADER_JWT: token} except Exception: log.exception( 'Failed to mint %s; falling back to plain user-info headers.', FORWARD_USER_INFO_HEADER_JWT, ) return { **headers, FORWARD_USER_INFO_HEADER_USER_NAME: quote(user.name, safe=' '), FORWARD_USER_INFO_HEADER_USER_ID: user.id, FORWARD_USER_INFO_HEADER_USER_EMAIL: user.email, FORWARD_USER_INFO_HEADER_USER_ROLE: user.role, } def get_custom_headers(custom_headers: dict, user=None, metadata: dict = None) -> dict: if not custom_headers or not isinstance(custom_headers, dict): return {} metadata = metadata or {} template_vars = { '{{CHAT_ID}}': metadata.get('chat_id', '') or '', '{{MESSAGE_ID}}': metadata.get('message_id', '') or '', '{{USER_ID}}': (user.id if user else '') or '', '{{USER_NAME}}': (user.name if user else '') or '', '{{USER_EMAIL}}': (user.email if user else '') or '', '{{USER_ROLE}}': (user.role if user else '') or '', } parsed_headers = {} for key, value in custom_headers.items(): if not isinstance(value, str): value = str(value) for token, val in template_vars.items(): value = value.replace(token, val) parsed_headers[key] = value return parsed_headers