diff --git a/EXAMPLES.md b/EXAMPLES.md
index ee4fb05c..40bff6f0 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 e34a59ef..78e0eb09 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 fdd4ed7e..f9a612d4 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.
@@ -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 = {
@@ -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.
@@ -94,30 +96,43 @@ 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
- }
+ // 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;
+ }
- 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
}
```
> [!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.
+
+## Changes to ``
The `` has been renamed to ``.
@@ -131,19 +146,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')
}
@@ -155,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:
@@ -231,11 +250,38 @@ 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.
+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.
-- 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.
+- 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