SSO Config Validation can result in incorrect Issuer URL

(#611) Bug Fixed self-hosting

Summary

Clicking "Save SSO Settings" when "Enable SSO" is checked can cause the "Issuer" field to get changed (in particular, URLs without a trailing slash will have one added). I assume this happens somewhere in the config validation/normalization, but I haven't looked much further. Since jose checks for an exact issuer match, this can cause SSO to fail with "Invalid SSO token." (user-facing) and JWTClaimValidationFailed/ERR_JWT_CLAIM_VALIDATION_FAILED/"Failed to verify SSO id_token" (in the logs, see below).

Steps to reproduce

  1. Go to https://chat.example.com/admin/instance-config
  2. Check "Enable SSO" and set the "Issuer" to https://example.com
  3. Click "Save SSO Settings" and refresh the page
  4. The "Issuer" is now set to https://example.com/, which will cause SSO to fail if the identity provider returns the URL without a trailing slash as the iss value

Environment

Latest docker image (v1)

Logs or screenshots

Short video demonstrating the config value changing (I am refreshing the page after saves): 608915653-5b06efed-c4a6-47d7-b944-def36e16b849.mp4 When properly setting up SSO and attempting to complete the auth flow, the logged error will look like the following:
{"level":"error","time":"2026-06-17T00:39:05.931Z","service":"fluxer-api","env":"production","logger":"SsoService","error":{"type":"JWTClaimValidationFailed","message":"unexpected \"iss\" claim value","stack":"JWTClaimValidationFailed: unexpected \"iss\" claim value\n    at validateClaimsSet (file:///usr/src/app/fluxer_api/node_modules/.pnpm/jose@6.1.3/node_modules/jose/dist/webapi/lib/jwt_claims_set.js:114:15)\n    at jwtVerify (file:///usr/src/app/fluxer_api/node_modules/.pnpm/jose@6.1.3/node_modules/jose/dist/webapi/jwt/verify.js:9:21)\n    at async SsoService.verifyIdToken (/usr/src/app/fluxer_api/src/api/auth/services/SsoService.ts:611:23)\n    at async SsoService.resolveClaims (/usr/src/app/fluxer_api/src/api/auth/services/SsoService.ts:553:14)\n    at async SsoService.completeLogin (/usr/src/app/fluxer_api/src/api/auth/services/SsoService.ts:319:18)\n    at async AuthRequestService.toSsoCompleteResponse (/usr/src/app/fluxer_api/src/api/auth/AuthRequestService.ts:383:18)\n    at async Object.handler (/usr/src/app/fluxer_api/src/api/auth/AuthController.ts:104:19)\n    at async dispatch (file:///usr/src/app/fluxer_api/node_modules/.pnpm/hono@4.12.2/node_modules/hono/dist/compose.js:22:17)\n    at async handler (file:///usr/src/app/fluxer_api/node_modules/.pnpm/hono@4.12.2/node_modules/hono/dist/hono-base.js:118:39)\n    at async dispatch (file:///usr/src/app/fluxer_api/node_modules/.pnpm/hono@4.12.2/node_modules/hono/dist/compose.js:22:17)","code":"ERR_JWT_CLAIM_VALIDATION_FAILED","name":"JWTClaimValidationFailed","claim":"iss","reason":"check_failed","payload":{"iss":"https://example.com","aud":["1516580774764351578"],"iat":1781656745,"exp":1781660345,"auth_time":1781656739,"at_hash":"CD3h8zmT_AAtZkEGHFq_LQ","sub":"82824507223445504"}},"msg":"Failed to verify SSO id_token"}
You can see in "payload" that the SSO provider returns "iss":"https://example.com", which will not match the https://example.com/ in the config.
608915653-5b06efed-c4a6-47d7-b944-def36e16b849.mp4 | 319 kB

4 comments

Sign in with Fluxer to comment and vote.
Comment by @vesaber
RexSystem 1 vote originally by @vesaber on GitHub
Can confirm that I have the same issue with my own identity server. Exactly the same error.
Comment by @jameslindesay
RexSystem 1 vote originally by @jameslindesay on GitHub
Same issue, using Pocket ID as my OIDC authenticator.
Comment by @mrjasonzee
RexSystem 1 vote originally by @mrjasonzee on GitHub
Same exact issue I had with Google OAuth.