Sign in

Protect Server Rendered Pages

This guide shows how to protect server-rendered pages in a Next.js Pages Router application using protectPage().

Protected pages require authentication and can optionally enforce group-based authorization, customize redirects, and render custom access denied UI.

What you'll cover

  • Protect a server-rendered page with protectPage()
  • Customize where users return after signing in
  • Restrict access based on group membership
  • Render custom UI for unauthenticated users or users without required permissions

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 a server-rendered page

Create a Pages Router page and wrap getServerSideProps with protectPage().

src/pages/index.tsx
import { MonoCloudUser, protectPage } from "@monocloud/auth-nextjs";

type Props = {
  user: MonoCloudUser;
};

export default function ServerPage({ user }: Props) {
  return <div>Hi {user.email}</div>;
}

export const getServerSideProps = protectPage<Props>();

How it works:

  • protectPage() runs on every request
  • Unauthenticated users are redirected to sign in
  • After authentication, the user object is injected into page props

Customize the return URL

By default, users are returned to the page they attempted to access.

To redirect users to a specific route after authentication, pass a returnUrl.

src/pages/index.tsx
export const getServerSideProps = protectPage<Props>({
  returnUrl: "/dashboard",
});

After authentication, users are redirected to http://localhost:3000/dashboard

Restrict access by group

You can restrict access to users belonging to specific groups.

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/index.tsx
export const getServerSideProps = protectPage<Props>({
  groups: ["admin"],
});

With this configuration, only authenticated users in the admin group can access the page.

Handle access denied (Unauthenticated)

Use onAccessDenied to override the default redirect when a user is not authenticated.

src/pages/index.tsx
export const getServerSideProps = protectPage<Props>({
  onAccessDenied: (ctx) => ({
    redirect: {
      destination: "/custom-signin",
      permanent: false,
    },
  }),
});

How it works:

  • Runs when no authenticated session exists.
  • If onAccessDenied is not provided, the user is automatically redirected to the sign-in flow.

Handle access denied (Group authorization)

Use onGroupAccessDenied to customize the behavior when a user is authenticated but does not belong to the required group.

src/pages/index.tsx
export const getServerSideProps = protectPage<Props>({
  groups: ["admin"],
  onGroupAccessDenied: (ctx) => {
    console.warn(`Unauthorized access attempt by ${ctx.user.email}`);
    return {
      redirect: {
        destination: "/403",
        permanent: false,
      },
    };
  },
});

How it works:

  • Runs when a valid session exists but the group check fails.
  • The handler receives the standard getServerSideProps context extended with the authenticated user.

If onGroupAccessDenied is not provided, protectPage() injects a groupAccessDenied: true prop into the page so you can render an alternate UI.

src/pages/index.tsx
export default function ServerPage({ user, groupAccessDenied }: Props) {
  if (groupAccessDenied) {
    return <div>Access Denied</div>;
  }
  return <div>Hi {user.email}</div>;
}

Next steps

Protect other parts of your application:

© 2024 MonoCloud. All rights reserved.