# How pushedAuthorizationRequests Works with buildAuthorizationUrl in Auth0 Auth-JS

> Learn how Auth0 Auth JS buildAuthorizationUrl uses pushedAuthorizationRequests to securely send parameters to the authorization server via its PAR endpoint returning a request_uri

- Repository: [Auth0/auth0-auth-js](https://github.com/auth0/auth0-auth-js)
- Tags: how-to-guide
- Published: 2026-02-25

---

**When you pass `{ pushedAuthorizationRequests: true }` to `AuthClient.buildAuthorizationUrl()`, the SDK initiates a Pushed Authorization Request (PAR) flow by posting parameters to the tenant's `pushed_authorization_request_endpoint` and returns an authorization URL containing only a `request_uri` instead of the full parameter set.**

The Auth0 Auth-JS library provides built-in support for OAuth 2.0 Pushed Authorization Requests to help applications avoid URL length limitations and prevent sensitive authorization parameters from appearing in browser history. By enabling the `pushedAuthorizationRequests` option when calling `buildAuthorizationUrl()`, you activate a secure backend-channel approach that validates tenant capabilities before constructing the final redirect URL. This implementation is located in the `AuthClient` class within the `auth0/auth0-auth-js` repository.

## How PAR Integrates with buildAuthorizationUrl

The integration follows a strict three-step validation and execution path defined in [`packages/auth0-auth-js/src/auth-client.ts`](https://github.com/auth0/auth0-auth-js/blob/main/packages/auth0-auth-js/src/auth-client.ts).

### Step 1: Server Metadata Discovery

First, the SDK discovers whether the tenant supports PAR. The private `#discover()` method fetches the OpenID Connect configuration from `https://<domain>/.well-known/openid-configuration` and examines the resulting `serverMetadata` for the presence of `pushed_authorization_request_endpoint`.

```typescript
const { serverMetadata } = await this.#discover();

```

According to the source code at lines 69-73 of [`auth-client.ts`](https://github.com/auth0/auth0-auth-js/blob/main/auth-client.ts), this discovery happens immediately upon entering the public `buildAuthorizationUrl()` method, ensuring the SDK has current tenant capabilities before proceeding.

### Step 2: PAR Capability Validation

Before constructing the URL, the SDK validates that PAR is actually available. At lines 72-76 of [`auth-client.ts`](https://github.com/auth0/auth0-auth-js/blob/main/auth-client.ts), the code checks if `options?.pushedAuthorizationRequests` is `true` while the `serverMetadata` lacks the required endpoint.

```typescript
if (options?.pushedAuthorizationRequests && !serverMetadata.pushed_authorization_request_endpoint) {
  throw new NotSupportedError(
    NotSupportedErrorCode.PAR_NOT_SUPPORTED,
    'The Auth0 tenant does not have pushed authorization requests enabled. Learn how to enable it here: https://auth0.com/docs/get-started/applications/configure-par'
  );
}

```

The `NotSupportedError` with code `PAR_NOT_SUPPORTED` is defined in [`packages/auth0-auth-js/src/errors.ts`](https://github.com/auth0/auth0-auth-js/blob/main/packages/auth0-auth-js/src/errors.ts). This guard prevents runtime failures against tenants that have not explicitly enabled the PAR feature in their Auth0 dashboard.

### Step 3: Conditional URL Construction

After passing the validation guard, the private `#buildAuthorizationUrl()` method prepares PKCE parameters and selects the appropriate builder. At lines 81-84 of [`auth-client.ts`](https://github.com/auth0/auth0-auth-js/blob/main/auth-client.ts), the SDK conditionally invokes either the standard or PAR-specific helper from the internal `client` module.

```typescript
const authorizationUrl = options?.pushedAuthorizationRequests
  ? await client.buildAuthorizationUrlWithPAR(configuration, params)   // PAR path
  : await client.buildAuthorizationUrl(configuration, params);        // Classic path

```

**`buildAuthorizationUrlWithPAR`** performs three operations:
1. **POSTs** the merged authorization parameters (including `client_id`, `code_challenge`, and custom `authorizationParams`) to the `pushed_authorization_request_endpoint`.
2. **Receives** a JSON response containing a `request_uri` (e.g., `urn:example:request_uri_123`).
3. **Assembles** the final `/authorize` URL containing only `client_id` and `request_uri` query parameters, significantly reducing URL length and keeping sensitive data out of the browser's address bar.

## Implementation Details in auth-client.ts

The complete flow demonstrates how the SDK handles parameter preparation before the conditional PAR call. The method first generates PKCE values using `client.randomPKCECodeVerifier()` and `client.calculatePKCECodeChallenge()`, then merges default and user-supplied parameters using `stripUndefinedProperties` from [`packages/auth0-auth-js/src/utils.ts`](https://github.com/auth0/auth0-auth-js/blob/main/packages/auth0-auth-js/src/utils.ts).

```typescript
const codeVerifier = client.randomPKCECodeVerifier();
const codeChallenge = await client.calculatePKCECodeChallenge(codeVerifier);
const additionalParams = stripUndefinedProperties({
  ...this.#options.authorizationParams,
  ...options?.authorizationParams,
});
const params = new URLSearchParams({
  scope: DEFAULT_SCOPES,
  ...additionalParams,
  client_id: this.#options.clientId,
  code_challenge: codeChallenge,
  code_challenge_method: 'S256',
});

```

These parameters are passed to either `buildAuthorizationUrlWithPAR` or `buildAuthorizationUrl` depending on the `pushedAuthorizationRequests` boolean. The PKCE generation occurs regardless of which path is taken, ensuring consistent security across both flows.

## Code Examples

### Standard Authorization URL (Classic Flow)

For tenants without PAR enabled, or when you prefer the traditional approach, omit the `pushedAuthorizationRequests` option.

```typescript
import { AuthClient } from '@auth0/auth0-auth-js';

const client = new AuthClient({
  domain: 'my-tenant.auth0.com',
  clientId: '<client_id>',
  clientSecret: '<client_secret>',
});

const { authorizationUrl, codeVerifier } = await client.buildAuthorizationUrl({
  authorizationParams: {
    redirect_uri: 'https://myapp.com/callback'
  }
});
// Redirect user to authorizationUrl.href

```

### PAR-Enabled Authorization URL

Enable the Pushed Authorization Request flow by setting `pushedAuthorizationRequests: true`. The resulting URL will contain only the `request_uri` parameter.

```typescript
import { AuthClient } from '@auth0/auth0-auth-js';

const client = new AuthClient({
  domain: 'my-tenant.auth0.com',
  clientId: '<client_id>',
  clientSecret: '<client_secret>',
});

const { authorizationUrl, codeVerifier } = await client.buildAuthorizationUrl({
  pushedAuthorizationRequests: true,  // Enable PAR
  authorizationParams: {
    redirect_uri: 'https://myapp.com/callback',
    audience: 'https://api.example.com'
  }
});

// authorizationUrl.searchParams.get('request_uri') contains the reference
// authorizationUrl.searchParams.size is minimal (typically 2)

```

### Handling Tenants Without PAR Support

The SDK throws a specific error code when PAR is requested but not available. Catch `NotSupportedError` with code `par_not_supported_error` to implement fallback logic.

```typescript
import { NotSupportedError } from '@auth0/auth0-auth-js';

try {
  const { authorizationUrl } = await client.buildAuthorizationUrl({ 
    pushedAuthorizationRequests: true 
  });
} catch (err) {
  if (err instanceof NotSupportedError && err.code === 'par_not_supported_error') {
    // Fallback to classic flow
    const { authorizationUrl } = await client.buildAuthorizationUrl();
    // Proceed with standard authorization
  }
}

```

The test suite in [`packages/auth0-auth-js/src/auth-client.spec.ts`](https://github.com/auth0/auth0-auth-js/blob/main/packages/auth0-auth-js/src/auth-client.spec.ts) validates this behavior. Lines 658-662 verify that deleting `pushed_authorization_request_endpoint` from the mock discovery document causes `buildAuthorizationUrl({ pushedAuthorizationRequests: true })` to throw the specific error message. Conversely, lines 687-706 confirm that when the endpoint is present, the resulting URL contains only the `request_uri` parameter with a minimal query string size of 2.

## Summary

- **Discovery First**: The SDK always fetches fresh metadata from `/.well-known/openid-configuration` to check for `pushed_authorization_request_endpoint` before attempting PAR.
- **Strict Validation**: If `pushedAuthorizationRequests: true` is passed but the tenant lacks support, the SDK immediately throws `NotSupportedError` with code `PAR_NOT_SUPPORTED` from [`auth-client.ts`](https://github.com/auth0/auth0-auth-js/blob/main/auth-client.ts) lines 72-76.
- **Backend Channel**: The `buildAuthorizationUrlWithPAR` helper posts full parameter sets to the PAR endpoint, receiving a `request_uri` that replaces the bulky query string in the final authorization URL.
- **PKCE Compatible**: PAR flows in Auth0 Auth-JS always include PKCE generation (`code_challenge` and `code_verifier`) regardless of whether the classic or PAR path is taken.
- **Minimal URLs**: The final authorization URL contains only `client_id` and `request_uri`, mitigating browser URL length limits and preventing sensitive parameters from appearing in browser history.

## Frequently Asked Questions

### What happens if I request PAR on a tenant that does not support it?

The SDK throws a `NotSupportedError` with the error code `par_not_supported_error`. According to the implementation in [`auth-client.ts`](https://github.com/auth0/auth0-auth-js/blob/main/auth-client.ts) lines 72-76, this check occurs after fetching the discovery document but before making any PAR HTTP requests, ensuring clear failure messaging that directs you to Auth0's PAR configuration documentation.

### Can I use PAR with PKCE in Auth0 Auth-JS?

Yes. The SDK automatically generates PKCE code verifiers and challenges for all authorization flows, including PAR. As shown in the source code, `client.randomPKCECodeVerifier()` and `client.calculatePKCECodeChallenge()` execute before the conditional logic that selects between `buildAuthorizationUrl` and `buildAuthorizationUrlWithPAR`, ensuring the `code_challenge` is included in the parameters pushed to the PAR endpoint.

### How does the final authorization URL differ when using pushedAuthorizationRequests?

Instead of containing all authorization parameters (scope, redirect_uri, audience, etc.) in the query string, the PAR-enabled URL contains only two parameters: `client_id` and `request_uri`. The `request_uri` value (e.g., `urn:auth0:request:xyz123`) is a reference handle that the authorization server uses to retrieve the full parameter set that was previously pushed via the backend POST request.

### Where is the PAR error code defined?

The `PAR_NOT_SUPPORTED` error code is defined in [`packages/auth0-auth-js/src/errors.ts`](https://github.com/auth0/auth0-auth-js/blob/main/packages/auth0-auth-js/src/errors.ts) as part of the `NotSupportedErrorCode` enumeration. When thrown from [`auth-client.ts`](https://github.com/auth0/auth0-auth-js/blob/main/auth-client.ts), the error includes a descriptive message explaining that the tenant does not have pushed authorization requests enabled and provides a link to the Auth0 documentation for configuring the feature.