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/reactSetup
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';