Sign in

Protect API Routes

This guide shows how to protect API routes in a Next.js Pages Router application using protectApi().

Protected API routes require authentication and can optionally enforce group-based authorization.

What you'll cover

  • Protect an API route with protectApi()
  • Restrict API access based on group membership
  • Customize responses for unauthenticated and unauthorized requests

Before you begin

This guide assumes you’ve completed the Next.js Pages Router quickstart.

You should already have:

  • A Next.js Pages Router project (pages/ directory)
  • Environment variables configured in .env.local
  • Authentication middleware registered
  • Any unprotected routes explicitly configured (matched routes are protected by default)

Protect an API route

Create an API route and wrap the handler with protectApi().

src/pages/api/data.ts
import { protectApi } from "@monocloud/auth-nextjs";
import { NextApiRequest, NextApiResponse } from "next";

export default protectApi((_req: NextApiRequest, res: NextApiResponse) => {
  res.status(200).json({
    message: "You have accessed a protected endpoint",
  });
});

How it works:

  • protectApi() runs on every request
  • Unauthenticated requests are blocked before your handler executes
  • Authenticated requests execute your handler as normal

Restrict access by group

You can require users to belong to specific groups before accessing an API route.

Enable group claims

  1. In the MonoCloud Dashboard, add groups to the application scopes
  2. Update your .env.local:
.env.local
MONOCLOUD_AUTH_SCOPES=openid profile email groups
After updating scopes, users must sign out and sign back in for the new claims to be included in their session.

Require a group

src/pages/api/data.ts
import { protectApi } from "@monocloud/auth-nextjs";
import { NextApiRequest, NextApiResponse } from "next";

export default protectApi(
  (_req: NextApiRequest, res: NextApiResponse) => {
    res.status(200).json({ message: "Admin-only data" });
  },
  {
    groups: ["admin"],
  }
);

Handle access denied errors (Unauthenticated)

To customize the response when a user is not authenticated, pass the onAccessDenied option.

src/pages/api/data.ts
import { protectApi } from "@monocloud/auth-nextjs";
import { NextApiRequest, NextApiResponse } from "next";

export default protectApi(
  (_req: NextApiRequest, res: NextApiResponse) => {
    res.status(200).json({ message: "Protected data" });
  },
  {
    onAccessDenied: (_req, res) => {
      res.status(401).json({
        error: "unauthorized",
        message: "Please sign in"
      });
    }
  }
);

How it works:

  • Runs when the request does not contain a valid authenticated session.
  • The protected handler is not executed.
  • If omitted, returns a default 401 Unauthorized JSON response.

Handle access denied (Group authorization)

To customize the response when a user is authenticated but does not belong to the required group, pass the onGroupAccessDenied option.

src/pages/api/data.ts
import { protectApi } from "@monocloud/auth-nextjs";
import { NextApiRequest, NextApiResponse } from "next";

export default protectApi(
  (_req: NextApiRequest, res: NextApiResponse) => {
    res.status(200).json({ message: "Admin-only data" });
  },
  {
    groups: ["admin"],
    onGroupAccessDenied: (_req, res, user) => {
      res.status(403).json({
        error: "forbidden",
        message: `User ${user.email} does not have access to this resource.`
      });
    }
  }
);

How it works:

  • Runs when a valid authenticated session exists but the group authorization check fails.
  • The protected handler is not executed.
  • If omitted, returns a default 403 Forbidden JSON response.

Response behavior

  • Unauthenticated requests: Receive a 401 Unauthorized response (or the result returned by onAccessDenied).
  • Authenticated users without required groups: Receive a 403 Forbidden response (or the result returned by onGroupAccessDenied).
  • Authorized users: The protected handler executes normally and its response is returned.

Next steps

Protect other parts of your application:

© 2024 MonoCloud. All rights reserved.