-
Notifications
You must be signed in to change notification settings - Fork 417
Usability upgrades to V4 Migration Guide #2095
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
918a688
1f4952a
c5d5263
98234d4
ddf89d4
407bf5b
b6b1b66
95ba058
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||
---|---|---|---|---|---|---|---|---|
|
@@ -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 | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I felt like our read like the Auth0 middleware, but we are actually referring to the user's middleware. |
||||||||
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) | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||
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). | ||||||||
|
||||||||
## `<UserProvider />` | ||||||||
For more examples on accessing user sessions in middleware, see [Accessing the authenticated user in Middleware in the Examples guide](./EXAMPLES.md#middleware). | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If I look at the link, it looks like this is the exact same code as just above this line. Is this expected? Feels like we aren't realy precented with more examples. |
||||||||
|
||||||||
### 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 `<UserProvider />` | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||
|
||||||||
The `<UserProvider />` has been renamed to `<Auth0Provider />`. | ||||||||
|
||||||||
|
@@ -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. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
While reading primary function, I wondered what the secondary function is of the above middleware. Maybe it makes sense to rephrase? But feel free to dismiss if u disagree.