Skip to content

feature/add customize auth handlers docs #2218

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

Draft
wants to merge 4 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all 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
65 changes: 65 additions & 0 deletions EXAMPLES.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@
- [On the server (App Router)](#on-the-server-app-router-3)
- [On the server (Pages Router)](#on-the-server-pages-router-3)
- [Middleware](#middleware-3)
- [Customizing Auth Handlers](#customizing-auth-handlers)
- [Run custom code before Auth Handlers](#run-custom-code-before-auth-handlers)
- [Run code after callback](#run-code-after-callback)

## Passing authorization parameters

Expand Down Expand Up @@ -1225,3 +1228,65 @@ export async function middleware(request: NextRequest) {
return resWithCombinedHeaders;
}
```

## Customizing Auth Handlers

In v4, authentication routes (`/auth/login`, `/auth/logout`, `/auth/callback`) are handled automatically by the middleware. While you can no longer customize individual route handlers directly like in v3, you can intercept these routes in your middleware to run custom logic before the auth handlers execute.

This approach allows you to:
- Run custom code before authentication actions (logging, analytics, validation)
- Modify the response (set cookies, headers, etc.)
- Implement custom redirects or early returns when needed
- Add business logic around authentication flows
- Maintain compatibility with existing tracking and analytics systems

The middleware-based approach provides the same level of control as v3's custom handlers while working seamlessly with v4's automatic route handling.

### Run custom code before Auth Handlers

Following example shows how to run custom logic before the `logout` handler:
```ts
export async function middleware(request) {

// prepare NextResponse object from auth0 middleware
const authRes = await auth0.middleware(request);

// The following interceptUrls can be used:
// "/auth/login" : intercept login auth handler
// "/auth/logout" : intercept logout auth handler
// "/auth/callback" : intercept callback auth handler
// "/your/login/returnTo/url" : intercept redirect after login
// "/your/logout/returnTo/url" : intercept redirect after logout

const interceptUrl = "/auth/logout";

// intercept auth handler
if (request.nextUrl.pathname === interceptUrl) {
// do custom stuff
console.log("Pre-logout code")

// Example: Set a cookie
authRes.cookies.set('myCustomCookie', 'cookieValue', { path: '/' });
// Example: Set another cookie with options
authRes.cookies.set({
name: 'anotherCookie',
value: 'anotherValue',
httpOnly: true,
path: '/',
});

// Example: Delete a cookie
// authRes.cookies.delete('cookieNameToDelete');

// you can also do an early return here with your own NextResponse object
// return NextResponse.redirect(new URL('/custom-logout-page'));
}

// return the original auth0-handled NextResponse object
return authRes
}
```

### Run code after callback
Please refer to [onCallback](https://github.com/auth0/nextjs-auth0/blob/main/EXAMPLES.md#oncallback)
for details on how to run code after callback.
17 changes: 17 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,23 @@ You can customize the client by using the options below:
| httpTimeout | `number` | Integer value for the HTTP timeout in milliseconds for authentication requests. Defaults to `5000` milliseconds |
| enableTelemetry | `boolean` | Boolean value to opt-out of sending the library name and version to your authorization server via the `Auth0-Client` header. Defaults to `true`. |

### Customizing Auth Handlers

While the authentication routes are handled automatically by the middleware, you can still customize the authentication flow through two main approaches:

- **Run custom code before auth handlers**: Intercept auth routes in your middleware to add custom logic before authentication actions
- **Run code after authentication**: Use the `onCallback` hook to add custom logic after authentication completes

Additional customization options include:
- Login parameters via query parameters or static configuration
- Session data modification using the `beforeSessionSaved` hook
- Logout redirects using query parameters

> [!IMPORTANT]
> When customizing auth handlers, always validate user inputs (especially redirect URLs) to prevent security vulnerabilities like open redirects. Use relative URLs when possible and implement proper input sanitization.

**Quick Start**: For detailed examples and step-by-step migration patterns from v3, see [Customizing Auth Handlers](https://github.com/auth0/nextjs-auth0/blob/main/EXAMPLES.md#customizing-auth-handlers).

## Session Cookie Configuration

You can specify the following environment variables to configure the session cookie:
Expand Down
95 changes: 95 additions & 0 deletions V4_MIGRATION_GUIDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -285,3 +285,98 @@ export const auth0 = new Auth0Client({
- `touchSession` method was removed. The middleware enables rolling sessions by default and can be configured via the [Session configuration section in the Examples guide](https://github.com/auth0/nextjs-auth0/blob/main/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](https://github.com/auth0/nextjs-auth0/blob/main/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.

## Customizing Auth Handlers

In v3, you could customize individual auth handlers by providing custom implementations to the `handleAuth` function:

```ts
// v3 approach (no longer available in v4)
export const GET = handleAuth({
async logout(req: NextApiRequest, res: NextApiResponse) {
// Custom logout logic
console.log('User is logging out');

return await handleLogout(req, res);
},
async login(req: NextApiRequest, res: NextApiResponse) {
// Custom login logic
return await handleLogin(req, res, {
authorizationParams: {
audience: 'https://my-api.com'
}
});
}
});
```

In v4, the auth routes are handled automatically by the middleware, but you can achieve similar customization through two main approaches:

### 1. Run custom code before auth handlers (Middleware Interception)

You can intercept auth routes in your middleware to run custom logic before the auth handlers execute:

```ts
import type { NextRequest } from 'next/server';
import { auth0 } from './lib/auth0';

export async function middleware(request: NextRequest) {
const authRes = await auth0.middleware(request);

// Intercept specific auth routes
if (request.nextUrl.pathname === '/auth/logout') {
// Custom logout logic runs BEFORE the actual logout
console.log('User is logging out');

// Example: Set custom cookies
authRes.cookies.set('logoutTime', new Date().toISOString());
}

if (request.nextUrl.pathname === '/auth/login') {
// Custom login logic runs BEFORE the actual login
console.log('User is attempting to login');
}

return authRes;
}
```

### 2. Run code after authentication (Callback Hook)

Use the `onCallback` hook to add custom logic after authentication completes:

```ts
import { NextResponse } from 'next/server';
import { Auth0Client } from '@auth0/nextjs-auth0/server';

export const auth0 = new Auth0Client({
async onCallback(error, context, session) {
if (error) {
console.error('Authentication error:', error);
return NextResponse.redirect(
new URL('/error', process.env.APP_BASE_URL)
);
}

// Custom logic after successful authentication
if (session) {
console.log(`User ${session.user.sub} logged in successfully`);
}

return NextResponse.redirect(
new URL(context.returnTo || "/", process.env.APP_BASE_URL)
);
}
});
```

### Additional Customization Options

- **Login parameters**: Use query parameters (`/auth/login?audience=...`) or static configuration
- **Session data**: Use the `beforeSessionSaved` hook to modify session data
- **Logout redirects**: Use query parameters (`/auth/logout?returnTo=...`)

> [!IMPORTANT]
> Always validate redirect URLs to prevent open redirect attacks. Use relative URLs when possible.

For detailed examples and implementation patterns, see [Customizing Auth Handlers](https://github.com/auth0/nextjs-auth0/blob/main/EXAMPLES.md#customizing-auth-handlers) in the Examples guide.