From 3e1e0a19db60b1396f286df706e7ff3c8c9b284e Mon Sep 17 00:00:00 2001 From: DecDuck Date: Sun, 1 Mar 2026 21:06:45 +1100 Subject: [PATCH 1/3] fix: validation and issuer checks --- server/internal/auth/oidc/index.ts | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/server/internal/auth/oidc/index.ts b/server/internal/auth/oidc/index.ts index b8cd8eb6..6969408e 100644 --- a/server/internal/auth/oidc/index.ts +++ b/server/internal/auth/oidc/index.ts @@ -17,23 +17,16 @@ import type { SessionSearchTerms } from "../../session/types"; // Schema for OIDC well-known configuration const OIDCWellKnownV1 = type({ - issuer: "string.url.parse", + issuer: "string", authorization_endpoint: "string.url.parse", token_endpoint: "string.url.parse", - userinfo_endpoint: "string.url.parse?", + userinfo_endpoint: "string.url.parse", jwks_uri: "string.url.parse", - scopes_supported: "string[]?", + scopes_supported: "string[]", }); // Represents required OIDC configuration -interface OIDCConfiguration { - issuer: URL; - authorization_endpoint: URL; - token_endpoint: URL; - userinfo_endpoint: URL; - jwks_uri: URL; - scopes_supported: string[]; -} +type OIDCConfiguration = typeof OIDCWellKnownV1.infer; interface OIDCAuthSessionOptions { redirect: string | undefined; @@ -241,7 +234,7 @@ export class OIDCManager { token_endpoint: new URL(tokenEndpoint), userinfo_endpoint: new URL(userinfoEndpoint), scopes_supported: scopes.split(","), - issuer: new URL(issuer), + issuer: issuer, jwks_uri: new URL(jwksEndpoint), }; } @@ -549,7 +542,8 @@ export class OIDCManager { } } -function isHttps(url: URL): boolean { - if (url.protocol === "https:") return true; +function isHttps(url: URL | string): boolean { + const parsedUrl = typeof url === "string" ? new URL(url) : url; + if (parsedUrl.protocol === "https:") return true; else return false; } From 1e82fe73e741ed63ff04ecdc9d98e486820a8c99 Mon Sep 17 00:00:00 2001 From: DecDuck Date: Sun, 1 Mar 2026 21:24:04 +1100 Subject: [PATCH 2/3] feat: query param util --- server/internal/auth/index.ts | 2 +- server/internal/auth/oidc/index.ts | 11 ++++++++++- server/internal/utils/query.ts | 5 +++++ 3 files changed, 16 insertions(+), 2 deletions(-) create mode 100644 server/internal/utils/query.ts diff --git a/server/internal/auth/index.ts b/server/internal/auth/index.ts index 3071c5d8..26b3cde2 100644 --- a/server/internal/auth/index.ts +++ b/server/internal/auth/index.ts @@ -30,7 +30,7 @@ class AuthManager { (this.authProviders as any)[key] = object; logger.info(`enabled auth: ${key}`); } catch (e) { - logger.warn((e as string).toString()); + logger.warn(`failed to enable auth ${key}: ${(e as string).toString()}`); } } diff --git a/server/internal/auth/oidc/index.ts b/server/internal/auth/oidc/index.ts index 6969408e..72e36819 100644 --- a/server/internal/auth/oidc/index.ts +++ b/server/internal/auth/oidc/index.ts @@ -12,6 +12,7 @@ import * as jose from "jose"; // import { inspect } from "util"; import sessionHandler from "../../session"; import type { SessionSearchTerms } from "../../session/types"; +import { queryParamBuilder } from "../../utils/query"; // TODO: monitor https://github.com/goauthentik/authentik/issues/8751 for easier?? OIDC setup by end users @@ -287,7 +288,15 @@ export class OIDCManager { this.oidcConfiguration.authorization_endpoint, ).toString(); - const finalUrl = `${normalisedUrl}?client_id=${this.clientId}&redirect_uri=${encodeURIComponent(this.redirectUrl.toString())}&state=${stateKey}&response_type=code&scope=${encodeURIComponent(this.oidcConfiguration.scopes_supported.join(" "))}`; + const queryParams = queryParamBuilder({ + client_id: this.clientId, + redirect_uri: this.redirectUrl.toString(), + state: stateKey, + response_type: "code", + scope: this.oidcConfiguration.scopes_supported.join(" "), + }); + + const finalUrl = `${normalisedUrl}?${queryParams}`; const session: OIDCAuthSession = { redirectUrl: finalUrl, diff --git a/server/internal/utils/query.ts b/server/internal/utils/query.ts new file mode 100644 index 00000000..bbcd691f --- /dev/null +++ b/server/internal/utils/query.ts @@ -0,0 +1,5 @@ +export function queryParamBuilder(params: { [key: string]: string }) { + const list = Object.entries(params).map(([key, value]) => `${key}=${encodeURIComponent(value)}`); + const str = list.join("&"); + return str; +} From 17fa8846c345e62519ccbb8eb9319ea819264707 Mon Sep 17 00:00:00 2001 From: DecDuck Date: Sun, 1 Mar 2026 21:25:40 +1100 Subject: [PATCH 3/3] fix: lint --- server/internal/auth/index.ts | 4 +++- server/internal/utils/query.ts | 8 +++++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/server/internal/auth/index.ts b/server/internal/auth/index.ts index 26b3cde2..77ce86a1 100644 --- a/server/internal/auth/index.ts +++ b/server/internal/auth/index.ts @@ -30,7 +30,9 @@ class AuthManager { (this.authProviders as any)[key] = object; logger.info(`enabled auth: ${key}`); } catch (e) { - logger.warn(`failed to enable auth ${key}: ${(e as string).toString()}`); + logger.warn( + `failed to enable auth ${key}: ${(e as string).toString()}`, + ); } } diff --git a/server/internal/utils/query.ts b/server/internal/utils/query.ts index bbcd691f..bb62a68b 100644 --- a/server/internal/utils/query.ts +++ b/server/internal/utils/query.ts @@ -1,5 +1,7 @@ export function queryParamBuilder(params: { [key: string]: string }) { - const list = Object.entries(params).map(([key, value]) => `${key}=${encodeURIComponent(value)}`); - const str = list.join("&"); - return str; + const list = Object.entries(params).map( + ([key, value]) => `${key}=${encodeURIComponent(value)}`, + ); + const str = list.join("&"); + return str; }