Team accounts with unlimited members now available to everyone! Invite your teammates and ship faster together, even on the Free Plan.
/Neon Auth/Next.js Server SDK

Next.js Server SDK Reference

Server-side authentication API for Next.js with Neon Auth

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. For UI components, see the UI Components reference.

  1. Installation

    Install the Neon Auth package in your Next.js project using npm, yarn, pnpm, or bun.

    npm install @neondatabase/auth@latest
  2. Environment variables

    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

    # 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
  3. createNeonAuth()

    createNeonAuth(config)

    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

    ParameterTypeRequiredDefault
    baseUrlstring-
    cookies.secretstring-
    cookies.sessionDataTtlnumber300
    cookies.domainstring-
    cookies.sameSitestringstrict
    logLevelstringwarn
    loggerobjectconsole (per level)

    See Server logging and Upstream fetch errors.

    // 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!,
      },
      // logLevel: 'silent',
    });
  4. Server logging

    Neon Auth emits structured logs from the API proxy, middleware, and Better Auth server fetch for upstream failures and session issues.

    Defaults: logLevel: 'warn' writes error and warn to console. Set logLevel: 'silent' to disable all Neon Auth console output ('silent' ignores any custom logger). Use info or debug for more detail during local troubleshooting.

    Custom sink: Pass a partial logger object with error, warn, info, and/or debug methods. Omitted methods still use console. Metadata may include err and detail for observability tools.

    auth.middleware() inherits the same resolved logging configuration from createNeonAuth (no per-request reconfiguration).

    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! },
      logLevel: 'debug',
      logger: {
        warn(message, meta) {
          myLogger.warn({ message, ...meta });
        },
      },
    });
    logLevelConsole output
    silentNone
    errorerror only
    warn (default)error, warn
    infoerror, warn, info
    debugall levels
  5. auth.handler()

    auth.handler()

    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.

    // app/api/auth/[...path]/route.ts
    import { auth } from '@/lib/auth/server';
    
    export const { GET, POST } = auth.handler();
  6. auth.middleware()

    auth.middleware(options)

    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
    ParameterTypeRequiredDefault
    loginUrlstring/auth/sign-in

    Next.js version compatibility

    proxy.ts replaces middleware.ts in Next.js 16. On earlier versions, name the file middleware.ts and export default function middleware instead of proxy. The auth logic is identical.

    proxy.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).*)",
      ],
    };
  7. auth.getSession()

    auth.getSession()

    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

    FieldTypeDescription
    dataSession | nullSession with user data, or null if not authenticated
    errorError | nullError object if session retrieval failed
    // 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 <div>Not authenticated</div>;
      }
    
      return <h1>Welcome, {session.user.name}</h1>;
    }
  8. auth.signIn.email()

    auth.signIn.email(credentials)

    Sign in with email and password. Use in Server Actions for form-based authentication.

    Parameters

    View parameters
    ParameterTypeRequired
    emailstring
    passwordstring
    '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');
    }
  9. auth.signIn.social()

    auth.signIn.social(options)

    Sign in with OAuth provider like Google, GitHub, etc.

    Parameters

    View parameters
    ParameterTypeRequired
    providerstring
    callbackURLstring
    const { data, error } = await auth.signIn.social({
      provider: 'google',
      callbackURL: '/dashboard',
    });
  10. auth.signIn.emailOtp()

    auth.signIn.emailOtp(credentials)

    Sign in with email OTP (one-time password). First call emailOtp.sendVerificationOtp() to send the code.

    Parameters

    View parameters
    ParameterTypeRequired
    emailstring
    otpstring
    const { data, error } = await auth.signIn.emailOtp({
      email: 'user@example.com',
      otp: '123456',
    });
  11. auth.signUp.email()

    auth.signUp.email(credentials)

    Create a new user account with email and password.

    Parameters

    View parameters
    ParameterTypeRequired
    emailstring
    passwordstring
    namestring
    const { data, error } = await auth.signUp.email({
      email: 'user@example.com',
      password: 'secure-password',
      name: 'John Doe',
    });
  12. auth.signOut()

    auth.signOut()

    Sign out the current user. Clears session and authentication tokens.

    'use server';
    import { auth } from '@/lib/auth/server';
    import { redirect } from 'next/navigation';
    
    export async function signOut() {
      await auth.signOut();
      redirect('/auth/sign-in');
    }
  13. auth.updateUser()

    auth.updateUser(data)

    Update the current user's profile. Password updates require the password reset flow for security.

    Parameters

    View parameters
    ParameterTypeRequired
    namestring | undefined
    imagestring | undefined
    const { data, error } = await auth.updateUser({
      name: 'Jane Doe',
      image: 'https://example.com/avatar.jpg',
    });
  14. auth.changePassword()

    auth.changePassword(passwords)

    Change the current user's password.

    Parameters

    View parameters
    ParameterTypeRequired
    currentPasswordstring
    newPasswordstring
    revokeOtherSessionsboolean
    const { data, error } = await auth.changePassword({
      currentPassword: 'old-password',
      newPassword: 'new-password',
      revokeOtherSessions: true,
    });
  15. auth.sendVerificationEmail()

    auth.sendVerificationEmail(options)

    Send email verification to the current user.

    Parameters

    View parameters
    ParameterTypeRequired
    callbackURLstring
    const { data, error } = await auth.sendVerificationEmail({
      callbackURL: '/dashboard',
    });
  16. auth.deleteUser()

    auth.deleteUser()

    Delete the current user account. This action is irreversible.

    const { data, error } = await auth.deleteUser();
  17. auth.emailOtp.sendVerificationOtp()

    auth.emailOtp.sendVerificationOtp(options)

    Send a one-time password via email. Available when Email OTP authentication is enabled.

    Parameters

    View parameters
    ParameterTypeRequired
    emailstring
    const { data, error } = await auth.emailOtp.sendVerificationOtp({
      email: 'user@example.com',
    });
  18. auth.emailOtp.verifyEmail()

    auth.emailOtp.verifyEmail(credentials)

    Verify email with OTP code.

    Parameters

    View parameters
    ParameterTypeRequired
    emailstring
    otpstring
    const { data, error } = await auth.emailOtp.verifyEmail({
      email: 'user@example.com',
      otp: '123456',
    });
  19. auth.listSessions()

    auth.listSessions()

    List all active sessions for the current user.

    const { data, error } = await auth.listSessions();
  20. auth.revokeSession()

    auth.revokeSession(options)

    Revoke a specific session by ID.

    Parameters

    View parameters
    ParameterTypeRequired
    sessionIdstring
    const { data, error } = await auth.revokeSession({
      sessionId: 'session-id',
    });
  21. auth.revokeOtherSessions()

    auth.revokeOtherSessions()

    Revoke all sessions except the current one.

    const { data, error } = await auth.revokeOtherSessions();
  22. auth.organization.create()

    auth.organization.create(data)

    Create a new organization. Available when the organizations plugin is enabled.

    Parameters

    View parameters
    ParameterTypeRequired
    namestring
    slugstring
    const { data, error } = await auth.organization.create({
      name: 'My Organization',
      slug: 'my-org',
    });
  23. auth.organization.list()

    auth.organization.list()

    List the current user's organizations.

    const { data, error } = await auth.organization.list();
  24. auth.organization.inviteMember()

    auth.organization.inviteMember(options)

    Invite a member to an organization.

    Parameters

    View parameters
    ParameterTypeRequired
    organizationIdstring
    emailstring
    rolestring
    const { data, error } = await auth.organization.inviteMember({
      organizationId: 'org-id',
      email: 'member@example.com',
      role: 'member',
    });
  25. auth.admin.listUsers()

    auth.admin.listUsers(options)

    List all users. Available for users with admin role.

    Parameters

    View parameters
    ParameterTypeRequired
    limitnumber
    offsetnumber
    const { data, error } = await auth.admin.listUsers({
      limit: 100,
      offset: 0,
    });
  26. auth.admin.banUser()

    auth.admin.banUser(options)

    Ban a user. Available for users with admin role.

    Parameters

    View parameters
    ParameterTypeRequired
    userIdstring
    reasonstring
    const { data, error } = await auth.admin.banUser({
      userId: 'user-id',
      reason: 'Violation of terms',
    });
  27. auth.admin.setRole()

    auth.admin.setRole(options)

    Set a user's role. Available for users with admin role.

    Parameters

    View parameters
    ParameterTypeRequired
    userIdstring
    rolestring
    const { data, error } = await auth.admin.setRole({
      userId: 'user-id',
      role: 'admin',
    });
  28. Upstream fetch errors

    When the SDK cannot reach your Neon Auth server (wrong baseUrl, DNS, TLS, timeout), the API proxy returns a synthetic 502 JSON body with a stable code. Server methods such as auth.signIn.email() surface the same codes on error.code when the failure is transport-related.

    CodeTypical cause
    NETWORK_DNSHostname does not resolve
    NETWORK_REFUSEDConnection refused
    NETWORK_TIMEOUTRequest timed out
    NETWORK_TLSTLS / certificate error
    NETWORK_RESETConnection reset
    NETWORK_ABORTRequest aborted
    NETWORK_ERROROther transport failure

    Client-visible messages are generic (for example, “Could not resolve authentication server hostname”). Check server logs (set logLevel: 'debug') for detail and the raw error.

    Non-transport failures (unexpected exceptions while handling a response) are re-thrown so Next.js error boundaries still receive the original error. HTTP 4xx upstream responses are logged at info; 5xx at warn.

    'use server';
    
    import { auth } from '@/lib/auth/server';
    
    export async function signIn(formData: FormData) {
      const { error } = await auth.signIn.email({
        email: formData.get('email') as string,
        password: formData.get('password') as string,
      });
    
      if (error?.code === 'NETWORK_DNS') {
        return { error: 'Check NEON_AUTH_BASE_URL in .env.local' };
      }
    
      if (error) {
        return { error: error.message };
      }
    }
  29. Performance features

    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
    // 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();
  30. Configuration reference

    Complete configuration options for createNeonAuth():

    OptionTypeRequiredDefault
    baseUrlstringYes-
    cookies.secretstringYes-
    cookies.sessionDataTtlnumberNo300
    cookies.domainstringNoundefined
    cookies.sameSitestringNostrict
    logLevelstringNowarn
    loggerobjectNoconsole
    • 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 for the signed session_data cookie
    • cookies.domain: For cross-subdomain sessions (for example, ".example.com")
    • cookies.sameSite: strict (default), lax, or none. Use lax or none if you embed the app in a third-party iframe or need cookies on cross-site navigations
    • logLevel: silent, error, warn, info, or debug — see Server logging
    • logger: Optional custom logger; see Server logging
    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!,
      },
    });
  31. Project structure

    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
    • proxy.ts (Next.js 16+) or middleware.ts (earlier versions) - Route protection

    Next.js version compatibility

    proxy.ts replaces middleware.ts in Next.js 16. On earlier versions, name the file middleware.ts and export default function middleware instead of proxy. The auth logic is identical.

    app/
    ├── api/
    │   └── auth/
    │       └── [...path]/
    │           └── route.ts
    ├── auth/
    │   └── [path]/
    │       └── page.tsx
    ├── dashboard/
    │   └── page.tsx
    ├── actions.ts
    └── layout.tsx
    
    lib/
    └── auth/
        ├── server.ts
        └── client.ts
    
    proxy.ts          # or middleware.ts on Next.js < 16
    .env.local

Migration from v0.1

If you're upgrading from Neon Auth SDK v0.1, see the migration guide for step-by-step instructions.

Need help?

Join our Discord Server to ask questions or see what others are doing with Neon. For paid plan support options, see Support.

Was this page helpful?
Edit on GitHub