Add authentication to your Next.js app
This guide walks you through adding authentication, user management, and access control to a Next.js application using @lumoauth/react (client components) and @lumoauth/sdk (server-side).
Before you start
You need:
- A LumoAuth account with a configured tenant (sign up)
- A registered OAuth application with redirect URIs for both App Router and Pages Router as applicable
- Next.js 13+ (App Router) or Next.js 12+ (Pages Router)
Install the SDKs
npm install @lumoauth/react @lumoauth/sdk
Environment variables
Add to .env.local:
NEXT_PUBLIC_LUMOAUTH_DOMAIN=https://app.lumoauth.dev
NEXT_PUBLIC_LUMOAUTH_TENANT=YOUR_TENANT_SLUG
NEXT_PUBLIC_LUMOAUTH_CLIENT_ID=YOUR_CLIENT_ID
Configure the provider (App Router)
app/providers.tsx — client component wrapper:
'use client';
import { LumoAuthProvider } from '@lumoauth/react';
export function Providers({ children }: { children: React.ReactNode }) {
return (
<LumoAuthProvider
domain={process.env.NEXT_PUBLIC_LUMOAUTH_DOMAIN!}
tenantSlug={process.env.NEXT_PUBLIC_LUMOAUTH_TENANT!}
clientId={process.env.NEXT_PUBLIC_LUMOAUTH_CLIENT_ID!}
afterSignInUrl="/dashboard"
afterSignOutUrl="/"
>
{children}
</LumoAuthProvider>
);
}
app/layout.tsx:
import { Providers } from './providers';
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="en">
<body><Providers>{children}</Providers></body>
</html>
);
}
Pages Router (pages/_app.tsx)
import { LumoAuthProvider } from '@lumoauth/react';
export default function App({ Component, pageProps }) {
return (
<LumoAuthProvider
domain={process.env.NEXT_PUBLIC_LUMOAUTH_DOMAIN!}
tenantSlug={process.env.NEXT_PUBLIC_LUMOAUTH_TENANT!}
clientId={process.env.NEXT_PUBLIC_LUMOAUTH_CLIENT_ID!}
>
<Component {...pageProps} />
</LumoAuthProvider>
);
}
Auth callback route
app/auth/callback/page.tsx:
'use client';
import { AuthCallback } from '@lumoauth/react';
export default function CallbackPage() {
return (
<AuthCallback
afterSignInUrl="/dashboard"
loading={<p>Signing in…</p>}
/>
);
}
Protecting pages
'use client';
import { SignedIn, SignedOut, RedirectToSignIn, UserButton } from '@lumoauth/react';
export default function DashboardPage() {
return (
<>
<SignedOut><RedirectToSignIn /></SignedOut>
<SignedIn>
<UserButton showName />
<Dashboard />
</SignedIn>
</>
);
}
Fine-grained access control
Use <Protect> for RBAC, Zanzibar (ReBAC), and ABAC checks:
'use client';
import { Protect } from '@lumoauth/react';
// RBAC
<Protect permission="billing.manage" fallback={<p>No access</p>}>
<BillingDashboard />
</Protect>
// Zanzibar (ReBAC)
<Protect
zanzibar={{ object: `document:${docId}`, relation: 'editor', subject: `user:${userId}` }}
fallback={<ReadOnly />}
>
<EditForm />
</Protect>
// ABAC
<Protect
abac={{ resourceType: 'document', action: 'read', resourceId: docId }}
fallback={<Denied />}
>
<SecretContent />
</Protect>