Environment
System:
OS: macOS 15.4.1
CPU: (8) arm64 Apple M1
Memory: 101.52 MB / 8.00 GB
Shell: 5.9 - /bin/zsh
Binaries:
Node: 20.19.0 - /opt/homebrew/opt/node@20/bin/node
npm: 10.8.2 - /opt/homebrew/opt/node@20/bin/npm
pnpm: 10.6.5 - ~/Library/pnpm/pnpm
bun: 1.2.10 - /opt/homebrew/bin/bun
Browsers:
Brave Browser: 135.1.77.97
Chrome: 135.0.7049.96
Safari: 18.4
npmPackages:
@auth/drizzle-adapter: ^1.9.0 => 1.9.0
@auth/unstorage-adapter: ^2.0.0 => 2.8.0
next: latest => 15.3.1
next-auth: beta => 5.0.0-beta.26
react: ^18.2.0 => 18.3.1
Reproduction URL
https://github.com/lwensveen/next-auth-example/tree/drizzle-credentials-session-issue
Describe the issue
In NextAuth v5 (next-auth@5.0.0-beta.25, @auth/core@0.37.2), auth() returns null in Server Components and server-side contexts (e.g., API fetches) in the App Router, despite a valid authjs.session-token cookie and a corresponding session in the database (sessionTable). This causes No active session errors and redirect loops to the sign-in page, breaking protected routes. The issue is a follow-up to discussion #12848, which describes similar session handling problems with the Drizzle adapter.
I’ve created a minimal reproduction in lwensveen/next-auth-example, showing that after a successful login via the Credentials provider, auth() fails to recognize the session, even though the cookie is set and the session exists in the database. Manual session creation in the jwt callback (as a workaround) creates a session, but auth() still returns null, suggesting a bug in the Drizzle adapter or App Router session retrieval.
How to reproduce
# Install Dependencies
npm install
# Set Up PostgreSQL
# Install PostgreSQL or use a service (e.g., Neon, Supabase).
# Create a database named next_auth_example:
psql -U postgres
CREATE DATABASE next_auth_example;
# Update .env.local with:
# .env.local
DATABASE_URL=postgres://postgres:password@localhost:5432/next_auth_example
AUTH_SECRET=your-secure-secret-here
NEXT_PUBLIC_API_URL=http://localhost:3000
# Generate AUTH_SECRET:
openssl rand -base64 32
# Run Migrations:
npx drizzle-kit generate
npx drizzle-kit migrate
# Create a Test User
# Generate a bcrypt hash for password123:
node -e "require('bcrypt').hash('password123', 10, (err, hash) => console.log(hash))"
# Insert user:
psql -U postgres -d next_auth_example
INSERT INTO users (id, email, password_hash, created_at) VALUES (
gen_random_uuid(),
'test@test.nl',
'$2b$10$your_hashed_password',
NOW()
);
# Start the App:
npm run dev
# Reproduce the Issue:
# 1. Visit http://localhost:3000/auth/signin.
# 2. Log in with email: test@test.com, password: password123.
# 3. Verify the authjs.session-token cookie is set (browser dev tools: Application > Cookies).
# 4. Navigate to http://localhost:3000/protected.
# 5. Observe:
# - Redirect to /auth/signin (307) or No active session error.
# - Console logs show session: null for ProtectedPage session:, fetchData session:, or Middleware session:.
# 6. Check the database:
psql -U postgres -d next_auth_example -c "SELECT * FROM session"
# - A session exists with sessionToken, userId, and expires.
# Expected Behavior
# - After login, the authjs.session-token cookie is set, and a session is created in sessionTable.
# - Navigating to /protected loads the page with session data and fetched data (e.g., /api/data).
# - auth() returns a valid session in Server Components and server-side fetches, using the cookie to retrieve the session from sessionTable.
# Actual Behavior
# - Login succeeds (/api/auth/callback/credentials returns 200), and the authjs.session-token cookie is set.
# - A session is created in sessionTable (via manual jwt callback workaround).
# - Navigating to /protected triggers a 307 redirect to /auth/signin, or fetchData throws No active session.
# - Console logs show session: null for ProtectedPage session:, fetchData session:, and Middleware session:.
# - SELECT * FROM session confirms a valid session exists, but auth() fails to retrieve it.
# Logs
# Console Logs (example):
Authorized user: {
id: 'b3ada650-3833-4d6c-a27f-a8242d031658',
email: 'test@test.nl',
name: null,
image: null,
emailVerified: null,
createdAt: '2025-04-22T09:26:26.126Z',
updatedAt: '2025-04-22T09:26:26.126Z'
}
jwt callback - token: {
name: null,
email: 'test@test.com,
picture: null,
sub: 'b3ada650-3833-4d6c-a27f-a8242d031658'
} user: {
id: 'b3ada650-3833-4d6c-a27f-a8242d031658',
email: 'test@test.com,
name: null,
image: null,
emailVerified: null,
createdAt: '2025-04-22T09:26:26.126Z',
updatedAt: '2025-04-22T09:26:26.126Z'
} account: {
providerAccountId: 'b3ada650-3833-4d6c-a27f-a8242d031658',
type: 'credentials',
provider: 'credentials'
} trigger: signIn session: undefined
No session found for user b3ada650-3833-4d6c-a27f-a8242d031658
ProtectedPage session: null
fetchData session: null
Middleware session: null
Fetched /api/data: Error: No active session
# Database:
SELECT * FROM session;
sessionToken | userId | expires
-------------+--------+---------
<token> | b3ada650-3833-4d6c-a27f-a8242d031658 | 2025-05-22T09:26:26.126Z
# Cookie:
# - Name: authjs.session-token
# - Value: <valid-token>
# - Attributes: HttpOnly; SameSite=Lax; Path=/; Secure=false
### Expected behavior
It should log in with a valid session.
Environment
Reproduction URL
https://github.com/lwensveen/next-auth-example/tree/drizzle-credentials-session-issue
Describe the issue
In NextAuth v5 (
next-auth@5.0.0-beta.25,@auth/core@0.37.2),auth()returnsnullin Server Components and server-side contexts (e.g., API fetches) in the App Router, despite a validauthjs.session-tokencookie and a corresponding session in the database (sessionTable). This causesNo active sessionerrors and redirect loops to the sign-in page, breaking protected routes. The issue is a follow-up to discussion #12848, which describes similar session handling problems with the Drizzle adapter.I’ve created a minimal reproduction in lwensveen/next-auth-example, showing that after a successful login via the Credentials provider,
auth()fails to recognize the session, even though the cookie is set and the session exists in the database. Manual session creation in thejwtcallback (as a workaround) creates a session, butauth()still returnsnull, suggesting a bug in the Drizzle adapter or App Router session retrieval.How to reproduce