# Auth

> Source: https://agilitycms.com/docs/developers/auth0

1. User Management
2. Access Management
3. Multi-Factor Authentication
4. Single Sign On

[Auth0](https://auth0.com/) is an easy to implement, adaptable authentication and authorization platform. Use Auth0 to allow users to sign up, login, and access protected Content or Pages on your Agility CMS powered website or application.

## Setting up Auth0

### Step 1: Sign up to Auth0

To get started with Auth0, sign up for a [Free Account](https://auth0.com/signup?place=header&type=button&text=sign%20up).

![](https://cdn.aglty.io/agility-cms-docs/block-editor/developerarticles/Screen-Shot-2021-12-09-at-4.27.24-PM-12092021212729.png)

### Step 2: Create an Application

Next, you'll want to create an application by heading to **Applications > Create Application**.

![](https://cdn.aglty.io/agility-cms-docs/block-editor/developerarticles/Screen-Shot-2021-12-09-at-4.39.11-PM-12092021214004.png)

Give you application a name and select the application type.

![](https://cdn.aglty.io/agility-cms-docs/block-editor/developerarticles/Screen-Shot-2021-12-09-at-4.30.28-PM-12092021213047.png)

> **Note** — There are many ways to use Auth0 in your Applications and Websites. For this example, we will be creating a site powered by Next.js (App Router) and Agility CMS, paired with Auth0's `@auth0/nextjs-auth0` NPM package (v4).

Once you've created your application head to Settings and take note of your **Domain**, **Client** **ID**, and **Client** **Secret** as we'll need to use this in our application later.

![](https://cdn.aglty.io/agility-cms-docs/block-editor/developerarticles/Screen-Shot-2021-12-09-at-4.40.47-PM-12092021214243.png)

Scroll down the page to **Application URIs**. Set **Allowed Callback URLs** to `http://localhost:3000/auth/callback` and **Allowed Logout URLs** to `http://localhost:3000`, and add the same paths on your production domain when you deploy.

![This screenshot shows /api/auth/callback, the path used by older versions of the SDK. With the current SDK, use /auth/callback.](https://cdn.aglty.io/agility-cms-docs/block-editor/developerarticles/Screen-Shot-2021-12-09-at-4.43.37-PM-12092021214516.png)

Feel free to look through and update the other Application Properties as needed. Once you're done, click **Save**.

![](https://cdn.aglty.io/agility-cms-docs/block-editor/developerarticles/Screen-Shot-2021-12-09-at-4.43.37-PM-12092021214601.png)

## Setting up an Agility CMS Website

We'll want to add authentication to an Agility CMS powered website. Sign up for a Free Agility CMS Account. Once you have an account, you'll be able to select a starter and create an Instance. 

For this example, we'll be using the [Next.js Blog Starter](https://agilitycms.com/starters/nextjs)** **Template.

[Getting Started with Agility CMS](https://www.youtube.com/watch?v=67s4bSpmDv0)

## Created a Protected Page in Agility

 We may want to set up Protected Pages in Agility that only grants users who have access to an account visibility to that Page.

### Step 1: Adding a Page

To add a Page in Agility, head to **Pages** and click the **New Page** Button.

![](https://cdn.aglty.io/agility-cms-docs/block-editor/developerarticles/Screen-Shot-2021-12-09-at-4.53.49-PM-12092021215429.png)

Select a **Page Model** and give your Page a **Title**.

![](https://cdn.aglty.io/agility-cms-docs/block-editor/developerarticles/Screen-Shot-2021-12-09-at-4.55.09-PM-12092021215514.png)

### Step 2: Create Secret Content

Add a Rich Text Area component with some top secret information.

![](https://cdn.aglty.io/agility-cms-docs/block-editor/developerarticles/Screen-Shot-2021-12-09-at-4.57.44-PM-12092021215829.png)

Make sure to **save** your changes.

### Step 3: Protect the Page

To make this Page Protected, heat to the **Settings** of the Page and enable the **Secure Page on Website** toggle.

![](https://cdn.aglty.io/agility-cms-docs/block-editor/developerarticles/Screen-Shot-2021-12-09-at-4.55.55-PM-12092021215659.png)

Make sure to **save** your changes.

Create protected pages under a folder in your sitemap (this example uses `/members`), so your site can keep them out of its static, cached pages. Step 5 below shows why.

## Adding Auth0 to Your Website

The last step is to add Authentication within our Agility CMS powered website.

### Step 1: Start from the Agility Next.js Starter

We will be using the Agility CMS Next.js Starter (App Router, Next.js 16) as the boilerplate for our Authentication implementation.

[The Next.js Starter (agilitycms.com)](https://agilitycms.com/starters/nextjs)


### Step 2: Install Packages

Once you have a copy of the starter running locally on your machine, add the `@auth0/nextjs-auth0` package as a dependency. The current SDK needs a recent Next.js 16 release, so update Next.js first if npm reports a peer dependency conflict.

```
npm install next@latest
npm install @auth0/nextjs-auth0
```

### Step 3: Set up Environment Variables

Remember those Auth0 credentials we asked you to save earlier? You'll want to include them as Environment Variables in your `.env.local` file.

```
AUTH0_DOMAIN=
AUTH0_CLIENT_ID=
AUTH0_CLIENT_SECRET=
AUTH0_SECRET=
APP_BASE_URL=http://localhost:3000
```

To retrieve your Auth0 Secret, you can run the following code snippet in the command line:

```
openssl rand -hex 32
```

This will return long secret value used to encrypt the session cookie.

`AUTH0_DOMAIN` is the **Domain** from your Auth0 application settings, and `APP_BASE_URL` is the URL of your site. Set all five on your hosting provider too, with `APP_BASE_URL` pointing at your production domain.

### Step 4: Create the Auth0 Client and Add It to the Proxy

Create `lib/auth0.ts` with a single Auth0 client for the whole app:

```
// lib/auth0.ts
import { Auth0Client } from "@auth0/nextjs-auth0/server"

export const auth0 = new Auth0Client()
```

The starter already has a `proxy.ts` (the Next.js 16 name for middleware) that handles Agility preview requests. Run the Auth0 middleware at the top of it, let the SDK answer its own routes, send signed-out visitors away from members-only pages, and return the Auth0 response at the end so the session cookie stays fresh:

```
import { NextResponse } from "next/server"
import type { NextRequest } from "next/server"
import { getDynamicPageURL } from "@agility/nextjs/node"
import { auth0 } from "./lib/auth0"

export async function proxy(request: NextRequest) {

	// Let the Auth0 SDK handle its own routes and keep the session cookie fresh
	const authResponse = await auth0.middleware(request)
	if (request.nextUrl.pathname.startsWith("/auth/")) {
		return authResponse
	}

	// Members-only pages: send signed-out visitors to the login page first
	if (request.nextUrl.pathname.startsWith("/members/")) {
		const session = await auth0.getSession(request)
		if (!session) {
			const loginUrl = new URL("/auth/login", request.nextUrl.origin)
			loginUrl.searchParams.set("returnTo", request.nextUrl.pathname)
			return NextResponse.redirect(loginUrl)
		}
	}

	// ...the starter's existing Agility preview and ContentID handling (unchanged)

	return authResponse
}
```

The SDK now mounts these routes for you. There are no route files to create:

```
# The route used to perform login with Auth0.
/auth/login

# The route used to log the user out.
/auth/logout

# The route Auth0 will redirect the user to after a successful login.
/auth/callback

# The route to fetch the user profile from.
/auth/profile

# The route to fetch an access token from.
/auth/access-token
```

### Step 5: Keep Protected Pages Out of the Static Cache

The starter prerenders every page in your sitemap (`dynamic = "force-static"` with `revalidate = 60`). That's what makes it fast, but a protected page rendered that way would end up in publicly cached HTML, and a static render can't read the visitor's session cookie. Put protected pages under a folder in your Agility sitemap (this example uses `/members`) and leave them out of the starter's catch-all route. As a safety net, any page flagged **Secure Page on Website** that isn't under `/members` returns a 404 instead of rendering publicly:

```
// app/[...slug]/page.tsx (two additions to the starter)
export async function generateStaticParams() {
	// ...the starter's existing sitemap fetch
	const paths = Object.values(sitemap)
		.filter((node, index) => {
			if (node.redirect !== null || node.isFolder === true || index === 0) return false
			// members-only pages are rendered per request by app/members/[...slug]
			if (node.path.startsWith("/members/")) return false
			return true
		})
		.map((node) => ({ slug: node.path.split("/").slice(1) }))

	return paths
}

export default async function Page({ params }: PageProps) {
	const agilityData = await getAgilityPage({ params })
	if (!agilityData.page) notFound()

	// a page marked "Secure Page on Website" outside /members must never render publicly
	if (agilityData.page.securePage) notFound()

	// ...render as before
}
```

### Step 6: Render Protected Pages per Request

Create `app/members/[...slug]/page.tsx`. It renders on every request, checks the session, and only then fetches and renders the Agility page:

```
// app/members/[...slug]/page.tsx
import { notFound, redirect } from "next/navigation"
import { auth0 } from "lib/auth0"
import { getAgilityPage } from "lib/cms/getAgilityPage"
import { getPageTemplate } from "components/agility-pages"

// Render on every request: never prerender or cache protected content
export const dynamic = "force-dynamic"

export default async function MembersPage({ params }: { params: Promise<{ slug: string[] }> }) {
	const { slug } = await params
	const path = `/members/${slug.join("/")}`

	const session = await auth0.getSession()
	if (!session) redirect(`/auth/login?returnTo=${encodeURIComponent(path)}`)

	const agilityData = await getAgilityPage({
		params: Promise.resolve({ slug: ["members", ...slug] }),
	})
	if (!agilityData.page) notFound()

	const AgilityPageTemplate = getPageTemplate(agilityData.pageTemplateName || "")
	if (!AgilityPageTemplate) notFound()

	return <AgilityPageTemplate {...agilityData} />
}
```

The proxy redirects signed-out visitors before the request reaches the page, and the page checks the session again itself, so protected content is never served from a cache or to an anonymous visitor. To show login state in a Client Component (for example, a header link), use the SDK's `useUser()` hook from `@auth0/nextjs-auth0`, and link to `/auth/login` and `/auth/logout`.

## Test it out

If you try to access the Protected Page, it will now redirect you to login.

![](https://cdn.aglty.io/agility-cms-docs/block-editor/developerarticles/PHXqkPkcIu-12092021224647.gif)

Once you authenticate, you'll be able to see the Protected Pages Content!!

![](https://cdn.aglty.io/agility-cms-docs/block-editor/developerarticles/Screen-Shot-2021-12-09-at-5.46.12-PM-12092021224708.png)

---

## Related pages

- [Zapier Translate](https://agilitycms.com/docs/developers/zapier-translate.md)
- [Vercel](https://agilitycms.com/docs/developers/vercel.md)
- [Ahrefs](https://agilitycms.com/docs/developers/ahrefs.md)
- [Netlify](https://agilitycms.com/docs/developers/netlify.md)
- [Salesforce Sales Cloud](https://agilitycms.com/docs/developers/salesforce-sales-cloud.md)

Index of every docs page: https://agilitycms.com/docs/llms.txt
