> This page location: Backend > Neon Auth > Migration Guides > From Neon Auth SDK v0.1 > Full Neon documentation index: https://neon.com/docs/llms.txt # Migrate from Neon Auth SDK v0.1 to v0.2 Upgrade guide for breaking changes in the Neon Auth SDK This guide helps you migrate from Neon Auth SDK v0.1.x to v0.2.x, which introduces a unified API and performance improvements through session caching. ## What's new in v0.2 ### Unified entry point The SDK now uses a single `createNeonAuth()` function that replaces four separate imports: - `neonAuth()` → `auth.getSession()` - `authApiHandler()` → `auth.handler()` - `neonAuthMiddleware()` → `auth.middleware()` - `createAuthServer()` → `createNeonAuth()` ### Session caching Session data is automatically cached in a signed cookie, reducing API calls to the Auth Server by 95-99%. Sessions are cached for 5 minutes by default (configurable). ### Explicit configuration Configuration is now explicit rather than implicit. You must pass `baseUrl` and `cookies.secret` directly to `createNeonAuth()` instead of relying on automatic environment variable reading. ## Migration steps ### 1. Update package version Update to the latest version: ```bash npm install @neondatabase/auth@latest ``` ### 2. Add required environment variable Add `NEON_AUTH_COOKIE_SECRET` to your `.env` file. This secret is required for signing session data cookies: ```bash # .env NEON_AUTH_BASE_URL=https://ep-xxx.neonauth.us-east-1.aws.neon.tech/neondb/auth NEON_AUTH_COOKIE_SECRET=your-secret-at-least-32-characters-long ``` Generate a secure secret with: ```bash openssl rand -base64 32 ``` **Important:** The secret must be at least 32 characters for HMAC-SHA256 security. ### 3. Create unified auth instance Create a new `lib/auth/server.ts` file with your auth configuration: **Before (v0.1):** ```typescript // lib/auth/server.ts import { createAuthServer } from '@neondatabase/auth/next/server'; export const authServer = createAuthServer(); ``` **After (v0.2):** ```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!, }, }); ``` **Note:** The `auth` object provides all functionality: `handler()`, `middleware()`, `getSession()`, and all Better Auth server methods. ### 4. Update API route handler **Before (v0.1):** ```typescript // app/api/auth/[...path]/route.ts import { authApiHandler } from '@neondatabase/auth/next/server'; export const { GET, POST } = authApiHandler(); ``` **After (v0.2):** ```typescript // app/api/auth/[...path]/route.ts import { auth } from '@/lib/auth/server'; export const { GET, POST } = auth.handler(); ``` ### 5. Update middleware **Before (v0.1):** ```typescript // proxy.ts import { neonAuthMiddleware } from '@neondatabase/auth/next/server'; export default neonAuthMiddleware({ loginUrl: '/auth/sign-in', }); export const config = { matcher: ['/account/:path*'], }; ``` **After (v0.2):** ```typescript // proxy.ts import { auth } from '@/lib/auth/server'; export default auth.middleware({ loginUrl: '/auth/sign-in', }); export const config = { matcher: ['/account/:path*'], }; ``` ### 6. Update server components **Before (v0.1):** ```typescript // app/dashboard/page.tsx import { neonAuth } from '@neondatabase/auth/next/server'; export default async function DashboardPage() { const { session, user } = await neonAuth(); if (!user) { return
Not logged in
; } return
Hello {user.name}
; } ``` **After (v0.2):** ```typescript // app/dashboard/page.tsx import { auth } from '@/lib/auth/server'; // Server components using auth methods must be rendered dynamically export const dynamic = 'force-dynamic'; export default async function DashboardPage() { const { data: session } = await auth.getSession(); if (!session?.user) { return
Not logged in
; } return
Hello {session.user.name}
; } ``` **Important:** Server components that use `auth` methods must set `export const dynamic = 'force-dynamic'` because session data depends on cookies that can only be read at request time. ### 7. Update server actions **Before (v0.1):** ```typescript 'use server'; import { authServer } from '@/lib/auth/server'; import { redirect } from 'next/navigation'; export async function signOut() { await authServer.signOut(); redirect('/auth/sign-in'); } ``` **After (v0.2):** ```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'); } ``` **Note:** All Better Auth server methods are available directly on the `auth` object: `signIn`, `signUp`, `signOut`, `updateUser`, `organization.*`, `admin.*`, etc. ### 8. Update API routes **Before (v0.1):** ```typescript // app/api/user/route.ts import { authServer } from '@/lib/auth/server'; export async function GET() { const { data } = await authServer.getSession(); if (!data?.session) { return Response.json({ error: 'Unauthorized' }, { status: 401 }); } return Response.json({ user: data.user }); } ``` **After (v0.2):** ```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 }); } ``` ### 9. Client-side code (no changes) Client-side code using `createAuthClient()` remains unchanged: ```typescript // lib/auth/client.ts 'use client'; import { createAuthClient } from '@neondatabase/auth/next'; export const authClient = createAuthClient(); ``` Client components and hooks work the same way: ```typescript 'use client'; import { authClient } from '@/lib/auth/client'; export function UserProfile() { const { data } = authClient.useSession(); return
{data?.user?.name}
; } ``` ## API changes reference ### Removed APIs | v0.1 API | v0.2 Replacement | | ---------------------- | ------------------- | | `neonAuth()` | `auth.getSession()` | | `authApiHandler()` | `auth.handler()` | | `neonAuthMiddleware()` | `auth.middleware()` | | `createAuthServer()` | `createNeonAuth()` | ### Return value changes #### `getSession()` return format **Before (v0.1):** ```typescript const { session, user } = await neonAuth(); // Returns: { session: Session, user: User } ``` **After (v0.2):** ```typescript const { data: session } = await auth.getSession(); // Returns: { data: { session: Session, user: User } | null, error: Error | null } ``` The new format is consistent with Better Auth's standard response pattern. ## Configuration options The `createNeonAuth()` function accepts these configuration options: ```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!, }, }); ``` ## Performance improvements The v0.2 SDK includes automatic session caching that reduces API calls by 95-99%: - Session data is cached in a signed cookie (`__Secure-neon-auth.next.session_data`) - Cache is valid for 5 minutes by default (configurable via `sessionDataTtl`) - Automatically refreshed when the session token is refreshed - Falls back to API calls if cache is stale or missing No code changes are needed to benefit from this caching. It works automatically after you configure `cookies.secret`. ## Troubleshooting ### Error: "Missing required config: cookies.secret" You need to add `NEON_AUTH_COOKIE_SECRET` to your environment variables: ```bash NEON_AUTH_COOKIE_SECRET=$(openssl rand -base64 32) ``` ### Error: "Server Component functions should be marked with 'force-dynamic'" Add this to any server component that uses auth methods: ```typescript export const dynamic = 'force-dynamic'; ``` ### Session not persisting Ensure your `NEON_AUTH_COOKIE_SECRET` is: - At least 32 characters long - The same across all environments - Not changing between deployments ### TypeScript errors after upgrade Run: ```bash npm install @neondatabase/auth@latest rm -rf node_modules/.cache npm run dev ``` ## Complete migration checklist - [ ] Update `@neondatabase/auth` to v0.2.x - [ ] Add `NEON_AUTH_COOKIE_SECRET` to `.env` - [ ] Create `lib/auth/server.ts` with `createNeonAuth()` - [ ] Update `app/api/auth/[...path]/route.ts` to use `auth.handler()` - [ ] Update `proxy.ts` to use `auth.middleware()` - [ ] Replace all `neonAuth()` calls with `auth.getSession()` - [ ] Replace all `authServer` imports with `auth` - [ ] Add `export const dynamic = 'force-dynamic'` to server components - [ ] Update return value destructuring from `{ session, user }` to `{ data: session }` - [ ] Test authentication flow in development - [ ] Deploy with new environment variable ## Additional resources - [Next.js Server SDK Reference](https://neon.com/docs/auth/reference/nextjs-server) - Complete API documentation - [Neon Auth SDK Changelog](https://github.com/neondatabase/neon-js/blob/main/packages/auth/CHANGELOG.md#020-beta1) - [Next.js Integration Guide](https://neon.com/docs/auth/quick-start/nextjs) - [Neon Auth Overview](https://neon.com/docs/auth/overview) --- ## Related docs (Migration Guides) - [From Stack Auth (legacy)](https://neon.com/docs/auth/migrate/from-legacy-auth) - [From Supabase](https://neon.com/docs/auth/migrate/from-supabase)