diff --git a/packages/auth/src/adapter.ts b/packages/auth/src/adapter.ts index 61d74a9..e1f899d 100644 --- a/packages/auth/src/adapter.ts +++ b/packages/auth/src/adapter.ts @@ -11,12 +11,29 @@ function createAdapter(): Adapter | undefined { } try { - return DrizzleAdapter(db, { + const baseAdapter = DrizzleAdapter(db, { usersTable: users, accountsTable: accounts, sessionsTable: sessions, verificationTokensTable: verificationTokens, }); + + // Override token methods — our custom sendVerificationRequest (config.ts) + // stores its own token with a "custom:" prefix, and our custom + // /api/auth/verify-email route consumes it directly. + // NextAuth's default flow creates a *hashed* token that our custom + // verify route can never match, causing Verification_Failed errors. + return { + ...baseAdapter, + createVerificationToken: async (token) => { + // No-op: our sendVerificationRequest handles token creation + return token; + }, + useVerificationToken: async (params) => { + // No-op: our /api/auth/verify-email route handles token consumption + return null; + }, + }; } catch (error) { console.error("Auth adapter: Failed to create Drizzle adapter:", error); return undefined; diff --git a/sites/mainweb/app/(portal)/api/auth/verify-email/route.ts b/sites/mainweb/app/(portal)/api/auth/verify-email/route.ts index 44ee338..5d74ba0 100644 --- a/sites/mainweb/app/(portal)/api/auth/verify-email/route.ts +++ b/sites/mainweb/app/(portal)/api/auth/verify-email/route.ts @@ -30,6 +30,8 @@ export async function GET(request: NextRequest) { // the token value as-is (no hashing) with a "custom:" prefix const customTokenValue = `custom:${tokenParam}`; + console.log(`[verify-email] Looking up token for ${email}`); + const result = await db .delete(verificationTokens) .where( @@ -41,6 +43,7 @@ export async function GET(request: NextRequest) { .returning(); if (result.length === 0) { + console.warn(`[verify-email] No matching token found for ${email} — link may be expired or already used`); return NextResponse.redirect(`${baseUrl}/auth/error?error=Verification`); }