From e7f3e6c3f97aa71cafff6f0473729fe04f6e47c7 Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Wed, 16 Sep 2026 10:49:05 +0200 Subject: [PATCH 1/4] Fix OIDC discovery with trailing slash --- apps/api/src/app/auth/auth.module.ts | 16 +++++++++++++++- apps/api/src/app/auth/oidc.helper.spec.ts | 20 ++++++++++++++++++++ apps/api/src/app/auth/oidc.helper.ts | 3 +++ 3 files changed, 38 insertions(+), 1 deletion(-) create mode 100644 apps/api/src/app/auth/oidc.helper.spec.ts create mode 100644 apps/api/src/app/auth/oidc.helper.ts diff --git a/apps/api/src/app/auth/auth.module.ts b/apps/api/src/app/auth/auth.module.ts index e2a71ca843..3be0db256e 100644 --- a/apps/api/src/app/auth/auth.module.ts +++ b/apps/api/src/app/auth/auth.module.ts @@ -22,6 +22,7 @@ import { AuthController } from './auth.controller'; import { AuthService } from './auth.service'; import { GoogleStrategy } from './google.strategy'; import { JwtStrategy } from './jwt.strategy'; +import { getOidcDiscoveryUrl } from './oidc.helper'; import { OidcStrategy } from './oidc.strategy'; @Module({ @@ -94,15 +95,28 @@ import { OidcStrategy } from './oidc.strategy'; // Fetch OIDC configuration from discovery endpoint try { const response = await fetchService.fetch( - `${issuer}/.well-known/openid-configuration` + getOidcDiscoveryUrl(issuer) ); + if (!response.ok) { + throw new Error( + `OIDC discovery request failed with status ${response.status}` + ); + } + const config = (await response.json()) as { authorization_endpoint: string; + issuer: string; token_endpoint: string; userinfo_endpoint: string; }; + if (config.issuer !== issuer) { + throw new Error( + 'OIDC discovery response issuer does not match configured issuer' + ); + } + // Manual URLs take priority over discovered ones authorizationURL = manualAuthorizationUrl || config.authorization_endpoint; diff --git a/apps/api/src/app/auth/oidc.helper.spec.ts b/apps/api/src/app/auth/oidc.helper.spec.ts new file mode 100644 index 0000000000..9234f12c95 --- /dev/null +++ b/apps/api/src/app/auth/oidc.helper.spec.ts @@ -0,0 +1,20 @@ +import { getOidcDiscoveryUrl } from './oidc.helper'; + +describe('getOidcDiscoveryUrl', () => { + it.each([ + [ + 'https://auth.example.com', + 'https://auth.example.com/.well-known/openid-configuration' + ], + [ + 'https://auth.example.com/', + 'https://auth.example.com/.well-known/openid-configuration' + ], + [ + 'https://auth.example.com/application/o/ghostfolio/', + 'https://auth.example.com/application/o/ghostfolio/.well-known/openid-configuration' + ] + ])('creates the discovery URL for %s', (issuer, expected) => { + expect(getOidcDiscoveryUrl(issuer)).toBe(expected); + }); +}); diff --git a/apps/api/src/app/auth/oidc.helper.ts b/apps/api/src/app/auth/oidc.helper.ts new file mode 100644 index 0000000000..0b04f1a806 --- /dev/null +++ b/apps/api/src/app/auth/oidc.helper.ts @@ -0,0 +1,3 @@ +export function getOidcDiscoveryUrl(issuer: string) { + return `${issuer.replace(/\/+$/, '')}/.well-known/openid-configuration`; +} From d37d04677e2ee1a2c517c8eaf3fd3a422a8d6258 Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Wed, 16 Sep 2026 10:53:06 +0200 Subject: [PATCH 2/4] Update changelog --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b27ee2188a..47e43a2733 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Upgraded `bull-board` from version `9.9.0` to `9.10.1` +### Fixed + +- Fixed the discovery of the _OpenID Connect_ (`OIDC`) configuration for issuer URLs with a trailing slash (experimental) + ## 3.72.0 - 2026-09-20 ### Added From 0e7107e2cfa2e463e903d583a3d0f326fd2dfbc0 Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Wed, 16 Sep 2026 10:55:31 +0200 Subject: [PATCH 3/4] Fix OIDC discovery with trailing slash --- apps/api/src/app/auth/oidc.helper.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/api/src/app/auth/oidc.helper.ts b/apps/api/src/app/auth/oidc.helper.ts index 0b04f1a806..4e8de829fc 100644 --- a/apps/api/src/app/auth/oidc.helper.ts +++ b/apps/api/src/app/auth/oidc.helper.ts @@ -1,3 +1,4 @@ export function getOidcDiscoveryUrl(issuer: string) { + // Remove trailing slashes return `${issuer.replace(/\/+$/, '')}/.well-known/openid-configuration`; } From 5a4b7010a57527dfcae86408d57c5327750474aa Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Mon, 21 Sep 2026 14:02:37 +0200 Subject: [PATCH 4/4] Fix OIDC discovery with trailing slash --- apps/api/src/app/auth/auth.module.ts | 7 ------- 1 file changed, 7 deletions(-) diff --git a/apps/api/src/app/auth/auth.module.ts b/apps/api/src/app/auth/auth.module.ts index 3be0db256e..879463cc13 100644 --- a/apps/api/src/app/auth/auth.module.ts +++ b/apps/api/src/app/auth/auth.module.ts @@ -106,17 +106,10 @@ import { OidcStrategy } from './oidc.strategy'; const config = (await response.json()) as { authorization_endpoint: string; - issuer: string; token_endpoint: string; userinfo_endpoint: string; }; - if (config.issuer !== issuer) { - throw new Error( - 'OIDC discovery response issuer does not match configured issuer' - ); - } - // Manual URLs take priority over discovered ones authorizationURL = manualAuthorizationUrl || config.authorization_endpoint;