---
title: Next.js Server SDK Reference
subtitle: Server-side authentication API for Next.js with Neon Auth
enableTableOfContents: true
layout: wide
updatedOn: '2026-01-30T14:03:06.275Z'
---
Reference documentation for the Neon Auth Next.js server SDK (`@neondatabase/auth/next/server`). This package provides server-side authentication for Next.js applications using React Server Components, API routes, middleware, and server actions.
For client-side authentication, see the [Client SDK reference](/docs/reference/javascript-sdk). For UI components, see the [UI Components reference](/docs/auth/reference/ui-components).
Install the Neon Auth package in your Next.js project using npm, yarn, pnpm, or bun.
```bash
npm install @neondatabase/auth
```
Configure these environment variables in your `.env.local` file:
- **NEON_AUTH_BASE_URL** (required): Your Neon Auth server URL from the Neon Console
- **NEON_AUTH_COOKIE_SECRET** (required): Secret for signing session cookies (must be 32+ characters for HMAC-SHA256 security)
Generate a secure secret with: `openssl rand -base64 32`
```bash
# Required: Your Neon Auth server URL
NEON_AUTH_BASE_URL=https://your-neon-auth-url.neon.tech
# Required: Cookie secret for session data signing (32+ characters)
NEON_AUTH_COOKIE_SECRET=your-secret-at-least-32-characters-long
```
Creates a unified auth instance that provides all server-side authentication functionality.
Returns an `auth` object with:
- `handler()` - Creates API route handlers
- `middleware()` - Creates Next.js middleware for route protection
- `getSession()` - Retrieves current session
- All Better Auth server methods (signIn, signUp, signOut, etc.)
### Parameters
| Parameter | Type | Required | Default |
| ------------------------------- | ------ | -------- | ------- |
| baseUrl | string | ✓ | - |
| cookies.secret | string | ✓ | - |
| cookies.sessionDataTtl | number | | 300 |
| cookies.domain | string | | - |
```typescript
// lib/auth/server.ts
import { createNeonAuth } from '@neondatabase/auth/next/server';
export const auth = createNeonAuth({
baseUrl: process.env.NEON_AUTH_BASE_URL!,
cookies: {
secret: process.env.NEON_AUTH_COOKIE_SECRET!,
},
});
```
Creates GET and POST route handlers for the Neon Auth API proxy.
Create a catch-all route at `app/api/auth/[...path]/route.ts`. This handles all authentication API calls from your client, including:
- Sign in/sign up requests
- OAuth callbacks
- Session management
- Email verification
- Password reset
### Returns
Object with `GET` and `POST` Next.js route handlers.
```typescript
// app/api/auth/[...path]/route.ts
import { auth } from '@/lib/auth/server';
export const { GET, POST } = auth.handler();
```
Creates Next.js middleware for session validation and route protection.
The middleware automatically:
- Validates session cookies on each request
- Provides session data to server components
- Redirects unauthenticated users to the login page
- Refreshes session tokens when needed
### Parameters
View parameters
| Parameter | Type | Required | Default |
| ----------------- | ------ | -------- | --------------- |
| loginUrl | string | | `/auth/sign-in` |
```typescript
// middleware.ts
import { auth } from '@/lib/auth/server';
export default auth.middleware({
loginUrl: '/auth/sign-in'
});
export const config = {
matcher: [
// Match all paths except static files
"/((?!_next/static|_next/image|favicon.ico).*)",
],
};
```
Retrieves the current session in Server Components, Server Actions, and API Routes.
- Returns cached session if available (fast)
- Automatically refreshes expired tokens
- Returns null if no active session
Server Components that use `auth.getSession()` must export `dynamic = 'force-dynamic'` because session data depends on cookies.
### Returns
| Field | Type | Description |
| ------- | --------------- | ---------------------------------------------------- |
| `data` | Session \| null | Session with user data, or null if not authenticated |
| `error` | Error \| null | Error object if session retrieval failed |
```typescript
// app/dashboard/page.tsx
import { auth } from '@/lib/auth/server';
export const dynamic = 'force-dynamic';
export default async function DashboardPage() {
const { data: session } = await auth.getSession();
if (!session?.user) {
return Not authenticated
;
}
return Welcome, {session.user.name}
;
}
```
```typescript
// app/actions.ts
'use server';
import { auth } from '@/lib/auth/server';
import { redirect } from 'next/navigation';
export async function updateProfile(formData: FormData) {
const { data: session } = await auth.getSession();
if (!session?.user) {
redirect('/auth/sign-in');
}
// Update user profile...
}
```
```typescript
// app/api/user/route.ts
import { auth } from '@/lib/auth/server';
export async function GET() {
const { data: session } = await auth.getSession();
if (!session?.user) {
return Response.json({ error: 'Unauthorized' }, { status: 401 });
}
return Response.json({ user: session.user });
}
```
Sign in with email and password. Use in Server Actions for form-based authentication.
### Parameters
View parameters
| Parameter | Type | Required |
| ----------------- | ------ | -------- |
| email | string | ✓ |
| password | string | ✓ |
```typescript
'use server';
import { auth } from '@/lib/auth/server';
import { redirect } from 'next/navigation';
export async function signIn(formData: FormData) {
const { data, error } = await auth.signIn.email({
email: formData.get('email') as string,
password: formData.get('password') as string,
});
if (error) return { error: error.message };
redirect('/dashboard');
}
```
Sign in with OAuth provider like Google, GitHub, etc.
### Parameters
View parameters
| Parameter | Type | Required |
| -------------------- | ------ | -------- |
| provider | string | ✓ |
| callbackURL | string | |
```typescript
const { data, error } = await auth.signIn.social({
provider: 'google',
callbackURL: '/dashboard',
});
```
Sign in with email OTP (one-time password). First call `emailOtp.sendVerificationOtp()` to send the code.
### Parameters
View parameters
| Parameter | Type | Required |
| -------------- | ------ | -------- |
| email | string | ✓ |
| otp | string | ✓ |
```typescript
const { data, error } = await auth.signIn.emailOtp({
email: 'user@example.com',
otp: '123456',
});
```
Create a new user account with email and password.
### Parameters
View parameters
| Parameter | Type | Required |
| ----------------- | ------ | -------- |
| email | string | ✓ |
| password | string | ✓ |
| name | string | ✓ |
```typescript
const { data, error } = await auth.signUp.email({
email: 'user@example.com',
password: 'secure-password',
name: 'John Doe',
});
```
Sign out the current user. Clears session and authentication tokens.
```typescript
'use server';
import { auth } from '@/lib/auth/server';
import { redirect } from 'next/navigation';
export async function signOut() {
await auth.signOut();
redirect('/auth/sign-in');
}
```
Update the current user's profile. Password updates require the password reset flow for security.
### Parameters
View parameters
| Parameter | Type | Required |
| -------------- | ------------------- | -------- |
| name | string \| undefined | |
| image | string \| undefined | |
```typescript
const { data, error } = await auth.updateUser({
name: 'Jane Doe',
image: 'https://example.com/avatar.jpg',
});
```
Change the current user's password.
### Parameters
View parameters
| Parameter | Type | Required |
| ---------------------------- | ------- | -------- |
| currentPassword | string | ✓ |
| newPassword | string | ✓ |
| revokeOtherSessions | boolean | |
```typescript
const { data, error } = await auth.changePassword({
currentPassword: 'old-password',
newPassword: 'new-password',
revokeOtherSessions: true,
});
```
Send email verification to the current user.
### Parameters
View parameters
| Parameter | Type | Required |
| -------------------- | ------ | -------- |
| callbackURL | string | |
```typescript
const { data, error } = await auth.sendVerificationEmail({
callbackURL: '/dashboard',
});
```
Delete the current user account. This action is irreversible.
```typescript
const { data, error } = await auth.deleteUser();
```
Send a one-time password via email. Available when Email OTP authentication is enabled.
### Parameters
View parameters
| Parameter | Type | Required |
| -------------- | ------ | -------- |
| email | string | ✓ |
```typescript
const { data, error } = await auth.emailOtp.sendVerificationOtp({
email: 'user@example.com',
});
```
Verify email with OTP code.
### Parameters
View parameters
| Parameter | Type | Required |
| -------------- | ------ | -------- |
| email | string | ✓ |
| otp | string | ✓ |
```typescript
const { data, error } = await auth.emailOtp.verifyEmail({
email: 'user@example.com',
otp: '123456',
});
```
List all active sessions for the current user.
```typescript
const { data, error } = await auth.listSessions();
```
Revoke a specific session by ID.
### Parameters
View parameters
| Parameter | Type | Required |
| ------------------ | ------ | -------- |
| sessionId | string | ✓ |
```typescript
const { data, error } = await auth.revokeSession({
sessionId: 'session-id',
});
```
Revoke all sessions except the current one.
```typescript
const { data, error } = await auth.revokeOtherSessions();
```
Create a new organization. Available when the organizations plugin is enabled.
### Parameters
View parameters
| Parameter | Type | Required |
| ------------- | ------ | -------- |
| name | string | ✓ |
| slug | string | |
```typescript
const { data, error } = await auth.organization.create({
name: 'My Organization',
slug: 'my-org',
});
```
List the current user's organizations.
```typescript
const { data, error } = await auth.organization.list();
```
Invite a member to an organization.
### Parameters
View parameters
| Parameter | Type | Required |
| ----------------------- | ------ | -------- |
| organizationId | string | ✓ |
| email | string | ✓ |
| role | string | |
```typescript
const { data, error } = await auth.organization.inviteMember({
organizationId: 'org-id',
email: 'member@example.com',
role: 'member',
});
```
List all users. Available for users with admin role.
### Parameters
View parameters
| Parameter | Type | Required |
| --------------- | ------ | -------- |
| limit | number | |
| offset | number | |
```typescript
const { data, error } = await auth.admin.listUsers({
limit: 100,
offset: 0,
});
```
Ban a user. Available for users with admin role.
### Parameters
View parameters
| Parameter | Type | Required |
| --------------- | ------ | -------- |
| userId | string | ✓ |
| reason | string | |
```typescript
const { data, error } = await auth.admin.banUser({
userId: 'user-id',
reason: 'Violation of terms',
});
```
Set a user's role. Available for users with admin role.
### Parameters
View parameters
| Parameter | Type | Required |
| --------------- | ------ | -------- |
| userId | string | ✓ |
| role | string | ✓ |
```typescript
const { data, error } = await auth.admin.setRole({
userId: 'user-id',
role: 'admin',
});
```
### Session caching
Session data is automatically cached in a signed, HTTP-only cookie to reduce API calls to the Auth Server by 95-99%.
- Default cache TTL: 5 minutes (300 seconds)
- Configurable via `cookies.sessionDataTtl`
- Automatic expiration based on JWT `exp` claim
- Synchronous cache clearing on sign-out
- Secure HMAC-SHA256 signing
### Request deduplication
Multiple concurrent `getSession()` calls are automatically deduplicated:
- Single network request for concurrent calls
- 10x faster cold starts
- Reduces server load
```typescript
// First call: Fetches from Auth Server
const { data: session } = await auth.getSession();
// Subsequent calls within TTL: Uses cached data (no API call)
const { data: session2 } = await auth.getSession();
```
Complete configuration options for `createNeonAuth()`:
| Option | Type | Required | Default |
| ------------------------ | ------ | -------- | --------- |
| `baseUrl` | string | Yes | - |
| `cookies.secret` | string | Yes | - |
| `cookies.sessionDataTtl` | number | No | 300 |
| `cookies.domain` | string | No | undefined |
- **baseUrl**: Your Neon Auth server URL from the Neon Console
- **cookies.secret**: Secret for HMAC-SHA256 signing (32+ characters)
- **cookies.sessionDataTtl**: Cache TTL in seconds
- **cookies.domain**: For cross-subdomain sessions (e.g., ".example.com")
```typescript
import { createNeonAuth } from '@neondatabase/auth/next/server';
export const auth = createNeonAuth({
baseUrl: process.env.NEON_AUTH_BASE_URL!,
cookies: {
secret: process.env.NEON_AUTH_COOKIE_SECRET!,
},
});
```
Recommended file structure for Next.js with Neon Auth:
- `app/api/auth/[...path]/route.ts` - Auth API handlers
- `app/auth/[path]/page.tsx` - Auth views (sign-in, sign-up)
- `app/dashboard/page.tsx` - Protected pages
- `lib/auth/server.ts` - Server auth instance
- `lib/auth/client.ts` - Client auth instance
- `middleware.ts` - Next.js middleware
```
app/
├── api/
│ └── auth/
│ └── [...path]/
│ └── route.ts
├── auth/
│ └── [path]/
│ └── page.tsx
├── dashboard/
│ └── page.tsx
├── actions.ts
└── layout.tsx
lib/
└── auth/
├── server.ts
└── client.ts
middleware.ts
.env.local
```
## Migration from v0.1
If you're upgrading from Neon Auth SDK v0.1, see the [migration guide](/docs/auth/migrate/from-auth-v0.1) for step-by-step instructions.
## Related documentation
- [Client SDK Reference](/docs/reference/javascript-sdk) - Client-side authentication
- [UI Components Reference](/docs/auth/reference/ui-components) - Pre-built auth UI
- [Next.js Quickstart](/docs/auth/quick-start/nextjs) - Getting started guide
- [Migration Guide](/docs/auth/migrate/from-auth-v0.1) - Upgrading from v0.1