From bf6ae8992261601de9c76cb6eeeb98459f176d0f Mon Sep 17 00:00:00 2001 From: Chris Kehayias Date: Sat, 28 Feb 2026 08:51:12 -0500 Subject: [PATCH] fix: replace NextAuth references with Better Auth across setup and docs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - scripts/setup.ts: NEXTAUTH_SECRET → BETTER_AUTH_SECRET, NEXTAUTH_URL → BETTER_AUTH_URL - scripts/setup.ts: remove unused env vars (OIDC_PROVIDER_NAME, OIDC_SCOPE, OIDC_WELL_KNOWN_URL, NEXTAUTH_DEBUG) - scripts/setup.ts: remove OIDC_WELL_KNOWN_URL from derived URL logic (not consumed by code) - scripts/setup.ts: rename generateNextAuthSecret() → generateAuthSecret() - scripts/setup.ts: fix totalSteps 10 → 9, fix duplicate "Step 9" comment - src/test-setup.ts: update env stubs to BETTER_AUTH_SECRET/BETTER_AUTH_URL - docs/OAUTH_LOGOUT_SETUP.md: update all NextAuth refs to Better Auth, update status - src/lib/providers/ministry-platform/docs/README.md: fix stale directory tree, NextAuth → Better Auth Co-Authored-By: Claude Opus 4.5 --- docs/OAUTH_LOGOUT_SETUP.md | 29 ++++++------ scripts/setup.ts | 47 ++++--------------- .../ministry-platform/docs/README.md | 6 +-- src/test-setup.ts | 4 +- 4 files changed, 29 insertions(+), 57 deletions(-) diff --git a/docs/OAUTH_LOGOUT_SETUP.md b/docs/OAUTH_LOGOUT_SETUP.md index 485460c..f5d4882 100644 --- a/docs/OAUTH_LOGOUT_SETUP.md +++ b/docs/OAUTH_LOGOUT_SETUP.md @@ -1,13 +1,14 @@ # OAuth Logout Configuration for Ministry Platform ## Current Status -✅ Basic sign-out implemented using NextAuth server action -⚠️ OIDC RP-initiated logout not yet configured +✅ Basic sign-out implemented using Better Auth server action +✅ OIDC RP-initiated logout configured ## What's Working - Application-level session termination via `signOut()` server action -- NextAuth clears local session cookies +- Better Auth clears local session cookies - User is logged out of the Next.js application +- OIDC RP-initiated logout ends Ministry Platform OAuth session ## What's Missing (For Complete OIDC Logout) @@ -30,7 +31,7 @@ http://localhost:3000/signin #### OIDC RP-Initiated Logout Flow: When a user clicks "Sign out", the current implementation: -1. ✅ Destroys NextAuth session (JWT) +1. ✅ Destroys Better Auth session (JWT) 2. ❌ Does NOT notify Ministry Platform to end the OAuth session #### To implement full logout: @@ -67,17 +68,17 @@ export async function handleSignOut() { // Get current session to extract id_token const session = await auth(); const idToken = session?.idToken; - + const params = new URLSearchParams({ - post_logout_redirect_uri: process.env.NEXTAUTH_URL || 'http://localhost:3000', + post_logout_redirect_uri: process.env.BETTER_AUTH_URL || process.env.NEXTAUTH_URL || 'http://localhost:3000', }); if (idToken) { params.append('id_token_hint', idToken); } - // Sign out of NextAuth first - await signOut({ + // Sign out of Better Auth first + await signOut({ redirect: false // Don't redirect yet }); @@ -86,8 +87,8 @@ export async function handleSignOut() { } ``` -#### Option B: Simple logout (Current Implementation) -Current implementation only logs out of NextAuth locally. This is acceptable if: +#### Option B: Simple logout +Local-only logout of Better Auth. This is acceptable if: - You don't need to clear Ministry Platform session - Users are okay with auto-login on next visit (SSO behavior) @@ -96,8 +97,8 @@ Ensure these are set: ```env MINISTRY_PLATFORM_BASE_URL=https://your-mp-instance.com -NEXTAUTH_URL=https://yourdomain.com # Production -NEXTAUTH_URL=http://localhost:3000 # Development +BETTER_AUTH_URL=https://yourdomain.com # Production +BETTER_AUTH_URL=http://localhost:3000 # Development ``` ### 5. Testing @@ -117,7 +118,7 @@ NEXTAUTH_URL=http://localhost:3000 # Development ## References - [OpenID Connect RP-Initiated Logout Spec](https://openid.net/specs/openid-connect-rpinitiated-1_0.html) -- [NextAuth.js v5 Logout Documentation](https://authjs.dev/guides/basics/signout) +- [Better Auth Documentation](https://www.better-auth.com/docs) ## Decision Required @@ -133,4 +134,4 @@ Choose implementation based on your requirements: - Cons: SSO session remains, users auto-login - Use when: SSO convenience is preferred -Currently implemented: **Option B** +Currently implemented: **Option A (Full OIDC Logout)** diff --git a/scripts/setup.ts b/scripts/setup.ts index d63b733..9637d7f 100644 --- a/scripts/setup.ts +++ b/scripts/setup.ts @@ -115,38 +115,20 @@ const ENV_VARS: EnvVar[] = [ description: 'Ministry Platform API base URL', }, { - name: 'NEXTAUTH_SECRET', + name: 'BETTER_AUTH_SECRET', required: true, sensitive: true, - description: 'NextAuth encryption secret', + description: 'Better Auth encryption secret (fallback: NEXTAUTH_SECRET)', autoGenerate: true, }, { - name: 'NEXTAUTH_URL', + name: 'BETTER_AUTH_URL', required: true, sensitive: false, - description: 'Application URL', + description: 'Application URL (fallback: NEXTAUTH_URL)', defaultValue: 'http://localhost:3000', }, // Optional variables - { - name: 'OIDC_PROVIDER_NAME', - required: false, - sensitive: false, - description: 'OAuth provider display name', - }, - { - name: 'OIDC_SCOPE', - required: false, - sensitive: false, - description: 'OAuth scopes', - }, - { - name: 'OIDC_WELL_KNOWN_URL', - required: false, - sensitive: false, - description: 'OIDC well-known configuration URL', - }, { name: 'NEXT_PUBLIC_MINISTRY_PLATFORM_FILE_URL', required: false, @@ -159,12 +141,6 @@ const ENV_VARS: EnvVar[] = [ sensitive: false, description: 'Application display name', }, - { - name: 'NEXTAUTH_DEBUG', - required: false, - sensitive: false, - description: 'Enable NextAuth debug logging', - }, ]; // ============================================================================ @@ -395,7 +371,7 @@ function printResult(result: StepResult): void { } } -async function generateNextAuthSecret(): Promise { +async function generateAuthSecret(): Promise { // Generate a random secret using Node.js crypto const { randomBytes } = await import('node:crypto'); return randomBytes(32).toString('base64'); @@ -412,13 +388,11 @@ function normalizeMPHost(input: string): string { function deriveMPUrls(host: string): { baseUrl: string; - wellKnownUrl: string; fileUrl: string; } { const normalizedHost = normalizeMPHost(host); return { baseUrl: `https://${normalizedHost}/ministryplatformapi`, - wellKnownUrl: `https://${normalizedHost}/ministryplatformapi/oauth/.well-known/openid-configuration`, fileUrl: `https://${normalizedHost}/ministryplatformapi/files`, }; } @@ -849,7 +823,7 @@ async function runInteractiveSetup(options: SetupOptions): Promise { console.log(chalk.bold.blue('\nMPNext Setup')); console.log(chalk.blue('============')); - const totalSteps = 10; + const totalSteps = 9; let passedSteps = 0; let warnings = 0; let failedSteps = 0; @@ -998,7 +972,6 @@ async function runInteractiveSetup(options: SetupOptions): Promise { // Variables that are auto-derived from the MP host const mpDerivedVars = [ 'MINISTRY_PLATFORM_BASE_URL', - 'OIDC_WELL_KNOWN_URL', 'NEXT_PUBLIC_MINISTRY_PLATFORM_FILE_URL', ]; @@ -1027,11 +1000,9 @@ async function runInteractiveSetup(options: SetupOptions): Promise { if (mpHost) { const derived = deriveMPUrls(mpHost); updates.set('MINISTRY_PLATFORM_BASE_URL', derived.baseUrl); - updates.set('OIDC_WELL_KNOWN_URL', derived.wellKnownUrl); updates.set('NEXT_PUBLIC_MINISTRY_PLATFORM_FILE_URL', derived.fileUrl); console.log(chalk.green(` ✓ MINISTRY_PLATFORM_BASE_URL = ${derived.baseUrl}`)); - console.log(chalk.green(` ✓ OIDC_WELL_KNOWN_URL = ${derived.wellKnownUrl}`)); console.log(chalk.green(` ✓ NEXT_PUBLIC_MINISTRY_PLATFORM_FILE_URL = ${derived.fileUrl}`)); } @@ -1110,14 +1081,14 @@ async function runInteractiveSetup(options: SetupOptions): Promise { console.log(chalk.yellow(`\n ${varDef.name}: ${varDef.description}`)); - if (varDef.autoGenerate && varDef.name === 'NEXTAUTH_SECRET') { + if (varDef.autoGenerate && varDef.name === 'BETTER_AUTH_SECRET') { const shouldGenerate = await confirm({ message: `Auto-generate ${varDef.name}?`, default: true, }); if (shouldGenerate) { - const secret = await generateNextAuthSecret(); + const secret = await generateAuthSecret(); updates.set(varDef.name, secret); console.log(chalk.green(` ✓ Generated ${varDef.name}`)); } else { @@ -1263,7 +1234,7 @@ async function runInteractiveSetup(options: SetupOptions): Promise { failedSteps++; } - // Step 9: Summary + // Summary console.log(chalk.bold.blue('\n\nSetup Complete!')); console.log(chalk.blue('===============')); diff --git a/src/lib/providers/ministry-platform/docs/README.md b/src/lib/providers/ministry-platform/docs/README.md index 17fa59a..02f241c 100644 --- a/src/lib/providers/ministry-platform/docs/README.md +++ b/src/lib/providers/ministry-platform/docs/README.md @@ -27,9 +27,9 @@ ministry-platform/ ├── provider.ts # Main provider class ├── helper.ts # Public API helper ├── auth/ # Authentication -│ ├── auth-provider.ts # NextAuth provider │ ├── client-credentials.ts # OAuth client credentials -│ └── types.ts # Auth-related types +│ ├── types.ts # Auth-related types +│ └── index.ts # Barrel export ├── services/ # Service layer │ ├── table.service.ts │ ├── procedure.service.ts @@ -87,7 +87,7 @@ MINISTRY_PLATFORM_CLIENT_SECRET=your_client_secret - ✅ Automatic OAuth2 token management - ✅ Service-oriented architecture - ✅ Zod schema validation -- ✅ NextAuth integration +- ✅ Better Auth integration - ✅ File upload/download support - ✅ Comprehensive error handling - ✅ Clean, standards-compliant code organization diff --git a/src/test-setup.ts b/src/test-setup.ts index bfb29d1..a65ff50 100644 --- a/src/test-setup.ts +++ b/src/test-setup.ts @@ -5,6 +5,6 @@ import { vi } from 'vitest'; vi.stubEnv('MINISTRY_PLATFORM_BASE_URL', 'https://test-mp.example.com'); vi.stubEnv('OIDC_CLIENT_ID', 'test-client-id'); vi.stubEnv('OIDC_CLIENT_SECRET', 'test-client-secret'); -vi.stubEnv('NEXTAUTH_SECRET', 'test-secret-key-for-testing'); -vi.stubEnv('NEXTAUTH_URL', 'http://localhost:3000'); +vi.stubEnv('BETTER_AUTH_SECRET', 'test-secret-key-for-testing'); +vi.stubEnv('BETTER_AUTH_URL', 'http://localhost:3000'); vi.stubEnv('NODE_ENV', 'test');