You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The rag-server's comprehensive RBAC system (merged in #672) is fully implemented — it fetches user identity from the OIDC userinfo endpoint, extracts email and groups, and maps them to roles (admin/ingestor/viewer) with Redis caching. None of this works in prod because JWKS validation fails before userinfo is ever called.
Auth flow in rbac.py (require_authenticated_user):
1. validate_token() via JWKS ← FAILS for Duo access_token
2. fetch_userinfo() → email/groups ← never reached
3. map groups → role ← never reached
4. cache in Redis ← never reached
Why JWKS fails
Duo issues access tokens signed with a key whose ID (ce989860..., a 64-char hex SHA-256) is not published in Duo's public JWKS for the configured client. This is expected — access tokens are intended for Duo's own resource servers, not for third-party JWKS validation. The rag-server's attempt to validate them via JWKS is architecturally incorrect for this token type.
Consequences in prod (plat-prod-use2-1)
Every caipe-ui → rag-server REST call returns 401 Unauthorized
Knowledge Bases tab is completely broken for all users
The supervisor works only because it uses MCP (no auth header → trusted network grants admin)
PR fix(ui): skip Bearer token for internal rag-server URLs #1127 worked around this by stripping the auth header entirely for internal URLs — but this bypasses the RBAC system and gives all UI users the same TRUSTED_NETWORK_DEFAULT_ROLE regardless of their actual group membership
Root Cause
validate_token() in auth.py is a hard prerequisite for the userinfo fetch. There is no fallback: if JWKS validation fails, the request is rejected with 401 immediately.
# rbac.py — require_authenticated_user()provider, access_claims=awaitauth_manager.validate_token(token) # hard fail# ...userinfo=awaitauth_manager.fetch_userinfo(token, provider) # never reached
Correct Fix
In auth.py, when JWKS validation fails, fall back to the userinfo endpoint directly. If the OIDC provider's userinfo endpoint accepts the token and returns valid claims, the token is implicitly valid — the provider has verified it server-side.
Problem
The rag-server's comprehensive RBAC system (merged in #672) is fully implemented — it fetches user identity from the OIDC userinfo endpoint, extracts email and groups, and maps them to roles (admin/ingestor/viewer) with Redis caching. None of this works in prod because JWKS validation fails before userinfo is ever called.
Auth flow in
rbac.py(require_authenticated_user):Why JWKS fails
Duo issues access tokens signed with a key whose ID (
ce989860..., a 64-char hex SHA-256) is not published in Duo's public JWKS for the configured client. This is expected — access tokens are intended for Duo's own resource servers, not for third-party JWKS validation. The rag-server's attempt to validate them via JWKS is architecturally incorrect for this token type.Consequences in prod (plat-prod-use2-1)
401 UnauthorizedTRUSTED_NETWORK_DEFAULT_ROLEregardless of their actual group membershipRoot Cause
validate_token()inauth.pyis a hard prerequisite for the userinfo fetch. There is no fallback: if JWKS validation fails, the request is rejected with 401 immediately.Correct Fix
In
auth.py, when JWKS validation fails, fall back to the userinfo endpoint directly. If the OIDC provider's userinfo endpoint accepts the token and returns valid claims, the token is implicitly valid — the provider has verified it server-side.With this fix:
caipe-admins→ admin, others → viewerRelated