|
| 1 | +# V4 Migration Guide |
| 2 | + |
| 3 | +Guide to migrating from `3.x` to `4.x`. |
| 4 | + |
| 5 | +## Environment variables |
| 6 | + |
| 7 | +The following environment variables are required in v4: |
| 8 | + |
| 9 | +``` |
| 10 | +AUTH0_DOMAIN |
| 11 | +AUTH0_CLIENT_ID |
| 12 | +AUTH0_CLIENT_SECRET |
| 13 | +AUTH0_SECRET |
| 14 | +APP_BASE_URL |
| 15 | +``` |
| 16 | + |
| 17 | +Of the required variables, the following have changed from v3: |
| 18 | + |
| 19 | +- `AUTH0_BASE_URL` has been renamed to `APP_BASE_URL` (e.g.: `http://localhost:3000`) |
| 20 | +- `AUTH0_ISSUER_BASE_URL` has been renamed to `AUTH0_DOMAIN` and does **not** accept a scheme (e.g.: `example.us.auth0.com`) |
| 21 | + |
| 22 | +All other configuration must be specified via the `Auth0Client` constructor. |
| 23 | + |
| 24 | +## Routes |
| 25 | + |
| 26 | +Previously, it was required to set up a dynamic Route Handler to mount the authentication endpoints to handle requests. |
| 27 | + |
| 28 | +For example, in v3 when using the App Router, you were required to create a Route Handler, under `/app/api/auth/[auth0]/route.ts`, with the following contents: |
| 29 | + |
| 30 | +```ts |
| 31 | +import { handleAuth } from "@auth0/nextjs-auth0" |
| 32 | + |
| 33 | +export const GET = handleAuth() |
| 34 | +``` |
| 35 | + |
| 36 | +In v4, the routes are now mounted automatically by the middleware: |
| 37 | + |
| 38 | +```ts |
| 39 | +import type { NextRequest } from "next/server" |
| 40 | + |
| 41 | +import { auth0 } from "./lib/auth0" |
| 42 | + |
| 43 | +export async function middleware(request: NextRequest) { |
| 44 | + return await auth0.middleware(request) |
| 45 | +} |
| 46 | +``` |
| 47 | + |
| 48 | +For a complete example, see [the Getting Started section](https://github.com/auth0/nextjs-auth0/tree/v4?tab=readme-ov-file#getting-started). |
| 49 | + |
| 50 | +Additionally, in v4, the mounted routes drop the `/api` prefix. For example, the default login route is now `/auth/login` instead of `/api/auth/login`. To link to the login route, it would now be: `<a href="/auth/login">Log in</a>`. |
| 51 | + |
| 52 | +> [!NOTE] |
| 53 | +> If you are using an existing client, you will need to update your **Allowed Callback URLs** accordingly. |
| 54 | +
|
| 55 | +The complete list of routes mounted by the SDK can be found [here](https://github.com/auth0/nextjs-auth0/tree/v4?tab=readme-ov-file#routes). |
| 56 | + |
| 57 | +## Auth0 middleware |
| 58 | + |
| 59 | +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. |
| 60 | + |
| 61 | +When configuring your application to use v4 of the SDK, it is now **required** to mount the middleware: |
| 62 | + |
| 63 | +```ts |
| 64 | +// middleware.ts |
| 65 | + |
| 66 | +import type { NextRequest } from "next/server" |
| 67 | + |
| 68 | +import { auth0 } from "./lib/auth0" |
| 69 | + |
| 70 | +export async function middleware(request: NextRequest) { |
| 71 | + return await auth0.middleware(request) |
| 72 | +} |
| 73 | + |
| 74 | +export const config = { |
| 75 | + matcher: [ |
| 76 | + /* |
| 77 | + * Match all request paths except for the ones starting with: |
| 78 | + * - _next/static (static files) |
| 79 | + * - _next/image (image optimization files) |
| 80 | + * - favicon.ico, sitemap.xml, robots.txt (metadata files) |
| 81 | + */ |
| 82 | + "/((?!_next/static|_next/image|favicon.ico|sitemap.xml|robots.txt).*)", |
| 83 | + ], |
| 84 | +} |
| 85 | +``` |
| 86 | + |
| 87 | +See [the Getting Started section](https://github.com/auth0/nextjs-auth0/tree/v4?tab=readme-ov-file#getting-started) for details on how to configure the middleware. |
| 88 | + |
| 89 | +### Protecting routes |
| 90 | + |
| 91 | +By default, **the middleware does not protect any routes**. To protect a page, you can use the `getSession()` handler in the middleware, like so: |
| 92 | + |
| 93 | +```ts |
| 94 | +export async function middleware(request: NextRequest) { |
| 95 | + const authRes = await auth0.middleware(request) |
| 96 | + |
| 97 | + // authentication routes — let the middleware handle it |
| 98 | + if (request.nextUrl.pathname.startsWith("/auth")) { |
| 99 | + return authRes |
| 100 | + } |
| 101 | + |
| 102 | + const { origin } = new URL(request.url) |
| 103 | + const session = await auth0.getSession() |
| 104 | + |
| 105 | + // user does not have a session — redirect to login |
| 106 | + if (!session) { |
| 107 | + return NextResponse.redirect(`${origin}/auth/login`) |
| 108 | + } |
| 109 | + |
| 110 | + return authRes |
| 111 | +} |
| 112 | +``` |
| 113 | + |
| 114 | +> [!NOTE] |
| 115 | +> 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). |
| 116 | +
|
| 117 | +## `<UserProvider />` |
| 118 | + |
| 119 | +The `<UserProvider />` has been renamed to `<Auth0Provider />`. |
| 120 | + |
| 121 | +Previously, when setting up your application to use v3 of the SDK, it was required to wrap your layout in the `<UserProvider />`. **This is no longer required by default.** |
| 122 | + |
| 123 | +If you would like to pass an initial user during server rendering to be available to the `useUser()` hook, you can wrap your components with the new `<Auth0Provider />` ([see example](https://github.com/auth0/nextjs-auth0/tree/v4?tab=readme-ov-file#auth0provider-)). |
| 124 | + |
| 125 | +## Rolling sessions |
| 126 | + |
| 127 | +In v4, rolling sessions are enabled by default and are handled automatically by the middleware with no additional configuration required. |
| 128 | + |
| 129 | +See the [session configuration section](https://github.com/auth0/nextjs-auth0/tree/v4?tab=readme-ov-file#session-configuration) for additional details on how to configure it. |
| 130 | + |
| 131 | +## `withPageAuthRequired` and `withApiAuthRequired` |
| 132 | + |
| 133 | +`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. |
| 134 | + |
| 135 | +On the server-side, the `getSession()` method can be used to check if the user is authenticated: |
| 136 | + |
| 137 | +```tsx |
| 138 | +function Page() { |
| 139 | + const session = await getSession() |
| 140 | + |
| 141 | + if (!session) { |
| 142 | + // the user will be redirected to authenticate and then taken to the |
| 143 | + // /dashboard route after successfully being authenticated |
| 144 | + return redirect('/auth/login?returnTo=/dashboard') |
| 145 | + } |
| 146 | + |
| 147 | + return <h1>Hello, {session.user.name}</h1> |
| 148 | +} |
| 149 | +``` |
| 150 | + |
| 151 | +The `getSession()` method can be used in the App Router in Server Components, Server Routes (APIs), Server Actions, and middleware. |
| 152 | + |
| 153 | +In the Pages Router, the `getSession(req)` method takes a request object and can be used in `getServerSideProps`, API routes, and middleware. |
| 154 | + |
| 155 | +Read more about [accessing the authenticated user here](https://github.com/guabu/nextjs-auth0/tree/v4?tab=readme-ov-file#accessing-the-authenticated-user). |
| 156 | + |
| 157 | +In the browser, you can rely on the `useUser()` hook to check if the user is authenticated. For example: |
| 158 | + |
| 159 | +```tsx |
| 160 | +"use client" |
| 161 | + |
| 162 | +import { useUser } from "@auth0/nextjs-auth0" |
| 163 | + |
| 164 | +export default function Profile() { |
| 165 | + const { user, isLoading, error } = useUser() |
| 166 | + |
| 167 | + if (isLoading) return <div>Loading...</div> |
| 168 | + if (!user) return <div>Not authenticated!</div> |
| 169 | + |
| 170 | + return ( |
| 171 | + <main> |
| 172 | + <h1>Profile</h1> |
| 173 | + <div> |
| 174 | + <pre>{JSON.stringify(user, null, 2)}</pre> |
| 175 | + </div> |
| 176 | + </main> |
| 177 | + ) |
| 178 | +} |
| 179 | +``` |
| 180 | + |
| 181 | +## Passing custom authorization parameters |
| 182 | + |
| 183 | +In v3, custom authorization parameters required specifying a custom handler, like so: |
| 184 | + |
| 185 | +```ts |
| 186 | +import { handleAuth, handleLogin } from "@auth0/nextjs-auth0" |
| 187 | + |
| 188 | +export default handleAuth({ |
| 189 | + login: handleLogin({ |
| 190 | + authorizationParams: { audience: "urn:my-api" }, |
| 191 | + }), |
| 192 | +}) |
| 193 | +``` |
| 194 | + |
| 195 | +In v4, you can simply append the authorization parameters to the query parameter of the login endpoint and they will be automatically fowarded to the `/authorize` endpoint, like so: |
| 196 | + |
| 197 | +```html |
| 198 | +<a href="/auth/login?audience=urn:my-api">Login</a> |
| 199 | +``` |
| 200 | + |
| 201 | +Or alternatively, it can be statically configured when initializing the SDK, like so: |
| 202 | + |
| 203 | +```ts |
| 204 | +export const auth0 = new Auth0Client({ |
| 205 | + authorizationParameters: { |
| 206 | + scope: "openid profile email", |
| 207 | + audience: "urn:custom:api", |
| 208 | + }, |
| 209 | +}) |
| 210 | +``` |
| 211 | + |
| 212 | +Read more about [passing authorization parameters](https://github.com/auth0/nextjs-auth0/tree/v4?tab=readme-ov-file#passing-authorization-parameters). |
| 213 | + |
| 214 | +## ID token claims |
| 215 | + |
| 216 | +In v3, any claims added to the ID token were automatically propagated to the `user` object in the session. This resulted in the large cookies that exceeded browser limits. |
| 217 | + |
| 218 | +In v4, by default, the only claims that are persisted in the `user` object of session are: |
| 219 | + |
| 220 | +- `sub` |
| 221 | +- `name` |
| 222 | +- `nickname` |
| 223 | +- `given_name` |
| 224 | +- `family_name` |
| 225 | +- `picture` |
| 226 | +- `email` |
| 227 | +- `email_verified` |
| 228 | +- `org_id` |
| 229 | + |
| 230 | +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/guabu/nextjs-auth0/tree/v4?tab=readme-ov-file#beforesessionsaved)) |
| 231 | + |
| 232 | +## Additional changes |
| 233 | + |
| 234 | +- By default, v4 is edge-compatible and as such there is no longer a `@auth0/nextjs-auth0/edge` export. |
| 235 | +- Cookie chunking has been removed |
| 236 | + - If the cookie size exceeds the browser limit of 4096 bytes, a warning will be logged |
| 237 | + - To store large session data, please use a [custom data store](https://github.com/auth0/nextjs-auth0/tree/v4?tab=readme-ov-file#database-sessions) with a SessionStore implementation |
| 238 | +- All cookies set by the SDK default to `SameSite=Lax` |
| 239 | +- `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/v4?tab=readme-ov-file#session-configuration). |
| 240 | +- `updateSession` method was removed. |
| 241 | +- `getAccessToken` can now be called in React Server Components. |
0 commit comments