SDKsTypeScript SDKGuides
Next.js Integration
Integrate Avnology ID with Next.js App Router using server components, middleware, and route handlers.
Next.js Integration
This guide covers Next.js 15 App Router integration with server-side session validation, middleware-based auth, and API route protection.
Setup
npm install @avnology/sdk-typescriptServer-side client
// lib/avnology-server.ts
import { AvnologyId } from "@avnology/sdk-typescript";
export function createServerClient() {
return new AvnologyId({
baseUrl: process.env.AVNOLOGY_BASE_URL!,
clientId: process.env.AVNOLOGY_CLIENT_ID!,
clientSecret: process.env.AVNOLOGY_CLIENT_SECRET!,
});
}Browser client
// lib/avnology-browser.ts
"use client";
import { AvnologyId } from "@avnology/sdk-typescript";
export const avnology = new AvnologyId({
baseUrl: process.env.NEXT_PUBLIC_AVNOLOGY_BASE_URL!,
clientId: process.env.NEXT_PUBLIC_AVNOLOGY_CLIENT_ID!,
credentials: "include",
});Middleware authentication
Protect routes at the edge with Next.js middleware.
// middleware.ts
import { NextResponse } from "next/server";
import type { NextRequest } from "next/server";
const protectedPaths = ["/dashboard", "/settings", "/admin"];
const publicPaths = ["/login", "/register", "/callback"];
export async function middleware(request: NextRequest) {
const { pathname } = request.nextUrl;
if (publicPaths.some((p) => pathname.startsWith(p))) {
return NextResponse.next();
}
if (protectedPaths.some((p) => pathname.startsWith(p))) {
const sessionCookie = request.cookies.get("avnology_session");
if (!sessionCookie) {
return NextResponse.redirect(new URL("/login", request.url));
}
}
return NextResponse.next();
}
export const config = {
matcher: ["/((?!_next/static|_next/image|favicon.ico).*)"],
};Server components
// app/dashboard/page.tsx
import { createServerClient } from "@/lib/avnology-server";
import { cookies } from "next/headers";
import { redirect } from "next/navigation";
export default async function DashboardPage() {
const client = createServerClient();
// Pass session cookie to the server client
const cookieStore = await cookies();
const sessionToken = cookieStore.get("avnology_session")?.value;
if (!sessionToken) {
redirect("/login");
}
const session = await client.getSession();
if (!session) {
redirect("/login");
}
return (
<div>
<h1>Dashboard</h1>
<p>Welcome, {session.identity.name?.first}</p>
</div>
);
}OAuth callback route
// app/callback/route.ts
import { createServerClient } from "@/lib/avnology-server";
import { cookies } from "next/headers";
import { redirect } from "next/navigation";
export async function GET(request: Request) {
const url = new URL(request.url);
const code = url.searchParams.get("code");
const state = url.searchParams.get("state");
if (!code) {
redirect("/login?error=missing_code");
}
const client = createServerClient();
const cookieStore = await cookies();
const codeVerifier = cookieStore.get("pkce_code_verifier")?.value;
const tokens = await client.oauth.exchangeCode({
code,
codeVerifier: codeVerifier!,
redirectUri: `${url.origin}/callback`,
});
// Set session cookie (httpOnly, secure)
cookieStore.set("avnology_session", tokens.accessToken, {
httpOnly: true,
secure: true,
sameSite: "lax",
maxAge: tokens.expiresIn,
path: "/",
});
redirect("/dashboard");
}API route protection
// app/api/users/route.ts
import { createServerClient } from "@/lib/avnology-server";
import { NextResponse } from "next/server";
export async function GET(request: Request) {
const authHeader = request.headers.get("authorization");
if (!authHeader?.startsWith("Bearer ")) {
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
}
const client = createServerClient();
const result = await client.oauth.introspectToken({
token: authHeader.slice(7),
});
if (!result.active) {
return NextResponse.json({ error: "Invalid token" }, { status: 401 });
}
const users = await client.admin.listUsers({ pageSize: 25 });
return NextResponse.json(users);
}See also
- React guide -- Client-side React integration
- Express guide -- Express.js middleware