()
| 403 | } |
| 404 | |
| 405 | async function registerSSOProvider(): Promise<boolean> { |
| 406 | try { |
| 407 | const ssoConfig = buildSSOConfigFromEnv() |
| 408 | |
| 409 | if (!ssoConfig) { |
| 410 | logger.error('❌ No valid SSO configuration found in environment variables') |
| 411 | logger.error('') |
| 412 | logger.error('📝 Required environment variables:') |
| 413 | logger.error('For OIDC providers (like Okta, Azure AD):') |
| 414 | const oidcExample = getExampleEnvVars('oidc', 'okta') |
| 415 | for (const [key, value] of Object.entries(oidcExample)) { |
| 416 | logger.error(` ${key}=${value}`) |
| 417 | } |
| 418 | logger.error(' SSO_USER_EMAIL=admin@yourdomain.com') |
| 419 | logger.error('') |
| 420 | logger.error('For SAML providers (like ADFS):') |
| 421 | const samlExample = getExampleEnvVars('saml') |
| 422 | for (const [key, value] of Object.entries(samlExample)) { |
| 423 | logger.error(` ${key}=${value}`) |
| 424 | } |
| 425 | logger.error(' SSO_USER_EMAIL=admin@yourdomain.com') |
| 426 | return false |
| 427 | } |
| 428 | |
| 429 | const adminUser = await getAdminUser() |
| 430 | if (!adminUser) { |
| 431 | return false |
| 432 | } |
| 433 | |
| 434 | logger.info('Registering SSO provider directly in database...', { |
| 435 | providerId: ssoConfig.providerId, |
| 436 | providerType: ssoConfig.providerType, |
| 437 | domain: ssoConfig.domain, |
| 438 | adminUser: adminUser.email, |
| 439 | }) |
| 440 | |
| 441 | try { |
| 442 | new URL(ssoConfig.issuer) |
| 443 | } catch { |
| 444 | logger.error('Invalid issuer. Must be a valid URL:', ssoConfig.issuer) |
| 445 | return false |
| 446 | } |
| 447 | |
| 448 | if ( |
| 449 | ssoConfig.providerType === 'saml' && |
| 450 | !process.env.NEXT_PUBLIC_APP_URL && |
| 451 | !process.env.BETTER_AUTH_URL |
| 452 | ) { |
| 453 | logger.error( |
| 454 | 'NEXT_PUBLIC_APP_URL or BETTER_AUTH_URL is required for SAML — it is used as the SP entity ID in SP metadata. Set one of these env vars.' |
| 455 | ) |
| 456 | return false |
| 457 | } |
| 458 | |
| 459 | if (ssoConfig.providerType === 'oidc' && ssoConfig.oidcConfig) { |
| 460 | const needsDiscovery = |
| 461 | !ssoConfig.oidcConfig.authorizationEndpoint || |
| 462 | !ssoConfig.oidcConfig.tokenEndpoint || |
no test coverage detected