<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Shivangi Tripathi</title>
    <description>The latest articles on DEV Community by Shivangi Tripathi (@rogue-tink).</description>
    <link>https://dev.to/rogue-tink</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3950907%2F854dd6e2-e271-408c-acaa-be8cdd0ec82c.png</url>
      <title>DEV Community: Shivangi Tripathi</title>
      <link>https://dev.to/rogue-tink</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/rogue-tink"/>
    <language>en</language>
    <item>
      <title>Next.js Authentication: The Complete 2026 Guide</title>
      <dc:creator>Shivangi Tripathi</dc:creator>
      <pubDate>Fri, 12 Jun 2026 12:03:18 +0000</pubDate>
      <link>https://dev.to/monocloud/nextjs-authentication-the-complete-2026-guide-5bok</link>
      <guid>https://dev.to/monocloud/nextjs-authentication-the-complete-2026-guide-5bok</guid>
      <description>&lt;p&gt;Most Next.js authentication tutorials teach you how to build the plumbing. This one skips that. You don't need to write session logic, token exchange, or JWT verification yourself — and you definitely shouldn't. You need to know where auth lives in a Next.js app, how the App Router changes things, and how to ship it fast without painting yourself into a corner.&lt;/p&gt;

&lt;p&gt;A production Next.js app needs session management that survives page refreshes, protected routes that redirect unauthenticated users without flicker, API endpoints that reject requests without a valid token, Server Actions that verify identity before running any business logic, and a sign-in/sign-out flow that handles the OAuth/OIDC roundtrip.&lt;/p&gt;

&lt;p&gt;Let's go through each one.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where Auth Lives in Next.js App Router
&lt;/h2&gt;

&lt;p&gt;Next.js 13+ separates your code into two runtimes: server and client. Auth decisions should happen on the server. If you're checking auth state in a client component to decide what to render, you're doing it in the wrong place — there will be a flash of unauthenticated content before the check resolves.&lt;/p&gt;

&lt;p&gt;The right model:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Middleware / proxy:&lt;/strong&gt; handles route protection at the edge — before the page renders&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Server Components:&lt;/strong&gt; access session data directly from the request&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Client Components:&lt;/strong&gt; receive auth state as props from the server, or via a lightweight hook&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This matters because it determines where tokens are stored and how they're validated.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setup
&lt;/h2&gt;

&lt;p&gt;Install the SDK:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install @monocloud/auth-nextjs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create &lt;code&gt;.env.local&lt;/code&gt; with your credentials from the &lt;a href="https://dashboard.monocloud.com" rel="noopener noreferrer"&gt;MonoCloud dashboard&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;MONOCLOUD_AUTH_TENANT_DOMAIN=https://&amp;lt;your-tenant-domain&amp;gt;
MONOCLOUD_AUTH_CLIENT_ID=&amp;lt;your-client-id&amp;gt;
MONOCLOUD_AUTH_CLIENT_SECRET=&amp;lt;your-client-secret&amp;gt;
MONOCLOUD_AUTH_SCOPES=openid profile email
MONOCLOUD_AUTH_APP_URL=http://localhost:3000
MONOCLOUD_AUTH_COOKIE_SECRET=&amp;lt;random-secret&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Generate a cookie secret with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;openssl rand -hex 32
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  One File, Full Auth
&lt;/h2&gt;

&lt;p&gt;In Next.js 16+, authentication middleware uses a proxy-based approach. Create &lt;code&gt;proxy.ts&lt;/code&gt; in your project root:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { authMiddleware } from "@monocloud/auth-nextjs";

export default authMiddleware();

