Next.js (App Router)
Integrate Aura Auth and Next.js App Router
This guide walks you through to implement Aura Auth in a Next.js application using the App Router with a complete support for Route Handlers, Server Components, and Server Actions. If you haven't configured Aura Auth yet, start with the Installation Guide and Quick Start Guide to set up your Auth instance and environment variables. Then follow the steps in this guide to integrate Aura Auth with your Next.js App Router application.
Aura Auth is working on developing a Next.js-specific package that will provide additional utilities and hooks for Next.js applications. For now, the core package can be used to implement authentication in Next.js with the patterns outlined in this guide. Stay tuned for updates on the Next.js package!
Setup Aura Auth
Create an Auth Instance
Create an auth.ts file in src/lib directory to configure your Aura Auth instance.
import { createAuth } from "@aura-stack/auth"
export const auth = createAuth({
oauth: ["github"],
basePath: "/api/auth",
baseURL: "http://localhost:3000",
})
export const { handlers, jose, api } = authThe basePath should match the path where your auth route handlers are mounted and baseURL should point to your local
development server or deployed application URL.
Create an Auth Client Instance
Create an auth-client.ts file in src/lib directory to enable client-side features.
import { createAuthClient } from "@aura-stack/auth/client"
export const authClient = createAuthClient({
basePath: "/api/auth",
baseURL: "http://localhost:3000",
})The basePath should match the path where your auth route handlers are mounted and baseURL should point to your local
development server or deployed application URL. Both options should be the same as the ones used in your auth.ts configuration
to ensure client and server instances are aligned.
Mount HTTP Handlers
Create a catch-all route in app/api/auth/[...aura]/route.ts to handle all authentication endpoints dynamically. The /api/auth path should match with the App Router Structure and basePath defined in your Auth configuration.
import { handlers } from "@/lib/auth"
export const { GET, POST, PATCH } = handlersRSC and Server Actions
The api object is designed for server environments such as Server Components and Server Actions.
When you need the active session on the server, pass the current request headers using headers() from next/headers. That gives Aura Auth access to the cookies and headers required to identify the session.
Sign-In
import { api } from "@/lib/auth"
import { redirect } from "next/navigation"
export default function LoginPage() {
const signInAction = async () => {
"use server"
const signIn = await api.signIn("github", {
redirect: false,
redirectTo: "/dashboard",
})
redirect(signIn.signInURL)
}
return (
<form action={signInAction}>
<button type="submit">Sign in with GitHub</button>
</form>
)
}Use this pattern when you want the server action to own the redirect destination while Aura Auth handles the provider flow.
Get Session
import { api } from "@/lib/auth"
import { headers } from "next/headers"
import { redirect } from "next/navigation"
export default async function DashboardPage() {
const headersStore = await headers()
const { session, authenticated } = await api.getSession({ headers: headersStore })
if (!authenticated) {
redirect("/login")
}
return (
<div>
<h1>Welcome back, {session.user?.name}</h1>
<img src={session.user?.image} alt="Profile Avatar" />
</div>
)
}This is the recommended pattern for protected App Router pages: check the session before rendering any private UI.
Sign Out
import { api } from "@/lib/auth"
import { headers } from "next/headers"
import { redirect } from "next/navigation"
export default async function DashboardPage() {
const signOutAction = async () => {
"use server"
const headerStore = await headers()
const response = await api.signOut({
headers: headerStore,
})
if (response.ok) {
redirect("/home")
}
}
return (
<form action={signOutAction}>
<button type="submit">Sign Out</button>
</form>
)
}If you prefer a client-only interaction, you can call authClient.signOut() from a client component instead.
Client Side Rendering (CSR)
Sign In
"use client"
import { authClient } from "@/lib/auth-client"
export const SignInButton = () => {
const handleSignIn = async () => {
await authClient.signIn("github", {
redirectTo: "/dashboard",
})
}
return <button onClick={handleSignIn}>Sign in with GitHub</button>
}Use a client component when you need a clickable auth button, custom modal, or other interactive sign-in entry point.
Get Session
"use client"
import { useEffect, useState } from "react"
import { authClient } from "@/lib/auth-client"
export const UserProfile = () => {
const [session, setSession] = useState(null)
useEffect(() => {
const fetchSession = async () => {
const { session } = await authClient.getSession()
setSession(session)
}
fetchSession()
}, [])
if (!session) return <div>Loading...</div>
return (
<div>
<h1>Welcome back, {session.user?.name}</h1>
<img src={session.user?.image} alt="Profile Avatar" />
</div>
)
}This is useful for session-aware UI that updates after hydration or after a client-side navigation.
Sign Out
To easily check sessions or log out from client components, use createAuthClient.
"use client"
import { authClient } from "@/lib/auth-client"
export const SignOutButton = () => {
const handleSignOut = async () => {
await authClient.signOut({
redirectTo: "/login",
})
}
return <button onClick={handleSignOut}>Sign out</button>
}Client-side sign-out is a better fit for navigation menus, profile popovers, and other interactive UI.
Common Pitfalls
- Mismatched Paths: Ensure the
basePathin your auth configuration matches the path where your route handlers are mounted. For example, if your handlers are inapp/api/auth/[...aura]/route.ts, thenbasePathshould be/api/auth. - Incorrect Headers: When calling
api.getSessionorapi.signOutfrom server components or actions, always pass the current request headers using Next.js'sheaders()function. This allows Aura Auth to read cookies and manage sessions correctly. - Don't update cookies in signOut: When signing out is called, Aura Auth will return a response with
Set-Cookieheaders and it's required to set the cookies usingcookiesfunction.