diff --git a/docs/pages/concepts/index.mdx b/docs/pages/concepts/index.mdx index d44f9d3e05..9eef01ac88 100644 --- a/docs/pages/concepts/index.mdx +++ b/docs/pages/concepts/index.mdx @@ -57,9 +57,9 @@ Yes! Check out the [TypeScript docs](/getting-started/typescript) - + -[Next.js middleware](https://nextjs.org/docs/middleware) is supported and is recommended as of version 5. An example middleware setup can be found [here](/getting-started/session-management/protecting#nextjs-middleware). +Yes! As of Next.js 16, `middleware.ts` has been renamed to `proxy.ts`. Auth.js supports both the new `proxy.ts` convention and the legacy `middleware.ts`. An example setup can be found [here](/getting-started/session-management/protecting#nextjs-proxy). diff --git a/docs/pages/getting-started/adapters/prisma.mdx b/docs/pages/getting-started/adapters/prisma.mdx index 9fc8b7b9c6..26b85a113d 100644 --- a/docs/pages/getting-started/adapters/prisma.mdx +++ b/docs/pages/getting-started/adapters/prisma.mdx @@ -65,9 +65,11 @@ if (process.env.NODE_ENV !== "production") globalForPrisma.prisma = prisma - We recommend using version `@prisma/client@5.12.0` or above if using - middleware or any other edge runtime(s). See [edge - compatibility](#edge-compatibility) below for more information. + We recommend using version `@prisma/client@5.12.0` or above if using proxy (or + middleware in older Next.js versions) or any other edge runtime(s). In Next.js + 16+, `proxy.ts` runs on the Node.js runtime, so this may no longer be + necessary. See [edge compatibility](#edge-compatibility) below for more + information. @@ -152,9 +154,9 @@ At the moment, Prisma is still working on being fully compatible with edge runti - Use the Prisma's [Accelerate](https://pris.ly/d/accelerate) feature - Follow our [Edge Compatibility](/guides/edge-compatibility) page as the workaround. This uses the `jwt` session strategy and separates the `auth.ts` configuration into two files. -Using Prisma with the `jwt` session strategy and `@prisma/client@5.9.1` or above doesn't require any additional modifications, other than ensuring you don't do any database queries in your middleware. +Using Prisma with the `jwt` session strategy and `@prisma/client@5.9.1` or above doesn't require any additional modifications, other than ensuring you don't do any database queries in your proxy (or middleware in older Next.js versions). -Since `@prisma/client@5.9.1`, Prisma no longer throws about being incompatible with the edge runtime at instantiation, but at query time. Therefore, it is possible to import it in files being used in your middleware as long as you do not execute any queries in your middleware. +Since `@prisma/client@5.9.1`, Prisma no longer throws about being incompatible with the edge runtime at instantiation, but at query time. Therefore, it is possible to import it in files being used in your proxy as long as you do not execute any queries in your proxy. ### Schema diff --git a/docs/pages/getting-started/installation.mdx b/docs/pages/getting-started/installation.mdx index e0b5741ff3..0cf9462470 100644 --- a/docs/pages/getting-started/installation.mdx +++ b/docs/pages/getting-started/installation.mdx @@ -86,10 +86,15 @@ import { handlers } from "@/auth" // Referring to the auth.ts we just created export const { GET, POST } = handlers ``` -3. Add optional Middleware to keep the session alive, this will update the session expiry every time its called. +3. Add optional Proxy to keep the session alive, this will update the session expiry every time its called. -```ts filename="./middleware.ts" -export { auth as middleware } from "@/auth" + + As of Next.js 16, `middleware.ts` has been renamed to `proxy.ts`. If you are + using an older version of Next.js, use `middleware.ts` with `export { auth as middleware }` instead. + + +```ts filename="./proxy.ts" +export { auth as proxy } from "@/auth" ``` diff --git a/docs/pages/getting-started/migrating-to-v5.mdx b/docs/pages/getting-started/migrating-to-v5.mdx index 29705ffdd7..3b35144a51 100644 --- a/docs/pages/getting-started/migrating-to-v5.mdx +++ b/docs/pages/getting-started/migrating-to-v5.mdx @@ -42,7 +42,7 @@ npm install next-auth@beta - OAuth 1.0 support is deprecated. - The minimum required Next.js version is now [14.0](https://nextjs.org/14). - The import `next-auth/next` is replaced. See [Authenticating server-side](#authenticating-server-side) for more details. -- The import `next-auth/middleware` is replaced. See [Authenticating server-side](#authenticating-server-side) for more details. +- The import `next-auth/middleware` is replaced. See [Authenticating server-side](#authenticating-server-side) for more details. As of Next.js 16, `middleware.ts` has been renamed to `proxy.ts`. - When the `idToken: boolean` option is set to `false`, it won't entirely disable the ID token. Instead, it signals `next-auth` to also visit the `userinfo_endpoint` for the final user data. Previously, `idToken: false` opted out to check the `id_token` validity at all. ## Migration @@ -92,7 +92,7 @@ See the table below for a summary of the changes. Below that are `diff` examples | Where | v4 | v5 | | ----------------------- | ----------------------------------------------------- | -------------------------------- | | **Server Component** | `getServerSession(authOptions)` | `auth()` call | -| **Middleware** | `withAuth(middleware, subset of authOptions)` wrapper | `auth` export / `auth()` wrapper | +| **Proxy (Middleware)** | `withAuth(middleware, subset of authOptions)` wrapper | `auth` export / `auth()` wrapper | | **Client Component** | `useSession()` hook | `useSession()` hook | | **Route Handler** | _Previously not supported_ | `auth()` wrapper | | **API Route (Edge)** | _Previously not supported_ | `auth()` wrapper | @@ -145,27 +145,27 @@ const ClientComponent = () => { -```diff filename="middleware.ts" +```diff filename="proxy.ts (middleware.ts in Next.js < 16)" - export { default } from "next-auth/middleware" -+ export { auth as middleware } from "@/auth" ++ export { auth as proxy } from "@/auth" ``` -For advanced use cases, you can use `auth` as a wrapper for your Middleware: +For advanced use cases, you can use `auth` as a wrapper for your Proxy: -```ts filename="middleware.ts" +```ts filename="proxy.ts" import { auth } from "@/auth" -export default auth((req) => { +export const proxy = auth((req) => { // req.auth }) -// Optionally, don't invoke Middleware on some paths +// Optionally, don't invoke Proxy on some paths export const config = { matcher: ["/((?!api|_next/static|_next/image|favicon.ico).*)"], } ``` -Check out additional [Middleware docs](/getting-started/session-management/protecting#nextjs-middleware) for more details. +Check out additional [Proxy docs](/getting-started/session-management/protecting#nextjs-proxy) for more details. @@ -258,7 +258,7 @@ While Auth.js strictly uses standard [Web APIs](https://developer.mozilla.org/en Auth.js supports two [session strategies](/concepts/session-strategies). When you are using an adapter, it will default to the `database` strategy. **Unless your database and its adapter is compatible with the Edge runtime/infrastructure, you will not be able to use the `"database"` session strategy**. -So for example, if you are using an adapter that relies on an ORM/library that is not yet compatible with Edge runtime(s) below is an example where we force the `jwt` strategy and split up the configuration so the library doesn't attempt to access the database in edge environments, like in the middleware. +So for example, if you are using an adapter that relies on an ORM/library that is not yet compatible with Edge runtime(s) below is an example where we force the `jwt` strategy and split up the configuration so the library doesn't attempt to access the database in edge environments, like in the proxy (or middleware for older Next.js versions). The following filenames are only a convention, they can be named anything you @@ -291,24 +291,24 @@ export const { auth, handlers, signIn, signOut } = NextAuth({ }) ``` -3. In your middleware file, import the configuration object from your first `auth.config.ts` file and use it to lazily initialize Auth.js there. In effect, initialize Auth.js separately with all of your common options, but **without the edge incompatible adapter**. +3. In your proxy file (or middleware file for older Next.js versions), import the configuration object from your first `auth.config.ts` file and use it to lazily initialize Auth.js there. In effect, initialize Auth.js separately with all of your common options, but **without the edge incompatible adapter**. -```ts filename="middleware.ts" {1} /NextAuth/ +```ts filename="proxy.ts" {1} /NextAuth/ import authConfig from "./auth.config" import NextAuth from "next-auth" -// Use only one of the two middleware options below -// 1. Use middleware directly -// export const { auth: middleware } = NextAuth(authConfig) +// Use only one of the two proxy options below +// 1. Use proxy directly +// export const { auth: proxy } = NextAuth(authConfig) -// 2. Wrapped middleware option +// 2. Wrapped proxy option const { auth } = NextAuth(authConfig) -export default auth(async function middleware(req: NextRequest) { - // Your custom middleware logic goes here +export const proxy = auth(async function proxy(req: NextRequest) { + // Your custom proxy logic goes here }) ``` -The above is just an example. **The main idea**, is to separate the part of the configuration that is edge-compatible from the rest, and only import the edge-compatible part in Middleware/Edge pages/routes. You can read more about this workaround in the [Prisma docs](/getting-started/adapters/prisma), for example. +The above is just an example. **The main idea**, is to separate the part of the configuration that is edge-compatible from the rest, and only import the edge-compatible part in Proxy/Edge pages/routes. You can read more about this workaround in the [Prisma docs](/getting-started/adapters/prisma), for example. Please follow up with your library/database/ORM's maintainer to see if they are planning to support the Edge runtime/infrastructure. diff --git a/docs/pages/getting-started/providers/passkey.mdx b/docs/pages/getting-started/providers/passkey.mdx index f02f734641..32b669507b 100644 --- a/docs/pages/getting-started/providers/passkey.mdx +++ b/docs/pages/getting-started/providers/passkey.mdx @@ -160,7 +160,7 @@ CREATE UNIQUE INDEX Authenticator_credentialID_key ON Authenticator(credentialID #### Edge Compatibility -If you're using `next-auth` with Next.js and middleware, you should ensure that your database client of choice is "edge compatible". If you're using an older version of Prisma or another adapter that is not edge compatible, you'll need to make some adjustments. Check out our [edge compatibility](/guides/edge-compatibility) guide for more details. There is also Prisma specific information in the [Prisma adapter docs](/getting-started/adapters/prisma#edge-compatibility). +If you're using `next-auth` with Next.js and a proxy (or middleware in older versions), you should ensure that your database client of choice is "edge compatible" when using Next.js versions before 16. In Next.js 16+, `proxy.ts` runs on the Node.js runtime, so edge compatibility is no longer a concern. For older versions, check out our [edge compatibility](/guides/edge-compatibility) guide for more details. There is also Prisma specific information in the [Prisma adapter docs](/getting-started/adapters/prisma#edge-compatibility). ### Update Auth.js Configuration diff --git a/docs/pages/getting-started/session-management/protecting.mdx b/docs/pages/getting-started/session-management/protecting.mdx index 67de091276..5217e5f6b3 100644 --- a/docs/pages/getting-started/session-management/protecting.mdx +++ b/docs/pages/getting-started/session-management/protecting.mdx @@ -240,12 +240,19 @@ API Routes are protected in the same way as any other route in Express, see [the -### Next.js Middleware +### Next.js Proxy -With Next.js 12+, the easiest way to protect a set of pages is using the middleware file. You can create a `middleware.ts` file in your root pages directory with the following contents. +With Next.js 16+, the easiest way to protect a set of pages is using the proxy file. You can create a `proxy.ts` file in your root pages directory with the following contents. -```ts filename="middleware.ts" -export { auth as middleware } from "@/auth" + + As of Next.js 16, `middleware.ts` has been renamed to `proxy.ts` and the + exported function has been renamed from `middleware` to `proxy`. If you are + using an older version of Next.js, use `middleware.ts` and export `auth` as + `middleware` instead. + + +```ts filename="proxy.ts" +export { auth as proxy } from "@/auth" ``` Then define `authorized` callback in your `auth.ts` file. For more details check out the [reference docs](/reference/nextjs#authorized). @@ -263,12 +270,12 @@ export const { auth, handlers } = NextAuth({ }) ``` -You can also use the `auth` method as a wrapper if you'd like to implement more logic inside the middleware. +You can also use the `auth` method as a wrapper if you'd like to implement more logic inside the proxy. -```ts filename="middleware.ts" +```ts filename="proxy.ts" import { auth } from "@/auth" -export default auth((req) => { +export const proxy = auth((req) => { if (!req.auth && req.nextUrl.pathname !== "/login") { const newUrl = new URL("/login", req.nextUrl.origin) return Response.redirect(newUrl) @@ -276,17 +283,17 @@ export default auth((req) => { }) ``` -You can also use a regex to match multiple routes or you can negate certain routes in order to protect all remaining routes. The following example avoids running the middleware on paths such as the favicon or static images. +You can also use a regex to match multiple routes or you can negate certain routes in order to protect all remaining routes. The following example avoids running the proxy on paths such as the favicon or static images. -```ts filename="middleware.ts" +```ts filename="proxy.ts" export const config = { matcher: ["/((?!api|_next/static|_next/image|favicon.ico).*)"], } ``` -Middleware will protect pages as defined by the `matcher` config export. For more details about the matcher, check out the [Next.js docs](https://nextjs.org/docs/pages/building-your-application/routing/middleware#matching-paths). +The proxy will protect pages as defined by the `matcher` config export. For more details about the matcher, check out the [Next.js docs](https://nextjs.org/docs/app/api-reference/file-conventions/proxy). - You should not rely on middleware exclusively for authorization. Always ensure + You should not rely on the proxy exclusively for authorization. Always ensure that the session is verified as close to your data fetching as possible. diff --git a/docs/pages/guides/edge-compatibility.mdx b/docs/pages/guides/edge-compatibility.mdx index 4ae65343cb..f1cc82d8ea 100644 --- a/docs/pages/guides/edge-compatibility.mdx +++ b/docs/pages/guides/edge-compatibility.mdx @@ -27,7 +27,7 @@ Because this Node.js vs. other runtimes situation is so fragmented and fluid at ## Auth.js -Edge compatibility is something Auth.js has optimized for. That means that you can run the core Auth.js functionality on any JavaScript runtime you choose. The key word here, however, being **core functionality**. If you use _only_ Auth.js / `next-auth` and no other library in your Auth.js callbacks, Middleware, etc. then you can use it wherever you want! +Edge compatibility is something Auth.js has optimized for. That means that you can run the core Auth.js functionality on any JavaScript runtime you choose. The key word here, however, being **core functionality**. If you use _only_ Auth.js / `next-auth` and no other library in your Auth.js callbacks, Proxy, etc. then you can use it wherever you want! Issues begin to arise when you want to use other libraries with Auth.js. @@ -41,9 +41,18 @@ PostgreSQL is a database that uses a message-based protocol for communication be As edge runtimes have matured and become more popular, however, people have gotten creative and implemented various solutions to this problem. One such common solution is to put some sort of API server in front of the database whose goal is to translate database queries sent to it via HTTP into a protocol the database can understand. This allows the client side to only have to make HTTP requests to the API server, which is something that every edge runtime supports. -### Middleware +### Proxy (formerly Middleware) -In Next.js and `next-auth` you can also use Next.js [Middleware](https://nextjs.org/docs/app/building-your-application/routing/middleware) to protect routes by checking if a session exists and deciding where to route next. By default, on Vercel and other hosting providers, **Middleware code always runs in an edge runtime**. This means that our code will be trying to execute, for example, PostgreSQL queries in an environment where the underlying functionality is not available (i.e. TCP sockets). Therefore, **to use a database adapter that isn't explicitly "edge compatible", we will need to find a way to query the database using the features that we do have available to us**. +In Next.js and `next-auth` you can also use Next.js [Proxy](https://nextjs.org/docs/app/api-reference/file-conventions/proxy) (formerly [Middleware](https://nextjs.org/docs/app/building-your-application/routing/middleware)) to protect routes by checking if a session exists and deciding where to route next. + + + As of Next.js 16, `middleware.ts` has been renamed to `proxy.ts` and now runs + on the **Node.js runtime** instead of the edge runtime. If you are using + Next.js 16+, the edge compatibility workarounds below may no longer be + necessary. + + +For older versions of Next.js, **Middleware code always runs in an edge runtime**. This means that our code will be trying to execute, for example, PostgreSQL queries in an environment where the underlying functionality is not available (i.e. TCP sockets). Therefore, **to use a database adapter that isn't explicitly "edge compatible", we will need to find a way to query the database using the features that we do have available to us**. ## The Solution @@ -53,7 +62,7 @@ This means that everywhere in your application where you may want to check if th ### Split Config -With Next.js and `next-auth` in mind, let's think about what we need to do to make Auth.js be able to both run some of its code in an edge runtime, but also use a database to store its sessions. We would need a separate "version" of `next-auth` without the database settings for the edge environment and another one with the database for everywhere else. To achieve this, we can use the ["lazy initialization"](/reference/nextjs#lazy-initialization) features of Auth.js to instantiate a standalone client without the adapter for middleware and another one to be used everywhere else. +With Next.js and `next-auth` in mind, let's think about what we need to do to make Auth.js be able to both run some of its code in an edge runtime, but also use a database to store its sessions. We would need a separate "version" of `next-auth` without the database settings for the edge environment and another one with the database for everywhere else. To achieve this, we can use the ["lazy initialization"](/reference/nextjs#lazy-initialization) features of Auth.js to instantiate a standalone client without the adapter for the proxy and another one to be used everywhere else. 1. First, a common Auth.js configuration object to be used everywhere. This **will not** include the database adapter. @@ -85,13 +94,13 @@ export const { handlers, auth, signIn, signOut } = NextAuth({ }) ``` -3. Our Middleware, which would then import the configuration **without the database adapter** and instantiate its own Auth.js client. +3. Our Proxy (or Middleware for older Next.js versions), which would then import the configuration **without the database adapter** and instantiate its own Auth.js client. -```ts filename="middleware.ts" {2, 4} +```ts filename="proxy.ts" {2, 4} import NextAuth from "next-auth" import authConfig from "./auth.config" -export const { auth: middleware } = NextAuth(authConfig) +export const { auth: proxy } = NextAuth(authConfig) ``` 4. Finally, everywhere else we can import from the primary `auth.ts` configuration and use `next-auth` as usual. See our [session management docs](/getting-started/session-management/protecting) for more examples. @@ -114,4 +123,4 @@ export default async function Page() { } ``` -It is important to note here that we've now removed database functionality and support from `next-auth` **in the middleware**. That means that we won't be able to fetch the session or other info like the user's account details, etc. while executing code in middleware. That means you'll want to rely on checks like the one demonstrated above in the `/app/protected/page.tsx` file to ensure you're [protecting your routes](/getting-started/session-management/protecting) effectively. Middleware is then still used for bumping the session cookie's expiry time, for example. +It is important to note here that we've now removed database functionality and support from `next-auth` **in the proxy**. That means that we won't be able to fetch the session or other info like the user's account details, etc. while executing code in the proxy. That means you'll want to rely on checks like the one demonstrated above in the `/app/protected/page.tsx` file to ensure you're [protecting your routes](/getting-started/session-management/protecting) effectively. The proxy is then still used for bumping the session cookie's expiry time, for example. diff --git a/docs/pages/guides/role-based-access-control.mdx b/docs/pages/guides/role-based-access-control.mdx index f28e3de158..d12538ed4f 100644 --- a/docs/pages/guides/role-based-access-control.mdx +++ b/docs/pages/guides/role-based-access-control.mdx @@ -368,8 +368,8 @@ export const load: PageServerLoad = async (event) => { When using Next.js and JWT, you can alternatively also use - [Middleware](/getting-started/session-management/protecting#nextjs-middleware) - to redirect the user based on their role, even before rendering the page. + [Proxy](/getting-started/session-management/protecting#nextjs-proxy) to + redirect the user based on their role, even before rendering the page. ## Resources @@ -377,5 +377,5 @@ export const load: PageServerLoad = async (event) => { - [Concepts: Session strategies](/concepts/session-strategies) - [Adapters: User model](/getting-started/database#user-model) - [Adapters: Prisma adapter](/getting-started/adapters/prisma) -- [Next.js: Middleware](/getting-started/session-management/protecting#nextjs-middleware) +- [Next.js: Proxy](/getting-started/session-management/protecting#nextjs-proxy) - [TypeScript](/getting-started/typescript) diff --git a/docs/pages/index.mdx b/docs/pages/index.mdx index 41a8a74a7f..604ff929dd 100644 --- a/docs/pages/index.mdx +++ b/docs/pages/index.mdx @@ -116,8 +116,8 @@ import NextAuth from "next-auth" import GitHub from "next-auth/providers/github" export const { auth, handlers } = NextAuth({ providers: [GitHub] }) -// middleware.ts -export { auth as middleware } from "@/auth" +// proxy.ts +export { auth as proxy } from "@/auth" // app/api/auth/[...nextauth]/route.ts import { handlers } from "@/auth"