From 5462c02af0500bd5d341d9a7f9c934dc08c28f08 Mon Sep 17 00:00:00 2001 From: Classic298 <27028174+Classic298@users.noreply.github.com> Date: Tue, 11 Aug 2026 04:06:31 +0200 Subject: [PATCH] fix: OIDC login fails when the provider adds a private JOSE header (#28065) Logging in through CyberArk Identity dies at the callback with "Unsupported {'app_id'} in header" and the user sees "The email or password provided is incorrect". Any provider that puts a vendor-specific parameter in the ID token header hits this; CAS was already patched by name, CyberArk is the next one. Authlib 1.7 verifies ID tokens with joserfc, which rejects header parameters it does not recognise. The old fix registered `client_id` so CAS would work, which only ever fixes one provider at a time. This turns off the unknown-header rejection instead, so any private header parameter is ignored rather than fatal. Signature verification, the algorithm allowlist, `crit` handling and value validation of registered headers all still run, so nothing that actually protects the token is relaxed. Fixes #28062 --- backend/open_webui/utils/oauth.py | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/backend/open_webui/utils/oauth.py b/backend/open_webui/utils/oauth.py index 265067390a..2ef1bee69f 100644 --- a/backend/open_webui/utils/oauth.py +++ b/backend/open_webui/utils/oauth.py @@ -10,6 +10,7 @@ import urllib import uuid from dataclasses import dataclass, field from datetime import datetime, timedelta +from functools import partialmethod from types import SimpleNamespace from typing import Literal, Optional @@ -25,7 +26,6 @@ from fastapi import ( ) from joserfc.errors import BadSignatureError from joserfc.jws import JWSRegistry -from joserfc.registry import HeaderParameter from mcp.shared.auth import ( OAuthClientMetadata as MCPOAuthClientMetadata, ) @@ -90,6 +90,10 @@ from open_webui.utils.misc import parse_duration from open_webui.utils.validate import validate_profile_image_url from starlette.responses import RedirectResponse +# Some IdPs put private params in ID token JOSE headers (CAS: client_id, CyberArk: app_id). +# Authlib exposes no way to pass a registry, so relax it globally; crit, alg and signature checks still apply. +JWSRegistry.__init__ = partialmethod(JWSRegistry.__init__, strict_check_header=False) + class OAuthClientMetadata(MCPOAuthClientMetadata): token_endpoint_auth_method: Literal['none', 'client_secret_basic', 'client_secret_post'] = 'client_secret_post' @@ -193,14 +197,6 @@ DEFAULT_TOKEN_EXPIRY_SECONDS = 3600 NON_EXPIRING_TOKEN_EXPIRES_AT = 253402300799 # 9999-12-31 23:59:59 UTC -# Apereo CAS includes client_id in ID token JWS headers; Authlib 1.7/joserfc -# rejects unknown headers unless we register the provider extension. -JWSRegistry.default_header_registry.setdefault( - 'client_id', - HeaderParameter('OAuth client identifier', 'str'), -) - - def _normalize_token_expiry(token: dict) -> dict: """Ensure a token dict always has a numeric ``expires_at``.