HelloJohn / docs
SDKsNext.js SDK

Middleware

Protect Next.js routes at the edge with HelloJohn middleware — authentication checks, redirects, and role-based access in middleware.ts.

Middleware

HelloJohn's Next.js middleware protects routes at the edge before any page code runs. It validates JWTs from cookies or the Authorization header and redirects unauthenticated requests.


Setup

Create middleware.ts in your project root:

// middleware.ts
import { hellojohnMiddleware } from "@hellojohn/nextjs";

export default hellojohnMiddleware({
  publicRoutes: ["/", "/sign-in", "/sign-up", "/about"],
  loginUrl: "/sign-in",
});

export const config = {
  matcher: [
    // Match all routes except static files and Next.js internals
    "/((?!_next|[^?]*\\.(?:html?|css|js(?!on)|jpe?g|webp|png|gif|svg|ttf|woff2?|ico|csv|docx?|xlsx?|zip|webmanifest)).*)",
    "/(api|trpc)(.*)",
  ],
};

Configuration Options

OptionTypeDefaultDescription
publicRoutesstring[][]Routes accessible without authentication
loginUrlstring"/sign-in"Redirect URL for unauthenticated users
afterSignInUrlstring"/"Redirect for already-authenticated users on auth pages
ignoredRoutesstring[][]Routes bypassed entirely by middleware
debugbooleanfalseLog middleware decisions

Public vs Protected Routes

export default hellojohnMiddleware({
  // These routes are accessible without authentication
  publicRoutes: [
    "/",
    "/pricing",
    "/blog(.*)",          // Wildcard: match /blog and all sub-paths
    "/api/webhooks(.*)",  // Public API endpoints
  ],

  // Everything else requires authentication
  loginUrl: "/sign-in",
});

Routes not in publicRoutes automatically require authentication.


Accessing Auth State in Middleware

import { hellojohnMiddleware, getAuth } from "@hellojohn/nextjs";
import { NextResponse } from "next/server";
import type { NextRequest } from "next/server";

export default hellojohnMiddleware(async (auth, req: NextRequest) => {
  const { userId, sessionId, orgId, orgRole } = auth();

  // Custom logic: require org membership for /app routes
  if (req.nextUrl.pathname.startsWith("/app") && !orgId) {
    return NextResponse.redirect(new URL("/select-org", req.url));
  }

  // Role-based access: /admin requires "admin" role
  if (req.nextUrl.pathname.startsWith("/admin") && orgRole !== "admin") {
    return NextResponse.redirect(new URL("/dashboard", req.url));
  }
});

Auth Object Properties

PropertyTypeDescription
userIdstring | nullAuthenticated user ID
sessionIdstring | nullCurrent session ID
orgIdstring | nullActive organization ID
orgRolestring | nullUser's role in the active org
getToken()() => Promise<string>Get the access token for outgoing requests

Protecting API Routes

Middleware protects API routes automatically. For API routes that should be public (e.g., webhooks), add them to ignoredRoutes:

export default hellojohnMiddleware({
  publicRoutes: [...],
  ignoredRoutes: [
    "/api/webhooks",
    "/api/health",
  ],
});

Edge Runtime Compatibility

HelloJohn's middleware runs in Next.js Edge Runtime. It verifies JWTs locally using the JWKS public key (no round-trip to HelloJohn). This makes it fast (sub-millisecond) and works on Vercel Edge, Cloudflare Workers, and other edge platforms.

The middleware does not make network requests for token validation by default.


On this page