Skip to content
Closed
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 56 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,33 @@ export const auth0 = new Auth0Client();
> The Auth0Client automatically uses safe defaults to manage authentication cookies. For advanced use cases, you can customize transaction cookie behavior by providing your own configuration. See [Transaction Cookie Configuration](https://github.com/auth0/nextjs-auth0/blob/main/EXAMPLES.md#transaction-cookie-configuration) for details.

### 4. Add the authentication middleware
Authentication requests in Next.js are intercepted at the network boundary using a middleware or proxy file.
Follow the setup below depending on your Next.js version.

#### 🟦 On Next.js 15

Create a `middleware.ts` file in the root of your project:

```ts
import type { NextRequest } from "next/server";
import { auth0 } from "./lib/auth0"; // Adjust path if your auth0 client is elsewhere

export async function middleware(request: NextRequest) {
return await auth0.middleware(request);
}

export const config = {
matcher: [
/*
* Match all request paths except for:
* - _next/static (static files)
* - _next/image (image optimization files)
* - favicon.ico, sitemap.xml, robots.txt (metadata files)
*/
"/((?!_next/static|_next/image|favicon.ico|sitemap.xml|robots.txt).*)"
]
};
```

Create a `middleware.ts` file in the root of your project's directory:

Expand Down Expand Up @@ -98,6 +125,35 @@ export const config = {
> [!NOTE]
> If you're using a `src/` directory, the `middleware.ts` file must be created inside the `src/` directory.


#### 🟨 On Next.js 16
Next.js 16 introduces a new convention called proxy.ts, replacing middleware.ts.
This change better represents the network interception boundary and unifies request handling
for both the Edge and Node runtimes.

Create a proxy.ts file in the root of your project (Or rename your existing middleware.ts to proxy.ts):
```ts
import type { NextRequest } from "next/server";
import { auth0 } from "./lib/auth0";

export async function proxy(request: NextRequest) {
return await auth0.middleware(request);
}

export const config = {
matcher: [
"/((?!_next/static|_next/image|favicon.ico|sitemap.xml|robots.txt).*)"
]
};
```
> [!IMPORTANT]
> Starting with **Next.js 16**, the recommended file for handling authentication boundaries is **`proxy.ts`**. You can still continue using **`middleware.ts`** for backward compatibility, it will work under the **Edge runtime** in Next.js 16. However, it is **deprecated** for the Node runtime and will be removed in a future release.
>
> The new proxy layer also executes slightly earlier in the routing pipeline, so make sure your matcher patterns do not conflict with other proxy or middleware routes.
>
> Additionally, the Edge runtime now applies stricter header and cookie validation,
> so avoid setting non-string cookie values or invalid header formats.

> [!IMPORTANT]
> This broad middleware matcher is essential for rolling sessions and security features. For scenarios when rolling sessions are disabled, see [Session Configuration](https://github.com/auth0/nextjs-auth0/blob/main/EXAMPLES.md#session-configuration) for alternative approaches.

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@
"vitest": "^2.1.4"
},
"peerDependencies": {
"next": "^14.2.25 || ^15.2.3",
"next": "^14.2.25 || ^15.2.3 || ^16.0.0-0",
"react": "^18.0.0 || ^19.0.0 || ^19.0.0-0",
"react-dom": "^18.0.0 || ^19.0.0 || ^19.0.0-0"
},
Expand Down
14 changes: 14 additions & 0 deletions src/client/helpers/get-session.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
export async function getSession(): Promise<any> {
// Implementation to get the session from the server
const response = await fetch("/auth/session", {
method: "GET",
credentials: "include"
});

if (!response.ok) {
throw new Error("Failed to fetch session");
}

const session = await response.json();
return session;
}
9 changes: 7 additions & 2 deletions src/server/auth-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ import {
FetcherHooks,
FetcherMinimalConfig
} from "./fetcher.js";
import { isPrefetch, nextNextResponse, toNextRequest } from "./next-compat.js";
import { AbstractSessionStore } from "./session/abstract-session-store.js";
import { TransactionState, TransactionStore } from "./transaction-store.js";
import { filterDefaultIdTokenClaims } from "./user.js";
Expand Down Expand Up @@ -369,7 +370,8 @@ export class AuthClient {
}
}

async handler(req: NextRequest): Promise<NextResponse> {
async handler(request: Request | NextRequest): Promise<NextResponse> {
const req = toNextRequest(request);
const { pathname } = req.nextUrl;
const sanitizedPathname = removeTrailingSlash(pathname);
const method = req.method;
Expand Down Expand Up @@ -400,10 +402,13 @@ export class AuthClient {
) {
return this.handleConnectAccount(req);
} else {
if (isPrefetch(req)) {
return nextNextResponse();
}
// no auth handler found, simply touch the sessions
// TODO: this should only happen if rolling sessions are enabled. Also, we should
// try to avoid reading from the DB (for stateful sessions) on every request if possible.
const res = NextResponse.next();
const res = nextNextResponse();
const session = await this.sessionStore.get(req.cookies);

if (session) {
Expand Down
Loading
Loading