@bastionauth/nextjs
v0.1.7
Published
Next.js integration for BastionAuth - Server components, middleware, and API routes
Maintainers
Readme
Complete Next.js integration for BastionAuth with edge middleware, server components support, and API route helpers.
🏰 What is BastionAuth?
BastionAuth is a complete, self-hostable enterprise authentication system. Think Clerk, but you own your data.
- 🔐 Email/password, OAuth, magic links, passkeys
- 🔑 Multi-factor authentication (TOTP, backup codes)
- 🏢 Organizations & RBAC
- ⚡ Edge-ready middleware
- 🎨 Beautiful React components
- 🔒 Enterprise security (Argon2id, RS256 JWT)
Learn more: https://bastionauth.dev
Installation
npm install @bastionauth/nextjs
# or
pnpm add @bastionauth/nextjs
# or
yarn add @bastionauth/nextjsQuick Start
1. Environment Variables
Create .env.local:
NEXT_PUBLIC_BASTION_PUBLISHABLE_KEY=pk_live_...
BASTION_SECRET_KEY=sk_live_...
NEXT_PUBLIC_BASTION_API_URL=https://api.bastionauth.dev2. Wrap Your App
// app/layout.tsx
import { BastionProvider } from '@bastionauth/nextjs';
export default function RootLayout({ children }) {
return (
<html>
<body>
<BastionProvider>
{children}
</BastionProvider>
</body>
</html>
);
}3. Protect Routes with Middleware
// middleware.ts
import { authMiddleware } from '@bastionauth/nextjs';
export default authMiddleware({
publicRoutes: ['/', '/sign-in', '/sign-up'],
signInUrl: '/sign-in',
});
export const config = {
matcher: ['/((?!.*\\..*|_next).*)', '/', '/(api|trpc)(.*)'],
};4. Use in Server Components
// app/dashboard/page.tsx
import { auth, currentUser } from '@bastionauth/nextjs/server';
export default async function DashboardPage() {
const { userId } = await auth();
const user = await currentUser();
return (
<div>
<h1>Welcome, {user?.firstName}!</h1>
<p>User ID: {userId}</p>
</div>
);
}Features
Edge Middleware
Protect your routes at the edge before they even render.
import { authMiddleware } from '@bastionauth/nextjs';
export default authMiddleware({
// Public routes that don't require authentication
publicRoutes: ['/', '/about', '/pricing'],
// Routes that should ignore authentication
ignoredRoutes: ['/api/webhook'],
// Custom sign-in URL
signInUrl: '/sign-in',
// After sign-in redirect
afterSignIn: '/dashboard',
});Server-Side Authentication
Access authentication state in Server Components and API routes.
import { auth, currentUser } from '@bastionauth/nextjs/server';
// Get user ID and session ID
const { userId, sessionId } = await auth();
// Get full user object
const user = await currentUser();
// Get organization
const { organization, membership } = await auth();Client Components
All React SDK components and hooks are re-exported for convenience.
import {
useAuth,
useUser,
SignIn,
UserButton
} from '@bastionauth/nextjs';
function ClientComponent() {
const { isSignedIn, user } = useAuth();
return <div>Hello, {user?.firstName}</div>;
}API Route Protection
Protect API routes with authentication checks.
// app/api/protected/route.ts
import { auth } from '@bastionauth/nextjs/server';
import { NextResponse } from 'next/server';
export async function GET() {
const { userId } = await auth();
if (!userId) {
return NextResponse.json(
{ error: 'Unauthorized' },
{ status: 401 }
);
}
return NextResponse.json({ message: 'Protected data', userId });
}Middleware Configuration
Basic Configuration
import { authMiddleware } from '@bastionauth/nextjs';
export default authMiddleware({
publicRoutes: ['/'],
signInUrl: '/sign-in',
});Advanced Configuration
import { authMiddleware } from '@bastionauth/nextjs';
export default authMiddleware({
// Public routes (no auth required)
publicRoutes: ['/', '/about', '/pricing'],
// Ignored routes (skip middleware entirely)
ignoredRoutes: ['/api/webhook', '/api/health'],
// Sign-in URL
signInUrl: '/sign-in',
// Redirect after sign-in
afterSignIn: '/dashboard',
// Redirect after sign-up
afterSignUp: '/onboarding',
// Custom unauthorized handler
beforeAuth: (auth, req) => {
// Custom logic before authentication
console.log('Authenticating:', req.url);
},
// Custom handler after authentication
afterAuth: (auth, req) => {
// Custom logic after authentication
if (auth.userId && req.nextUrl.pathname === '/') {
return NextResponse.redirect(new URL('/dashboard', req.url));
}
},
});Pattern Matching
export const config = {
matcher: [
// Match all paths except static files
'/((?!.*\\..*|_next).*)',
// Match root
'/',
// Match API and tRPC routes
'/(api|trpc)(.*)',
],
};Server Helpers
auth()
Get authentication state in Server Components and API routes.
import { auth } from '@bastionauth/nextjs/server';
const {
userId, // string | null - current user ID
sessionId, // string | null - current session ID
orgId, // string | null - active organization ID
orgRole, // string | null - user's role in org
} = await auth();currentUser()
Get the full user object.
import { currentUser } from '@bastionauth/nextjs/server';
const user = await currentUser();
if (user) {
console.log(user.email);
console.log(user.firstName);
console.log(user.lastName);
}currentOrganization()
Get the active organization.
import { currentOrganization } from '@bastionauth/nextjs/server';
const { organization, membership } = await currentOrganization();
if (organization) {
console.log(organization.name);
console.log(membership.role);
}Examples
Protected Page
// app/dashboard/page.tsx
import { auth } from '@bastionauth/nextjs/server';
import { redirect } from 'next/navigation';
export default async function DashboardPage() {
const { userId } = await auth();
if (!userId) {
redirect('/sign-in');
}
return <div>Protected Dashboard</div>;
}User Profile Page
// app/profile/page.tsx
import { currentUser } from '@bastionauth/nextjs/server';
export default async function ProfilePage() {
const user = await currentUser();
return (
<div>
<h1>{user?.firstName} {user?.lastName}</h1>
<p>Email: {user?.email}</p>
<p>Member since: {user?.createdAt.toLocaleDateString()}</p>
</div>
);
}Organization Dashboard
// app/org/[orgId]/page.tsx
import { auth } from '@bastionauth/nextjs/server';
export default async function OrganizationPage({ params }) {
const { userId, orgId, orgRole } = await auth();
return (
<div>
<h1>Organization Dashboard</h1>
<p>Your role: {orgRole}</p>
</div>
);
}API Route with Auth
// app/api/user/route.ts
import { auth, currentUser } from '@bastionauth/nextjs/server';
import { NextResponse } from 'next/server';
export async function GET() {
try {
const { userId } = await auth();
if (!userId) {
return NextResponse.json(
{ error: 'Unauthorized' },
{ status: 401 }
);
}
const user = await currentUser();
return NextResponse.json({
user: {
id: user.id,
email: user.email,
name: `${user.firstName} ${user.lastName}`,
},
});
} catch (error) {
return NextResponse.json(
{ error: 'Internal Server Error' },
{ status: 500 }
);
}
}Sign-In Page
// app/sign-in/page.tsx
import { SignIn } from '@bastionauth/nextjs';
export default function SignInPage() {
return (
<div className="flex min-h-screen items-center justify-center">
<SignIn afterSignIn="/dashboard" />
</div>
);
}Client Component with Hooks
// components/user-menu.tsx
'use client';
import { useAuth, useUser } from '@bastionauth/nextjs';
export function UserMenu() {
const { isSignedIn, signOut } = useAuth();
const { user } = useUser();
if (!isSignedIn) {
return <a href="/sign-in">Sign in</a>;
}
return (
<div>
<p>Hello, {user?.firstName}!</p>
<button onClick={() => signOut()}>
Sign out
</button>
</div>
);
}App Router vs Pages Router
This package is designed for Next.js 13+ App Router. For Pages Router support, use the React SDK with custom middleware.
App Router (✅ Recommended)
// app/page.tsx - Server Component
import { auth } from '@bastionauth/nextjs/server';
export default async function Page() {
const { userId } = await auth();
return <div>{userId}</div>;
}Pages Router (Use React SDK)
// pages/index.tsx
import { BastionProvider, useAuth } from '@bastionauth/react';
export default function Page() {
const { userId } = useAuth();
return <div>{userId}</div>;
}TypeScript Support
Fully typed with TypeScript. All functions and components have complete type definitions.
import type { User, Session } from '@bastionauth/nextjs';
const user: User = await currentUser();Edge Runtime Compatibility
All middleware and server functions are compatible with the Edge Runtime.
export const runtime = 'edge';
export default authMiddleware({
// Edge-compatible middleware
});Related Packages
@bastionauth/react- React SDK with components and hooks@bastionauth/core- Shared types and utilities
Documentation
- Full Documentation: https://docs.bastionauth.dev
- Live Demo: https://bastionauth.dev
- Pricing: https://bastionauth.dev/pricing
- Next.js Guide: https://docs.bastionauth.dev/guides/nextjs-integration
- API Reference: https://docs.bastionauth.dev/api/nextjs
💰 Pricing
BastionAuth offers self-hosted authentication with transparent pricing:
- Free Tier: Up to 1,000 monthly active users
- Pro: $29/month for up to 10,000 users
- Enterprise: Custom pricing for unlimited users + premium support
Why Self-Hosted?
- 📊 No per-user costs at scale - Pay for hosting, not for users
- 🔐 Complete data ownership - Your data stays on your infrastructure
- 🌍 GDPR, HIPAA, SOC2 compliance ready - Meet any regulatory requirement
- 🚀 No vendor lock-in - You control your auth infrastructure
Support
- Email: [email protected]
- Website: bastionauth.dev
- Documentation: docs.bastionauth.dev
