From 92ab5be298ceb19ca8718c67a0c9da8728b6b0bf Mon Sep 17 00:00:00 2001 From: Matt Krick Date: Mon, 26 Feb 2024 12:23:28 -0800 Subject: [PATCH] feat: support env-defined saml issuer for PPMIs (#9455) * feat: support env-defined saml issuer for PPMIs Signed-off-by: Matt Krick * feat: support single SAML for entire tenant Signed-off-by: Matt Krick --------- Signed-off-by: Matt Krick --- .env.example | 2 ++ .../SAMLHelpers/getURLWithSAMLRequestParam.ts | 3 ++- packages/server/utils/getSAMLURLFromEmail.ts | 20 +++++++++++++++++++ 3 files changed, 24 insertions(+), 1 deletion(-) diff --git a/.env.example b/.env.example index 88cdde703de..25c9a9c856e 100644 --- a/.env.example +++ b/.env.example @@ -14,6 +14,8 @@ SOCKET_PORT='3001' # INVITATION_SHORTLINK='example.com' # If true, all new orgs will default to being enterprise tier. Use for PPMIs # IS_ENTERPRISE=false +# PPMI single tenant use only. Will set the SAML issuer to this value. +# SAML_ISSUER='' # AUTHENTICATION # AUTH_INTERNAL_DISABLED='false' diff --git a/packages/server/graphql/public/mutations/helpers/SAMLHelpers/getURLWithSAMLRequestParam.ts b/packages/server/graphql/public/mutations/helpers/SAMLHelpers/getURLWithSAMLRequestParam.ts index bf80ce33ac4..d3fa3b7e98f 100644 --- a/packages/server/graphql/public/mutations/helpers/SAMLHelpers/getURLWithSAMLRequestParam.ts +++ b/packages/server/graphql/public/mutations/helpers/SAMLHelpers/getURLWithSAMLRequestParam.ts @@ -2,13 +2,14 @@ import {v4 as uuid} from 'uuid' import zlib from 'zlib' const getURLWithSAMLRequestParam = (destination: string, slug: string) => { + const issuer = process.env.SAML_ISSUER || `https://${process.env.HOST}/saml-metadata/${slug}` const template = ` - https://${process.env.HOST}/saml-metadata/${slug} + ${issuer} ` diff --git a/packages/server/utils/getSAMLURLFromEmail.ts b/packages/server/utils/getSAMLURLFromEmail.ts index a2e3fc65e11..2c07d74a06d 100644 --- a/packages/server/utils/getSAMLURLFromEmail.ts +++ b/packages/server/utils/getSAMLURLFromEmail.ts @@ -2,6 +2,13 @@ import base64url from 'base64url' import getSSODomainFromEmail from 'parabol-client/utils/getSSODomainFromEmail' import {URL} from 'url' import {DataLoaderWorker} from '../graphql/graphql' +import getKysely from '../postgres/getKysely' + +const isSingleTenantSSO = + process.env.AUTH_INTERNAL_DISABLED === 'true' && + process.env.AUTH_GOOGLE_DISABLED === 'true' && + process.env.AUTH_MICROSOFT_DISABLED === 'true' && + process.env.AUTH_SSO_DISABLED === 'false' const urlWithRelayState = (url: string, isInvited?: boolean | null) => { if (!isInvited) return url @@ -18,6 +25,19 @@ const getSAMLURLFromEmail = async ( ) => { const domainName = getSSODomainFromEmail(email) if (!domainName) return null + if (isSingleTenantSSO) { + // For PPMI use + const pg = getKysely() + const instanceURLres = await pg + .selectFrom('SAML') + .select('url') + .where('url', 'is not', null) + .limit(1) + .executeTakeFirst() + const instanceURL = instanceURLres?.url + if (!instanceURL) return null + return urlWithRelayState(instanceURL, isInvited) + } const saml = await dataLoader.get('samlByDomain').load(domainName) if (!saml) return null const {url} = saml