SDK Reference
Next.js SDK

Next.js SDK

The @bastionauth/nextjs package provides Next.js-specific integration including middleware and server helpers.

Installation

npm install @bastionauth/nextjs @bastionauth/react
# or
pnpm add @bastionauth/nextjs @bastionauth/react
# or
yarn add @bastionauth/nextjs @bastionauth/react

Setup

1. Configure Provider

// app/providers.tsx
'use client';
 
import { BastionProvider } from '@bastionauth/react';
 
export function Providers({ children }: { children: React.ReactNode }) {
  return (
    <BastionProvider
      publishableKey={process.env.NEXT_PUBLIC_BASTION_KEY!}
      apiUrl={process.env.NEXT_PUBLIC_BASTION_API_URL!}
    >
      {children}
    </BastionProvider>
  );
}
// app/layout.tsx
import { Providers } from './providers';
 
export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <html>
      <body>
        <Providers>{children}</Providers>
      </body>
    </html>
  );
}

2. Configure Middleware

// middleware.ts
import { authMiddleware } from '@bastionauth/nextjs';
 
export default authMiddleware({
  publicRoutes: ['/', '/sign-in', '/sign-up', '/api/webhooks(.*)'],
  signInUrl: '/sign-in',
});
 
export const config = {
  matcher: ['/((?!.*\\..*|_next).*)', '/', '/(api|trpc)(.*)'],
};

Middleware Configuration

publicRoutes

Routes that don't require authentication:

authMiddleware({
  publicRoutes: [
    '/',
    '/sign-in',
    '/sign-up',
    '/api/webhooks(.*)', // Regex patterns supported
    '/blog/:slug',       // Dynamic routes
  ],
});

ignoredRoutes

Routes to skip entirely (no auth check):

authMiddleware({
  ignoredRoutes: [
    '/_next/static(.*)',
    '/favicon.ico',
  ],
});

afterAuth

Custom logic after authentication:

authMiddleware({
  afterAuth(auth, req) {
    // Redirect non-admin users from admin routes
    if (req.nextUrl.pathname.startsWith('/admin') && !auth.isAdmin) {
      return NextResponse.redirect(new URL('/dashboard', req.url));
    }
  },
});

Server-Side Auth

auth()

Get authentication state in Server Components:

// app/dashboard/page.tsx
import { auth } from '@bastionauth/nextjs/server';
 
export default async function DashboardPage() {
  const { userId, sessionId, getToken } = await auth();
 
  if (!userId) {
    redirect('/sign-in');
  }
 
  // Get token for API calls
  const token = await getToken();
 
  return <Dashboard />;
}

currentUser()

Get full user object:

import { currentUser } from '@bastionauth/nextjs/server';
 
export default async function ProfilePage() {
  const user = await currentUser();
 
  if (!user) {
    redirect('/sign-in');
  }
 
  return (
    <div>
      <h1>{user.firstName} {user.lastName}</h1>
      <p>{user.email}</p>
    </div>
  );
}

API Routes

Route Handlers

// app/api/user/route.ts
import { auth } from '@bastionauth/nextjs/server';
import { NextResponse } from 'next/server';
 
export async function GET() {
  const { userId } = await auth();
 
  if (!userId) {
    return new NextResponse('Unauthorized', { status: 401 });
  }
 
  // Fetch user data...
  return NextResponse.json({ userId });
}

Protecting API Routes

// app/api/protected/route.ts
import { auth } from '@bastionauth/nextjs/server';
 
export async function POST(req: Request) {
  const { userId, getToken } = await auth();
 
  if (!userId) {
    return new Response('Unauthorized', { status: 401 });
  }
 
  // Call external API with token
  const token = await getToken();
  const response = await fetch('https://api.example.com/data', {
    headers: {
      Authorization: `Bearer ${token}`,
    },
  });
 
  return Response.json(await response.json());
}

Environment Variables

# .env.local
NEXT_PUBLIC_BASTION_KEY=pk_live_...
NEXT_PUBLIC_BASTION_API_URL=https://auth-api.yourdomain.com
BASTION_SECRET_KEY=sk_live_...

Re-exports

All React SDK exports are available from @bastionauth/nextjs:

import {
  SignIn,
  SignUp,
  UserButton,
  useAuth,
  useUser,
} from '@bastionauth/nextjs';