export const config = {
  matcher: ["/((?!_next/static|_next/image|favicon.ico|sitemap.xml|robots.txt).*)"],
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This gives you the entire OpenID Connect flow — redirects, token exchange, cookie-based session storage, silent refresh. By default, every matched route requires authentication. Unauthenticated users are redirected to sign in.&lt;/p&gt;

&lt;p&gt;To protect only specific routes (everything else passes through unauthenticated):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { authMiddleware } from "@monocloud/auth-nextjs";

export default authMiddleware({
  protectedRoutes: ["/dashboard", "/settings", "/api/orders"],
});

export const config = {
  matcher: ["/((?!_next/static|_next/image|favicon.ico|sitemap.xml|robots.txt).*)"],
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; If you need multiple configurations, custom routes, or dependency injection, you can create a &lt;code&gt;MonoCloudNextClient&lt;/code&gt; instance manually. For standard setups, the direct &lt;code&gt;authMiddleware()&lt;/code&gt; import above is all you need.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Protecting Pages
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;protectPage()&lt;/code&gt; is a HOC that wraps your Server Component. The user object is injected as a prop — you never need to call &lt;code&gt;getSession()&lt;/code&gt; manually inside a protected page:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { MonoCloudUser, protectPage } from "@monocloud/auth-nextjs";

type Props = { user: MonoCloudUser };

function DashboardPage({ user }: Props) {
  return (
    &amp;lt;div&amp;gt;
      &amp;lt;h1&amp;gt;Welcome, {user.name}&amp;lt;/h1&amp;gt;
      &amp;lt;p&amp;gt;{user.email}&amp;lt;/p&amp;gt;
    &amp;lt;/div&amp;gt;
  );
}

export default protectPage(DashboardPage);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Unauthenticated users are redirected to sign in. Your component code only runs for authenticated sessions.&lt;/p&gt;

&lt;p&gt;To restrict to a specific group (RBAC):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export default protectPage(AdminPage, { groups: ["admin"] });
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Users not in the &lt;code&gt;admin&lt;/code&gt; group are shown an access denied message before your component renders.&lt;/p&gt;

&lt;h2&gt;
  
  
  Protecting API Routes
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;protectApi()&lt;/code&gt; wraps your route handler. The handler signature is &lt;code&gt;(req, ctx)&lt;/code&gt; — to read the authenticated user inside, call &lt;code&gt;getSession()&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { protectApi, getSession } from "@monocloud/auth-nextjs";
import { NextResponse } from "next/server";
import { db } from "@/lib/db";

export const GET = protectApi(async (req, ctx) =&amp;gt; {
  const session = await getSession();
  const orders = await db.orders.findMany({
    where: { userId: session!.user.sub },
  });
  return NextResponse.json(orders);
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Unauthenticated requests get a &lt;code&gt;401&lt;/code&gt; before your handler runs. &lt;code&gt;getSession()&lt;/code&gt; inside a protected handler is safe — the session is guaranteed to exist.&lt;/p&gt;

&lt;h2&gt;
  
  
  Server Actions
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"use server";

import { protect, getSession } from "@monocloud/auth-nextjs";
import { db } from "@/lib/db";

export async function placeOrder(items: CartItem[]) {
  await protect(); // redirects if not authenticated

  const session = await getSession();
  const userId = session!.user.sub;

  return db.orders.create({
    data: { userId, items, status: "pending" },
  });
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;protect()&lt;/code&gt; guards the action — if the session is missing, the user is redirected to sign in and the action body never executes. Retrieve the user via &lt;code&gt;getSession()&lt;/code&gt; when you need identity data inside the action.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reading Auth State Server-Side
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { getSession } from "@monocloud/auth-nextjs";

export default async function HomePage() {
  const session = await getSession();

  if (!session) {
    return &amp;lt;p&amp;gt;You are not signed in.&amp;lt;/p&amp;gt;;
  }

  return &amp;lt;p&amp;gt;Hello, {session.user.name}&amp;lt;/p&amp;gt;;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Client Components
&lt;/h2&gt;

&lt;p&gt;For client-side auth state, use &lt;code&gt;useAuth()&lt;/code&gt; from the &lt;code&gt;/client&lt;/code&gt; subpath:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"use client";

import { useAuth } from "@monocloud/auth-nextjs/client";

export function UserMenu() {
  const { user, isAuthenticated, isLoading } = useAuth();

  if (isLoading) {
    return &amp;lt;div className="h-8 w-8 animate-pulse rounded-full bg-gray-200" /&amp;gt;;
  }

  if (!isAuthenticated || !user) {
    return &amp;lt;a href="/api/auth/login"&amp;gt;Sign in&amp;lt;/a&amp;gt;;
  }

  return (
    &amp;lt;div className="flex items-center gap-2"&amp;gt;
      &amp;lt;span className="text-sm"&amp;gt;{user.name}&amp;lt;/span&amp;gt;
      &amp;lt;a href="/api/auth/logout" className="text-sm text-gray-500"&amp;gt;Sign out&amp;lt;/a&amp;gt;
    &amp;lt;/div&amp;gt;
  );
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To protect a client component with a HOC:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"use client";

import { MonoCloudUser } from "@monocloud/auth-nextjs";
import { protectClientPage } from "@monocloud/auth-nextjs/client";

type Props = { user: MonoCloudUser };

const ProfilePage = ({ user }: Props) =&amp;gt; (
  &amp;lt;div&amp;gt;
    &amp;lt;h2&amp;gt;{user.name}&amp;lt;/h2&amp;gt;
    &amp;lt;p&amp;gt;{user.email}&amp;lt;/p&amp;gt;
  &amp;lt;/div&amp;gt;
);

export default protectClientPage(ProfilePage);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note: &lt;code&gt;protectClientPage()&lt;/code&gt; runs in the browser — use &lt;code&gt;protectPage()&lt;/code&gt; (server) for anything security-sensitive.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sign In and Sign Out
&lt;/h2&gt;

&lt;p&gt;Use the &lt;code&gt;&amp;lt;SignIn /&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;SignOut /&amp;gt;&lt;/code&gt; components provided by the SDK:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { getSession } from "@monocloud/auth-nextjs";
import { SignIn, SignOut } from "@monocloud/auth-nextjs/components";

export async function Navbar() {
  const session = await getSession();

  return (
    &amp;lt;nav&amp;gt;
      {session ? (
        &amp;lt;SignOut&amp;gt;Sign out&amp;lt;/SignOut&amp;gt;
      ) : (
        &amp;lt;SignIn&amp;gt;Sign in&amp;lt;/SignIn&amp;gt;
      )}
    &amp;lt;/nav&amp;gt;
  );
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The SDK registers all required auth routes automatically. No route handler file needed.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Not to Do
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Don't store tokens in localStorage.&lt;/strong&gt; Any XSS on your domain exposes them. The SDK uses httpOnly cookies.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Don't check auth in client components for security.&lt;/strong&gt; Client-side auth checks are UI hints only. Use &lt;code&gt;protectPage()&lt;/code&gt; or &lt;code&gt;protectApi()&lt;/code&gt; for enforcement.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Don't roll your own JWT validation.&lt;/strong&gt; JWKS rotation, clock skew, audience verification, algorithm pinning — there are eight ways to get this wrong and you'll find most of them in production.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Next Steps
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Docs:&lt;/strong&gt; &lt;a href="https://www.monocloud.com/docs/sdks/nextjs/index" rel="noopener noreferrer"&gt;MonoCloud Next.js SDK&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Working example:&lt;/strong&gt; &lt;a href="https://github.com/monocloud/monogrub-nextjs-demo" rel="noopener noreferrer"&gt;MonoGrub on GitHub&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Add RBAC:&lt;/strong&gt; Pass &lt;code&gt;groups: ["admin"]&lt;/code&gt; to &lt;code&gt;protectPage()&lt;/code&gt; or &lt;code&gt;protectApi()&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Profile management:&lt;/strong&gt; &lt;a href="https://github.com/monocloud/management-js" rel="noopener noreferrer"&gt;MonoCloud Management SDK&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Start Building for Free with MonoCloud
&lt;/h2&gt;

&lt;p&gt;We built MonoCloud after learning for ourselves that authentication and user management are hard. But we knew that building an easy-to-use tool wasn't enough. Our platform isn't just about saving you a few days of coding. Instead, it's about adding the expertise you need to secure your software for the long term.&lt;/p&gt;

&lt;p&gt;You can start building with MonoCloud today. Sign up now for your free account. Click here &lt;a href="https://www.monocloud.com/" rel="noopener noreferrer"&gt;monocloud.com&lt;/a&gt;&lt;/p&gt;

</description>
      <category>nextjs</category>
      <category>authentication</category>
      <category>webdev</category>
      <category>oauth</category>
    </item>
  </channel>
</rss>
