From 918a6884026a631944d0ac4e438b64524439d57e Mon Sep 17 00:00:00 2001 From: Nandan Bhat Date: Wed, 14 May 2025 03:27:11 +0530 Subject: [PATCH 1/5] Addressing github issue 1983 --- V4_MIGRATION_GUIDE.md | 61 +++++++++++++++++++++++++++++++++---------- 1 file changed, 47 insertions(+), 14 deletions(-) diff --git a/V4_MIGRATION_GUIDE.md b/V4_MIGRATION_GUIDE.md index fdd4ed7ef..e4ec4aa9b 100644 --- a/V4_MIGRATION_GUIDE.md +++ b/V4_MIGRATION_GUIDE.md @@ -71,7 +71,7 @@ import type { NextRequest } from "next/server" import { auth0 } from "./lib/auth0" export async function middleware(request: NextRequest) { - return await auth0.middleware(request) + return await auth0.middleware(request) // Returns a NextResponse object } export const config = { @@ -94,23 +94,30 @@ See [the Getting Started section](https://github.com/auth0/nextjs-auth0/tree/mai By default, **the middleware does not protect any routes**. To protect a page, you can use the `getSession()` handler in the middleware, like so: ```ts -export async function middleware(request: NextRequest) { - const authRes = await auth0.middleware(request) +export async function middleware(request) { + const authRes = await auth0.middleware(request); //Returns a NextResponse object - // authentication routes — let the middleware handle it - if (request.nextUrl.pathname.startsWith("/auth")) { - return authRes - } + // Let Auth0 handle authentication-specific routes (e.g. /auth/login, /auth/callback, etc.) + if (request.nextUrl.pathname.startsWith("/auth")) { + return authRes; + } - const { origin } = new URL(request.url) - const session = await auth0.getSession() + // Allow access to public routes without requiring a session + if (request.nextUrl.pathname === ("/")) { + return authRes; + } - // user does not have a session — redirect to login - if (!session) { - return NextResponse.redirect(`${origin}/auth/login`) - } + const { origin } = new URL(request.url) + const session = await auth0.getSession() + + // If the user does not have a session, redirect to login + if (!session) { + return NextResponse.redirect(`${origin}/auth/login`) + } - return authRes + // If a valid session exists, continue with the response from Auth0 middleware + // You can also add custom logic here... + return authRes } ``` @@ -232,6 +239,32 @@ In v4, by default, the only claims that are persisted in the `user` object of se If you'd like to customize the `user` object to include additional custom claims from the ID token, you can use the `beforeSessionSaved` hook (see [beforeSessionSaved hook](https://github.com/auth0/nextjs-auth0/blob/main/EXAMPLES.md#beforesessionsaved)) +## Handling Dynamic Base URLs (e.g. Vercel Preview Deployments) +When deploying to platforms like Vercel with dynamic preview URLs, it’s important to set the correct appBaseUrl and redirect_uri at runtime — especially in preview environments where URLs change per deployment. +1. Set `APP_BASE_URL` dynamically in `next.config.js`: +```ts +// next.config.js +module.exports = { + env: { + APP_BASE_URL: + process.env.VERCEL_ENV === "preview" + ? `https://${process.env.VERCEL_BRANCH_URL}` + : process.env.APP_BASE_URL, + }, +}; +``` +2. Use the `APP_BASE_URL` in your Auth0 configuration: +```ts +export const auth0 = new Auth0Client({ + appBaseUrl: process.env.APP_BASE_URL, + authorizationParameters: { + redirect_uri: `${process.env.APP_BASE_URL}/auth/callback`, + audience: "YOUR_API_AUDIENCE_HERE", // optional + }, +}); +``` +3. Ensure your Auth0 application settings include the dynamic URL in the **Allowed Callback URLs** and **Allowed Logout URLs** fields. For example, `https://*.vercel.app/auth/callback`. + ## Additional changes - By default, v4 is edge-compatible and as such there is no longer a `@auth0/nextjs-auth0/edge` export. From 1f4952a0f8431b0fd8061902d5950c2d4ae7672b Mon Sep 17 00:00:00 2001 From: Nandan Bhat Date: Wed, 14 May 2025 03:36:40 +0530 Subject: [PATCH 2/5] Fixed the indentation --- V4_MIGRATION_GUIDE.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/V4_MIGRATION_GUIDE.md b/V4_MIGRATION_GUIDE.md index e4ec4aa9b..01ebea5a5 100644 --- a/V4_MIGRATION_GUIDE.md +++ b/V4_MIGRATION_GUIDE.md @@ -99,12 +99,12 @@ export async function middleware(request) { // Let Auth0 handle authentication-specific routes (e.g. /auth/login, /auth/callback, etc.) if (request.nextUrl.pathname.startsWith("/auth")) { - return authRes; + return authRes; } // Allow access to public routes without requiring a session if (request.nextUrl.pathname === ("/")) { - return authRes; + return authRes; } const { origin } = new URL(request.url) @@ -112,7 +112,7 @@ export async function middleware(request) { // If the user does not have a session, redirect to login if (!session) { - return NextResponse.redirect(`${origin}/auth/login`) + return NextResponse.redirect(`${origin}/auth/login`) } // If a valid session exists, continue with the response from Auth0 middleware From ddf89d49e0c29c1c66ef82b5058c784e1eaafeb0 Mon Sep 17 00:00:00 2001 From: Tushar Pandey Date: Thu, 15 May 2025 14:01:16 +0530 Subject: [PATCH 3/5] update v4_migration guide --- V4_MIGRATION_GUIDE.md | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/V4_MIGRATION_GUIDE.md b/V4_MIGRATION_GUIDE.md index 01ebea5a5..14a76997b 100644 --- a/V4_MIGRATION_GUIDE.md +++ b/V4_MIGRATION_GUIDE.md @@ -57,7 +57,7 @@ Additionally, in v4, the mounted routes drop the `/api` prefix. For example, the The complete list of routes mounted by the SDK can be found [here](https://github.com/auth0/nextjs-auth0/tree/main?tab=readme-ov-file#routes). -## Auth0 middleware +## The Auth0 middleware In v4, the Auth0 middleware is a central component of the SDK. It serves a number of core functions such as registering the required authentication endpoints, providing rolling sessions functionality, keeping access tokens fresh, etc. @@ -86,6 +86,8 @@ export const config = { ], } ``` +> [!NOTE] +> The above middleware is a basic setup. Its primary function is to pass incoming requests to the Auth0 SDK's request handler, which in turn manages the [default auto-mounted authentication routes](../README.md#routes), user sessions, and the overall authentication flow. See [the Getting Started section](https://github.com/auth0/nextjs-auth0/tree/main?tab=readme-ov-file#getting-started) for details on how to configure the middleware. @@ -97,7 +99,7 @@ By default, **the middleware does not protect any routes**. To protect a page, y export async function middleware(request) { const authRes = await auth0.middleware(request); //Returns a NextResponse object - // Let Auth0 handle authentication-specific routes (e.g. /auth/login, /auth/callback, etc.) + // Ensure our own middleware does not handle the `/auth` routes, auto-mounted and handled by the SDK if (request.nextUrl.pathname.startsWith("/auth")) { return authRes; } @@ -124,7 +126,11 @@ export async function middleware(request) { > [!NOTE] > We recommend keeping the security checks as close as possible to the data source you're accessing. This is also in-line with [the recommendations from the Next.js team](https://nextjs.org/docs/app/building-your-application/authentication#optimistic-checks-with-middleware-optional). -## `` +### Combining with other middleware + +For scenarios where you need to combine the Auth0 middleware with other Next.js middleware, please refer to the [Combining middleware](../EXAMPLES.md#combining-middleware) guide for examples and best practices. + +## Changes to `` The `` has been renamed to ``. @@ -138,19 +144,23 @@ In v4, rolling sessions are enabled by default and are handled automatically by See the [session configuration section](https://github.com/auth0/nextjs-auth0/tree/main?tab=readme-ov-file#session-configuration) for additional details on how to configure it. -## `withPageAuthRequired` and `withApiAuthRequired` +## Migrating from `withPageAuthRequired` and `withApiAuthRequired` `withPageAuthRequired` and `withApiAuthRequired` have been removed from v4 of the SDK. Instead, we recommend adding a `getSession()` check or relying on `useUser()` hook where you would have previously used the helpers. On the server-side, the `getSession()` method can be used to check if the user is authenticated: ```tsx -function Page() { - const session = await getSession() +// Example for an App Router Server Component +import { redirect } from 'next/navigation' +import { auth0 } from '@/lib/auth0' // Adjust path if your auth0 client is elsewhere + +export default async function Page() { + const session = await auth0.getSession() if (!session) { - // the user will be redirected to authenticate and then taken to the - // /dashboard route after successfully being authenticated + // The user will be redirected to authenticate and then taken to the + // /dashboard route after successfully being authenticated. return redirect('/auth/login?returnTo=/dashboard') } @@ -240,7 +250,7 @@ In v4, by default, the only claims that are persisted in the `user` object of se If you'd like to customize the `user` object to include additional custom claims from the ID token, you can use the `beforeSessionSaved` hook (see [beforeSessionSaved hook](https://github.com/auth0/nextjs-auth0/blob/main/EXAMPLES.md#beforesessionsaved)) ## Handling Dynamic Base URLs (e.g. Vercel Preview Deployments) -When deploying to platforms like Vercel with dynamic preview URLs, it’s important to set the correct appBaseUrl and redirect_uri at runtime — especially in preview environments where URLs change per deployment. +When deploying to platforms like Vercel with dynamic preview URLs, it's important to set the correct appBaseUrl and redirect_uri at runtime — especially in preview environments where URLs change per deployment. 1. Set `APP_BASE_URL` dynamically in `next.config.js`: ```ts // next.config.js @@ -271,4 +281,4 @@ export const auth0 = new Auth0Client({ - All cookies set by the SDK default to `SameSite=Lax` - `touchSession` method was removed. The middleware enables rolling sessions by default and can be configured via the [session configuration](https://github.com/auth0/nextjs-auth0/tree/main?tab=readme-ov-file#session-configuration). - `getAccessToken` can now be called in React Server Components. -- By default, v4 will use [OpenID Connect's RP-Initiated Logout](https://auth0.com/docs/authenticate/login/logout/log-users-out-of-auth0) if it's enabled on the tenant. Otherwise, it will fallback to the `/v2/logout` endpoint. +- By default, v4 will use [OpenID Connect's RP-Initiated Logout](https://auth0.com/docs/authenticate/login/logout/log-users-out-of-auth0) if it's enabled on the tenant. Otherwise, it will fallback to the `/v2/logout` endpoint. \ No newline at end of file From b6b1b66153c9eb08f554d4a196eb67c6d2e4d5cc Mon Sep 17 00:00:00 2001 From: Tushar Pandey Date: Thu, 15 May 2025 14:24:53 +0530 Subject: [PATCH 4/5] added refs to examples --- V4_MIGRATION_GUIDE.md | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/V4_MIGRATION_GUIDE.md b/V4_MIGRATION_GUIDE.md index 14a76997b..a25dea3dc 100644 --- a/V4_MIGRATION_GUIDE.md +++ b/V4_MIGRATION_GUIDE.md @@ -126,6 +126,8 @@ export async function middleware(request) { > [!NOTE] > We recommend keeping the security checks as close as possible to the data source you're accessing. This is also in-line with [the recommendations from the Next.js team](https://nextjs.org/docs/app/building-your-application/authentication#optimistic-checks-with-middleware-optional). +For more examples on accessing user sessions in middleware, see [Accessing the authenticated user in Middleware in the Examples guide](./EXAMPLES.md#middleware). + ### Combining with other middleware For scenarios where you need to combine the Auth0 middleware with other Next.js middleware, please refer to the [Combining middleware](../EXAMPLES.md#combining-middleware) guide for examples and best practices. @@ -172,7 +174,7 @@ The `getSession()` method can be used in the App Router in Server Components, Se In the Pages Router, the `getSession(req)` method takes a request object and can be used in `getServerSideProps`, API routes, and middleware. -Read more about [accessing the authenticated user here](https://github.com/guabu/nextjs-auth0/tree/main?tab=readme-ov-file#accessing-the-authenticated-user). +Read more about [accessing the authenticated user in various contexts (browser, server, middleware) in the Examples guide](./EXAMPLES.md#accessing-the-authenticated-user). In the browser, you can rely on the `useUser()` hook to check if the user is authenticated. For example: @@ -248,6 +250,7 @@ In v4, by default, the only claims that are persisted in the `user` object of se - `org_id` If you'd like to customize the `user` object to include additional custom claims from the ID token, you can use the `beforeSessionSaved` hook (see [beforeSessionSaved hook](https://github.com/auth0/nextjs-auth0/blob/main/EXAMPLES.md#beforesessionsaved)) +For a list of default claims included in the user object, refer to the [ID Token claims and the user object section in the Examples guide](./EXAMPLES.md#id-token-claims-and-the-user-object). ## Handling Dynamic Base URLs (e.g. Vercel Preview Deployments) When deploying to platforms like Vercel with dynamic preview URLs, it's important to set the correct appBaseUrl and redirect_uri at runtime — especially in preview environments where URLs change per deployment. @@ -278,7 +281,7 @@ export const auth0 = new Auth0Client({ ## Additional changes - By default, v4 is edge-compatible and as such there is no longer a `@auth0/nextjs-auth0/edge` export. -- All cookies set by the SDK default to `SameSite=Lax` -- `touchSession` method was removed. The middleware enables rolling sessions by default and can be configured via the [session configuration](https://github.com/auth0/nextjs-auth0/tree/main?tab=readme-ov-file#session-configuration). -- `getAccessToken` can now be called in React Server Components. +- All cookies set by the SDK default to `SameSite=Lax`. For details on how to customize cookie attributes, see the [Cookie Configuration section in the Examples guide](./EXAMPLES.md#cookie-configuration). +- `touchSession` method was removed. The middleware enables rolling sessions by default and can be configured via the [Session configuration section in the Examples guide](./EXAMPLES.md#session-configuration). +- `getAccessToken` can now be called in React Server Components. For examples on how to use `getAccessToken` in various environments (browser, App Router, Pages Router, Middleware), refer to the [Getting an access token section in the Examples guide](./EXAMPLES.md#getting-an-access-token). - By default, v4 will use [OpenID Connect's RP-Initiated Logout](https://auth0.com/docs/authenticate/login/logout/log-users-out-of-auth0) if it's enabled on the tenant. Otherwise, it will fallback to the `/v2/logout` endpoint. \ No newline at end of file From 95ba05844e6eb27b7f658a90207c7c1cd9f0972d Mon Sep 17 00:00:00 2001 From: Nandan Bhat Date: Thu, 15 May 2025 18:18:26 +0530 Subject: [PATCH 5/5] Changing the way how lib/auth0 is imported in EXAMPLES.md --- EXAMPLES.md | 14 +++++++------- README.md | 2 +- V4_MIGRATION_GUIDE.md | 4 ++-- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/EXAMPLES.md b/EXAMPLES.md index ee4fb05ca..40bff6f0e 100644 --- a/EXAMPLES.md +++ b/EXAMPLES.md @@ -455,7 +455,7 @@ In middleware, the `getAccessToken(req, res)` helper can be used to get an acces ```tsx import { NextRequest, NextResponse } from "next/server" -import { auth0 } from "@/lib/auth0" +import { auth0 } from "./lib/auth0" // Adjust path if your auth0 client is elsewhere export async function middleware(request: NextRequest) { const authRes = await auth0.middleware(request) @@ -486,7 +486,7 @@ If you are using the Pages Router and are calling the `getAccessToken` method in ```ts import { NextRequest, NextResponse } from "next/server" -import { auth0 } from "@/lib/auth0" +import { auth0 } from "./lib/auth0" // Adjust path if your auth0 client is elsewhere export async function middleware(request: NextRequest) { const authRes = await auth0.middleware(request) @@ -589,7 +589,7 @@ You can wrap your components in an `` and pass an initial user ```tsx import { Auth0Provider } from "@auth0/nextjs-auth0" -import { auth0 } from "@/lib/auth0" +import { auth0 } from "./lib/auth0" // Adjust path if your auth0 client is elsewhere export default async function RootLayout({ children, @@ -991,7 +991,7 @@ For example: ```ts import { NextResponse } from "next/server" -import { auth0 } from "@/lib/auth0" +import { auth0 } from "./lib/auth0" // Adjust path if your auth0 client is elsewhere export async function GET() { try { @@ -1016,7 +1016,7 @@ On the server, the `getAccessTokenForConnection({}, req, res)` helper can be use ```ts import type { NextApiRequest, NextApiResponse } from "next" -import { auth0 } from "@/lib/auth0" +import { auth0 } from "./lib/auth0" // Adjust path if your auth0 client is elsewhere export default async function handler( req: NextApiRequest, @@ -1039,7 +1039,7 @@ In middleware, the `getAccessTokenForConnection({}, req, res)` helper can be use ```tsx import { NextRequest, NextResponse } from "next/server" -import { auth0 } from "@/lib/auth0" +import { auth0 } from "./lib/auth0" // Adjust path if your auth0 client is elsewhere export async function middleware(request: NextRequest) { const authRes = await auth0.middleware(request) @@ -1070,7 +1070,7 @@ If you are using the Pages Router and are calling the `getAccessTokenForConnecti ```ts import { NextRequest, NextResponse } from "next/server" -import { auth0 } from "@/lib/auth0" +import { auth0 } from "./lib/auth0" // Adjust path if your auth0 client is elsewhere export async function middleware(request: NextRequest) { const authRes = await auth0.middleware(request) diff --git a/README.md b/README.md index e34a59efa..78e0eb093 100644 --- a/README.md +++ b/README.md @@ -97,7 +97,7 @@ export const config = { You can now begin to authenticate your users by redirecting them to your application's `/auth/login` route: ```tsx -import { auth0 } from "@/lib/auth0" +import { auth0 } from "./lib/auth0" // Adjust path if your auth0 client is elsewhere export default async function Home() { const session = await auth0.getSession() diff --git a/V4_MIGRATION_GUIDE.md b/V4_MIGRATION_GUIDE.md index a25dea3dc..f9a612d4e 100644 --- a/V4_MIGRATION_GUIDE.md +++ b/V4_MIGRATION_GUIDE.md @@ -97,7 +97,7 @@ By default, **the middleware does not protect any routes**. To protect a page, y ```ts export async function middleware(request) { - const authRes = await auth0.middleware(request); //Returns a NextResponse object + const authRes = await auth0.middleware(request); // Returns a NextResponse object // Ensure our own middleware does not handle the `/auth` routes, auto-mounted and handled by the SDK if (request.nextUrl.pathname.startsWith("/auth")) { @@ -155,7 +155,7 @@ On the server-side, the `getSession()` method can be used to check if the user i ```tsx // Example for an App Router Server Component import { redirect } from 'next/navigation' -import { auth0 } from '@/lib/auth0' // Adjust path if your auth0 client is elsewhere +import { auth0 } from './lib/auth0' // Adjust path if your auth0 client is elsewhere export default async function Page() { const session = await auth0.getSession()