From 2a0b877bb53fa326cee2bfaed1158976868b1da5 Mon Sep 17 00:00:00 2001 From: Deepak Prabhakara Date: Fri, 21 Feb 2025 18:15:10 +0000 Subject: [PATCH 1/2] introduced new config OPENID_SUBJECT_PREFIX to prefix OIDC subject with tenant and product --- .env.example | 5 ++++- lib/env.ts | 1 + npm/src/controller/oauth.ts | 11 ++++++++++- npm/src/typings.ts | 1 + 4 files changed, 16 insertions(+), 2 deletions(-) diff --git a/.env.example b/.env.example index fe1a8e686..33b8db4fb 100644 --- a/.env.example +++ b/.env.example @@ -127,4 +127,7 @@ ENTERPRISE_ORY_PROJECT_ID= # Log file to write to LOG_FILE= # Log levels - "fatal" | "error" | "warn" | "info" (default) | "debug" | "trace" -LOG_LEVEL= \ No newline at end of file +LOG_LEVEL= + +# Set this config to add prefix OIDC subject wiht tenant and product to avoid any potential collissions with SAML IdP profile IDs +# OPENID_SUBJECT_PREFIX=true diff --git a/lib/env.ts b/lib/env.ts index 25d0d6854..2b40fd756 100644 --- a/lib/env.ts +++ b/lib/env.ts @@ -87,6 +87,7 @@ const jacksonOptions: JacksonOption = { }, requestProfileScope: process.env.OPENID_REQUEST_PROFILE_SCOPE === 'false' ? false : true, forwardOIDCParams: process.env.OPENID_REQUEST_FORWARD_PARAMS === 'true' ? true : false, + subjectPrefix: process.env.OPENID_SUBJECT_PREFIX === 'true' ? true : false, }, certs: { publicKey: process.env.PUBLIC_KEY || '', diff --git a/npm/src/controller/oauth.ts b/npm/src/controller/oauth.ts index 2c6fdba81..2950a73f9 100644 --- a/npm/src/controller/oauth.ts +++ b/npm/src/controller/oauth.ts @@ -1338,6 +1338,15 @@ export class OAuthController implements IOAuthController { protocol, }; + let subject = codeVal.profile.claims.id; + if (this.opts.openid?.subjectPrefix) { + subject = + codeVal.requested?.tenant + ':' + codeVal.requested?.product + ':' + codeVal.profile.claims.id; + if (subject.length > 255) { + subject = crypto.createHash('sha512').update(subject).digest('hex'); + } + } + const requestHasNonce = !!codeVal.requested?.nonce; if (requestedOIDCFlow) { const { jwtSigningKeys, jwsAlg } = this.opts.openid ?? {}; @@ -1365,7 +1374,7 @@ export class OAuthController implements IOAuthController { .setExpirationTime(`${this.opts.db.ttl}s`) // identity token only really needs to be valid long enough for it to be verified by the client application. .sign(signingKey); tokenVal.id_token = id_token; - tokenVal.claims.sub = codeVal.profile.claims.id; + tokenVal.claims.sub = subject; } const { hexKey, encVal } = encrypt(tokenVal); diff --git a/npm/src/typings.ts b/npm/src/typings.ts index 491b0e593..192fa4508 100644 --- a/npm/src/typings.ts +++ b/npm/src/typings.ts @@ -468,6 +468,7 @@ export interface JacksonOption { }; requestProfileScope?: boolean; // defaults to true forwardOIDCParams?: boolean; // defaults to false + subjectPrefix?: boolean; // defaults to false }; certs?: { publicKey: string; From 14e124c536805844f2f45d37938c09bc9316ae81 Mon Sep 17 00:00:00 2001 From: Deepak Prabhakara Date: Fri, 21 Feb 2025 19:40:50 +0000 Subject: [PATCH 2/2] set subject correctly --- npm/src/controller/oauth.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/npm/src/controller/oauth.ts b/npm/src/controller/oauth.ts index 2950a73f9..ca1527867 100644 --- a/npm/src/controller/oauth.ts +++ b/npm/src/controller/oauth.ts @@ -1356,7 +1356,7 @@ export class OAuthController implements IOAuthController { let claims: Record = requestHasNonce ? { nonce: codeVal.requested.nonce } : {}; claims = { ...claims, - id: codeVal.profile.claims.id, + id: subject, email: codeVal.profile.claims.email, firstName: codeVal.profile.claims.firstName, lastName: codeVal.profile.claims.lastName, @@ -1369,7 +1369,7 @@ export class OAuthController implements IOAuthController { .setProtectedHeader({ alg: jwsAlg!, kid }) .setIssuedAt() .setIssuer(this.opts.externalUrl) - .setSubject(codeVal.profile.claims.id) + .setSubject(subject) .setAudience(tokenVal.requested.client_id) .setExpirationTime(`${this.opts.db.ttl}s`) // identity token only really needs to be valid long enough for it to be verified by the client application. .sign(signingKey);