Skip to content
Open
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
58 changes: 51 additions & 7 deletions EXAMPLES.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@
- [ID Token claims and the user object](#id-token-claims-and-the-user-object)
- [Routes](#routes)
- [Custom routes](#custom-routes)
- [Dynamic Application Base URLs](#dynamic-application-base-urls)
- [Testing helpers](#testing-helpers)
- [`generateSessionCookie`](#generatesessioncookie)
- [Programmatically starting interactive login](#programmatically-starting-interactive-login)
Expand Down Expand Up @@ -2376,16 +2377,18 @@ For example, a custom `onCallback` hook may be specified like so:
```ts
export const auth0 = new Auth0Client({
async onCallback(error, context, session) {
const appBaseUrl = context.appBaseUrl ?? process.env.APP_BASE_URL;

// redirect the user to a custom error page
if (error) {
return NextResponse.redirect(
new URL(`/error?error=${error.message}`, process.env.APP_BASE_URL)
new URL(`/error?error=${error.message}`, appBaseUrl)
);
}

// complete the redirect to the provided returnTo URL
return NextResponse.redirect(
new URL(context.returnTo || "/", process.env.APP_BASE_URL)
new URL(context.returnTo || "/", appBaseUrl)
);
}
});
Expand Down Expand Up @@ -2462,7 +2465,7 @@ Set the desired environment variables in your `.env.local` file or your deployme
AUTH0_COOKIE_DOMAIN='.example.com' # Set cookie for subdomains
AUTH0_COOKIE_PATH='/app' # Limit cookie to /app path
AUTH0_COOKIE_TRANSIENT=true # Make cookie transient (session-only)
AUTH0_COOKIE_SECURE=true # Recommended for production
AUTH0_COOKIE_SECURE=true # Recommended for production; enforced when appBaseUrl is omitted
AUTH0_COOKIE_SAME_SITE='Lax'
```

Expand Down Expand Up @@ -2497,7 +2500,7 @@ export const auth0 = new Auth0Client({
- `domain` (String): Specifies the `Domain` attribute.
- `path` (String): Specifies the `Path` attribute. Defaults to `/`.
- `transient` (Boolean): If `true`, the `maxAge` attribute is omitted, making it a session cookie. Defaults to `false`.
- `secure` (Boolean): Specifies the `Secure` attribute. Defaults to `false` (or `true` if `AUTH0_COOKIE_SECURE=true` is set).
- `secure` (Boolean): Specifies the `Secure` attribute. Defaults to `false` (or `true` if `AUTH0_COOKIE_SECURE=true` is set, or when `appBaseUrl` is omitted in production).
- `sameSite` ('Lax' | 'Strict' | 'None'): Specifies the `SameSite` attribute. Defaults to `Lax` (or the value of `AUTH0_COOKIE_SAME_SITE`).
- `name` (String): The name of the session cookie. Defaults to `__session`.

Expand Down Expand Up @@ -2564,7 +2567,7 @@ const authClient = new Auth0Client({
| cookieOptions.maxAge | `number` | The expiration time for transaction cookies in seconds. Defaults to `3600` (1 hour). After this time, abandoned transaction cookies will expire automatically. |
| cookieOptions.prefix | `string` | The prefix for transaction cookie names. Defaults to `__txn_`. In parallel mode, cookies are named `__txn_{state}`. In single mode, just `__txn_`. |
| cookieOptions.sameSite | `"strict" \| "lax" \| "none"` | Controls when the cookie is sent with cross-site requests. Defaults to `"lax"`. |
| cookieOptions.secure | `boolean` | When `true`, the cookie will only be sent over HTTPS connections. Automatically determined based on your application's base URL protocol if not specified. |
| cookieOptions.secure | `boolean` | When `true`, the cookie will only be sent over HTTPS connections. Derived from `appBaseUrl` when available; enforced in production when `appBaseUrl` is omitted. |
| cookieOptions.path | `string` | Specifies the URL path for which the cookie is valid. Defaults to `"/"`. |

## Database sessions
Expand Down Expand Up @@ -2661,13 +2664,15 @@ import { Auth0Client } from "@auth0/nextjs-auth0/server";

export const auth0 = new Auth0Client({
async onCallback(err, ctx, session) {
const appBaseUrl = ctx.appBaseUrl ?? process.env.APP_BASE_URL;

// `ctx` will contain the following properties when handling a connected account callback:
// - `connectedAccount`: the connected account object (`CompleteConnectAccountResponse`) if the connection was successful
// - `responseType`: will be set to `connect_code` when handling a connected accounts callback (`RESPONSE_TYPES.ConnectCode`)
// - `returnTo`: the returnTo URL specified when calling the connect endpoint (if any)

return NextResponse.redirect(
new URL(ctx.returnTo ?? "/", process.env.APP_BASE_URL)
new URL(ctx.returnTo ?? "/", appBaseUrl)
);
},
enableConnectAccountEndpoint: true
Expand Down Expand Up @@ -2812,6 +2817,45 @@ NEXT_PUBLIC_ACCESS_TOKEN_ROUTE=/api/auth/token
> [!IMPORTANT]
> Updating the route paths will also require updating the **Allowed Callback URLs** and **Allowed Logout URLs** configured in the [Auth0 Dashboard](https://manage.auth0.com) for your client.

## Dynamic Application Base URLs

By default the SDK uses `appBaseUrl`/`APP_BASE_URL`. If it is omitted, the base URL is inferred at runtime from the request host.

### Host-based inference (zero-config)

Omit `APP_BASE_URL` to let the SDK infer the base URL from the incoming request:

```env
# .env.local
AUTH0_DOMAIN=
AUTH0_CLIENT_ID=
AUTH0_CLIENT_SECRET=
AUTH0_SECRET=
# APP_BASE_URL omitted
```

### Allow-listing hosts

To restrict which hosts are accepted, pass an allow list (or use a comma-separated `APP_BASE_URL`):

```ts
import { Auth0Client } from "@auth0/nextjs-auth0/server";

const appBaseUrls = [
"https://app.example.com",
process.env.VERCEL_URL ? `https://${process.env.VERCEL_URL}` : undefined
].filter((value): value is string => Boolean(value));

export const auth0 = new Auth0Client({
appBaseUrl: appBaseUrls
});
```

If the request host does not match the allow list, the SDK throws `InvalidConfigurationError`.

> [!NOTE]
> When relying on dynamic base URLs in production, the SDK enforces secure cookies. If you explicitly set `AUTH0_COOKIE_SECURE=false`, `session.cookie.secure=false`, or `transactionCookie.secure=false`, the SDK throws `InvalidConfigurationError`.

## Testing helpers

### `generateSessionCookie`
Expand Down Expand Up @@ -3545,4 +3589,4 @@ The SDK provides typed error classes for all MFA operations:
| `MfaVerifyError` | `invalid_grant` | Verification failed | Invalid OTP code |
| `MfaTokenNotFoundError` | `mfa_token_not_found` | No MFA context for token | Token not in session |
| `MfaTokenExpiredError` | `mfa_token_expired` | Token TTL exceeded | Context expired |
| `MfaTokenInvalidError` | `mfa_token_invalid` | Token tampered or wrong secret | Decryption failed |
| `MfaTokenInvalidError` | `mfa_token_invalid` | Token tampered or wrong secret | Decryption failed |
36 changes: 33 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ AUTH0_DOMAIN=
AUTH0_CLIENT_ID=
AUTH0_CLIENT_SECRET=
AUTH0_SECRET=
APP_BASE_URL=
APP_BASE_URL= # optional for dynamic preview environments
```

The `AUTH0_DOMAIN`, `AUTH0_CLIENT_ID`, and `AUTH0_CLIENT_SECRET` can be obtained from the [Auth0 Dashboard](https://manage.auth0.com) once you've created an application. **This application must be a `Regular Web Application`**.
Expand All @@ -47,12 +47,41 @@ openssl rand -hex 32
```

The `APP_BASE_URL` is the URL that your application is running on. When developing locally, this is most commonly `http://localhost:3000`.
If you omit it, the SDK will infer the base URL from the incoming request host at runtime.

> [!IMPORTANT]
> You will need to register the following URLs in your Auth0 Application via the [Auth0 Dashboard](https://manage.auth0.com):
>
> - Add `http://localhost:3000/auth/callback` to the list of **Allowed Callback URLs**
> - Add `http://localhost:3000` to the list of **Allowed Logout URLs**
>
> When using dynamic hosts (preview environments), ensure the resulting callback and logout URLs are registered in your Auth0 application.

#### Dynamic base URLs (Preview deployments)

For preview environments (`Vercel`, `Netlify`), we recommend supplying an allow list so only known hosts are accepted (or use a comma-separated `APP_BASE_URL`).
The SDK resolves the base URL per request by matching the incoming host against the list. If multiple entries match, the most specific URL path wins.

If you prefer zero-config, you can omit `APP_BASE_URL` and let the SDK infer the base URL from the request host at runtime.
Because host headers are untrusted input, the SDK treats the Auth0 Allowed Callback URLs as the primary safeguard in zero-config mode: if the inferred host is not allowlisted in Auth0, the authorize request is rejected. An allow list adds an SDK-side guardrail before any redirect happens.

```ts
import { Auth0Client } from "@auth0/nextjs-auth0/server";

const appBaseUrls = [
"https://app.example.com",
process.env.VERCEL_URL ? `https://${process.env.VERCEL_URL}` : undefined
].filter((value): value is string => Boolean(value));

export const auth0 = new Auth0Client({
appBaseUrl: appBaseUrls
});
```

> [!NOTE]
> When relying on dynamic base URLs in production, the SDK enforces secure cookies. If you explicitly set `AUTH0_COOKIE_SECURE=false`, `session.cookie.secure=false`, or `transactionCookie.secure=false`, the SDK throws `InvalidConfigurationError`.
>
> If the request host does not match the allow list, the SDK throws `InvalidConfigurationError`.

### 3. Create the Auth0 SDK client

Expand Down Expand Up @@ -173,7 +202,7 @@ You can customize the client by using the options below:
| authorizationParameters | `AuthorizationParameters` | The authorization parameters to pass to the `/authorize` endpoint. See [Passing authorization parameters](https://github.com/auth0/nextjs-auth0/blob/main/EXAMPLES.md#passing-authorization-parameters) for more details. |
| clientAssertionSigningKey | `string` or `CryptoKey` | Private key for use with `private_key_jwt` clients. This can also be specified via the `AUTH0_CLIENT_ASSERTION_SIGNING_KEY` environment variable. |
| clientAssertionSigningAlg | `string` | The algorithm used to sign the client assertion JWT. This can also be provided via the `AUTH0_CLIENT_ASSERTION_SIGNING_ALG` environment variable. |
| appBaseUrl | `string` | The URL of your application (e.g.: `http://localhost:3000`). If it's not specified, it will be loaded from the `APP_BASE_URL` environment variable. |
| appBaseUrl | `string \| string[]` | The URL of your application (e.g.: `http://localhost:3000`). If it's not specified, it will be loaded from the `APP_BASE_URL` environment variable or inferred from the request host at runtime. Pass an array (or a comma-separated `APP_BASE_URL`) to allow-list multiple hosts. |
| logoutStrategy | `"auto" \| "oidc" \| "v2"` | Strategy for logout endpoint selection. `"auto"` (default) uses OIDC logout when available, falls back to `/v2/logout`. `"oidc"` always uses OIDC logout. `"v2"` always uses `/v2/logout` endpoint which supports wildcard URLs. See [Configuring logout strategy](https://github.com/auth0/nextjs-auth0/blob/main/EXAMPLES.md#configuring-logout-strategy) for details. |
| includeIdTokenHintInOIDCLogoutUrl | `boolean` | Configure whether to include `id_token_hint` in OIDC logout URLs for privacy. Defaults to `true` (recommended). When `false`, excludes PII from logout URLs but reduces DoS protection. See [OIDC logout privacy configuration](https://github.com/auth0/nextjs-auth0/blob/main/EXAMPLES.md#oidc-logout-privacy-configuration) for details. |
| secret | `string` | A 32-byte, hex-encoded secret used for encrypting cookies. If it's not specified, it will be loaded from the `AUTH0_SECRET` environment variable. |
Expand Down Expand Up @@ -388,14 +417,15 @@ The SDK performs validation of required configuration options when initializing

- `domain` (or `AUTH0_DOMAIN` environment variable)
- `clientId` (or `AUTH0_CLIENT_ID` environment variable)
- `appBaseUrl` (or `APP_BASE_URL` environment variable)
- `secret` (or `AUTH0_SECRET` environment variable)
- Either:
- `clientSecret` (or `AUTH0_CLIENT_SECRET` environment variable), OR
- `clientAssertionSigningKey` (or `AUTH0_CLIENT_ASSERTION_SIGNING_KEY` environment variable)

If any of these required options are missing, the SDK will issue a warning with a detailed message explaining which options are missing and how to provide them.

`appBaseUrl` is optional; if omitted, the SDK will infer it from the request host at runtime.

## Routes

The SDK mounts 6 routes:
Expand Down
Loading