Using the Next.js App Router instead? See the App Router version of this guide.
The source code and sample for the project can be found at the following GitHub repository: Pages Router Sample.
In MonoCloud, you can create different clients. Each one represents an application you want to secure with MonoCloud. To get started, create a client configuration for the Next.js app we'll create in this guide:

On your new client's overview page, scroll down to the URLs section and add the following:
Set the Callback URIs to http://localhost:3000/api/auth/callback and the Sign-out URIs to http://localhost:3000.
Next, scroll to the Scopes section where you'll find two types of scope:
Select openid, profile, and email in Identity scopes. We can leave API scopes for now.
If you don't have one yet, set up a fresh Next.js app by running the following command in your terminal:
npx create-next-app@latest quickstart
This command will create a new Next.js application in a directory named 'quickstart'.
It will ask you some configuration questions. The ones to look out for are:

In this guide, we're working with the Next.js Page Router. See the App Router version of this guide if you prefer.
Next install the MonoCloud SDK for Next.js. In your new project directory, run:
npm install @monocloud/nextjs-auth
To connect the MonoCloud SDK with your MonoCloud project, you'll need to set up some environment variables.
Create an .env.local file in your application's root directory and open your client's settings page in the MonoCloud Dashboard.
You'll find the first three values you need in the General Settings and Secrets sections on the client's setting page:
| Environment variable | Where to find the value in MonoCloud |
|---|---|
MONOCLOUD_AUTH_ISSUER | Tenant Domain from General Settings |
MONOCLOUD_AUTH_CLIENT_ID | Client ID also from General Settings |
MONOCLOUD_AUTH_CLIENT_SECRET | For now, use the default secret in the Secrets section |
MONOCLOUD_AUTH_SCOPES | Set this to openid profile email, the types of user profile data for our app |
MONOCLOUD_AUTH_APP_URL | In dev, this will be http://localhost:3000 |
MONOCLOUD_AUTH_COOKIE_SECRET | Generate a secret key using your preferred method or run the following command in the terminal: openssl rand -hex 32 |
Your .env.local file should look like this, with your specific values in place of the placeholders:
MONOCLOUD_AUTH_ISSUER=https://<your-domain>
MONOCLOUD_AUTH_CLIENT_ID=<your-client-id>
MONOCLOUD_AUTH_CLIENT_SECRET=<your-client-secret>
MONOCLOUD_AUTH_SCOPES=openid profile email
MONOCLOUD_AUTH_APP_URL=http://localhost:3000
MONOCLOUD_AUTH_COOKIE_SECRET=<your_secret>
Now we're ready to add authentication to the Next.js app. We'll start by creating a header component with a sign-in and sign-out button.
components folder under src.components folder, create a header.tsx file.import { SignIn, SignOut, SignUp } from "@monocloud/nextjs-auth/components";
import { useUser } from "@monocloud/nextjs-auth/client";
import Link from "next/link";
export default function Header() {
const { user, isAuthenticated } = useUser();
return (
<nav className='flex bg-slate-900 p-4 justify-between text-white'>
{isAuthenticated ? (
<h1>Hello {user?.email}</h1>
) : (
<div>Welcome</div>
)}
<div className='flex gap-4'>
<Link href='/'>Home</Link>
{isAuthenticated ? (
<>
<Link href='/server'>Server Page</Link>
<Link href='/client'>Client Page</Link>
<SignOut>Sign Out</SignOut>
</>
) : (
<>
<SignIn>Sign In</SignIn>
<SignUp>Sign Up</SignUp>
</>
)}
</div>
</nav>
);
}
Let's walk through the component briefly:
For now, don't worry about the /server and /client links; we'll set them up later.
Now that we have a header, we need to render it and manage authentication state.
On the client-side, we'll do that using the MonoCloudAuthProvider component from the MonoCloud SDK. This component takes care of:
In the src/pages folder of your Next.js project you'll find _app.tsx. Open the file in your editor and replace the contents with the following code:
import "@/styles/globals.css";
import type { AppProps } from "next/app";
import { MonoCloudAuthProvider } from "@monocloud/nextjs-auth/client";
import Header from "@/components/header";
export default function App({
Component,
pageProps: { session, ...pageProps }
}: AppProps) {
return (
<MonoCloudAuthProvider>
<Header />
<Component {...pageProps} />
</MonoCloudAuthProvider>
)
}
Here, we're importing the MonoCloudAuthProvider component and using it to wrap the page contents. This allows us to share the session object across components using React Context for client-rendered components.
Next we'll set up the handler that will interact with MonoCloud on the server-side of your Next.js app.
We'll start by creating the folders we need and a catch-all route.
src/pages/api, create a new folder named auth.auth, set up our catch-all route by creating a file named [...monocloud].ts.In that new file, paste the following code:
import { monoCloudAuth } from "@monocloud/nextjs-auth";
export default monoCloudAuth();
monoCloudAuth() adds the core authentication functionality, including:
Let's recap where we are so far:
MonoCloudAuthProvider to our app to manage authentication state and make available the user's session in client-rendered components.Now we need to set up the server and client components that will display the user's session and profile data.
As we saw in the header component, we have two links: Server Page and Client Page. Let's create two pages, one with a server-side component and another with a client-side component. We'll use getSession() and useUser() from the MonoCloud SDK to display the current session details and some information about the user.
In this quickstart, we're not protecting any particular pages or endpoints. Instead, we're logging a user in and displaying their session and user information.
In a real application, protect individual pages usingprotectPage()or protect several pages and endpoints usingmonoCloudMiddleware().
src/pages folder create a new folder named server.index.tsx and add the code below:import { getSession } from '@monocloud/nextjs-auth';
import { InferGetServerSidePropsType, NextApiRequest, NextApiResponse, GetServerSideProps } from 'next';
export default function ServerPage({
user,
}: InferGetServerSidePropsType<typeof getServerSideProps>) {
if (!user) return <div>Please Sign In...</div>;
return (
<div className='mt-5 ml-5'>
<p>Hello {user.email} from the Server</p>
<h1>User:</h1>
<div className='pl-2 flex flex-col gap-2'>
<textarea
className='text-black w-3/5 p-2 rounded-md text-sm'
cols={30}
rows={10}
value={JSON.stringify(user, undefined, 2)}
readOnly={true}
/>
</div>
</div>
);
}
export const getServerSideProps: GetServerSideProps = async (ctx) => {
const session = await getSession(ctx.req, ctx.res);
return { props: { user: session?.user } };
};
Now we have a server-rendered page that uses getSession() from @monocloud/nextjs-auth to:
Now let's create a client-rendered page to display the user's session and profile data.
Just as with server-rendered pages, in a real application you'd protect individual pages by usingprotectPage()or protecting several pages and endpoints withmonoCloudMiddleware()from@monocloud/nextjs-auth.
src/pages folder create a new folder named client.index.tsx and add the code below:import { useUser } from '@monocloud/nextjs-auth/client';
export default function ClientSide() {
const { user, isAuthenticated, isLoading } = useUser();
if (isLoading) return <div>Loading...</div>;
if (!user) return <div>Something went wrong!</div>;
if (!isAuthenticated) return <div>Please Sign In...</div>;
return (
<div className='mt-5 ml-5'>
<p>Hello {user.email} from the Client</p>
<h1>User:</h1>
<div className='pl-2 flex flex-col gap-2'>
<textarea
className='text-black w-3/5 p-2 rounded-md text-sm'
cols={30}
rows={10}
value={JSON.stringify(user, undefined, 2)}
readOnly={true}
/>
</div>
</div>
);
}
The client-rendered page uses the useUser() hook from the MonoCloud SDK to get the current user's profile. This page is rendered on the client side, and the user state returned by the hook is displayed on the page. If the user is not authenticated we invite them to sign-in.
Now we've put it all together, let's run our new Next.js app by executing the following in your terminal:
npm run dev
To see your MonoCloud protected Next.js application in action, visit: http://localhost:3000
Try it out by clicking the Sign in button in the header. That will take you through the log-in flow using MonoCloud. Once you're signed in, visit the server-rendered page by clicking the Server Page link in the header and then the client-rendered page by clicking the Client Page link.
Now jump back to the MonoCloud Dashboard and check out the Users section to see yourself in the users list.
Finally, back in your Next.js app, click Sign Out in the header to see the sign-out flow in action.
Great work! You've just secured a Next.js application using MonoCloud.
Next steps: Learn how to protect client rendered routes.