@@ -235,12 +235,19 @@ function buildSSOConfigFromEnv(): SSOProviderConfig | null {
235235 return null
236236 }
237237
238- const callbackUrl = process . env . SSO_SAML_CALLBACK_URL || `${ issuer } /callback`
238+ const appBaseUrl = (
239+ process . env . NEXT_PUBLIC_APP_URL ||
240+ process . env . BETTER_AUTH_URL ||
241+ ''
242+ ) . replace ( / \/ $ / , '' )
243+
244+ const callbackUrl =
245+ process . env . SSO_SAML_CALLBACK_URL || `${ appBaseUrl } /api/auth/sso/callback/${ providerId } `
239246
240247 let spMetadata = process . env . SSO_SAML_SP_METADATA
241248 if ( ! spMetadata ) {
242249 spMetadata = `<?xml version="1.0" encoding="UTF-8"?>
243- <md:EntityDescriptor xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata" entityID="${ issuer } ">
250+ <md:EntityDescriptor xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata" entityID="${ appBaseUrl } ">
244251 <md:SPSSODescriptor AuthnRequestsSigned="false" WantAssertionsSigned="false" protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
245252 <md:AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="${ callbackUrl } " index="1"/>
246253 </md:SPSSODescriptor>
@@ -259,7 +266,7 @@ function buildSSOConfigFromEnv(): SSOProviderConfig | null {
259266 identifierFormat : process . env . SSO_SAML_IDENTIFIER_FORMAT ,
260267 spMetadata : {
261268 metadata : spMetadata ,
262- entityID : issuer ,
269+ entityID : appBaseUrl ,
263270 } ,
264271 }
265272 const idpMetadata = process . env . SSO_SAML_IDP_METADATA
@@ -396,6 +403,18 @@ async function registerSSOProvider(): Promise<boolean> {
396403 return false
397404 }
398405
406+ if (
407+ ssoConfig . providerType === 'saml' &&
408+ ! process . env . SSO_SAML_CALLBACK_URL &&
409+ ! process . env . NEXT_PUBLIC_APP_URL &&
410+ ! process . env . BETTER_AUTH_URL
411+ ) {
412+ logger . error (
413+ 'NEXT_PUBLIC_APP_URL or BETTER_AUTH_URL is required to generate the SAML callback URL. Set one of these or provide SSO_SAML_CALLBACK_URL explicitly.'
414+ )
415+ return false
416+ }
417+
399418 if ( ssoConfig . providerType === 'oidc' && ssoConfig . oidcConfig ) {
400419 const needsDiscovery =
401420 ! ssoConfig . oidcConfig . authorizationEndpoint ||
0 commit comments