# Auth0 Client Authentication Methods: How `#getClientAuth` Prioritizes mTLS, private_key_jwt, and client_secret_post

> Discover Auth0 client authentication methods like mTLS, private_key_jwt, and client_secret_post. Learn how #getClientAuth prioritizes these options for robust security.

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

---

**The Auth0 JavaScript SDK supports three client authentication methods—mTLS, `private_key_jwt`, and `client_secret_post`—which the private method `#getClientAuth` evaluates in that strict security-first order, automatically selecting the strongest available option or throwing `MissingClientAuthError` if none are configured.**

The `auth0-auth-js` SDK authenticates your application during privileged OAuth 2.0 flows such as Custom Token Exchange and Back-Channel Logout. The `AuthClient` class encapsulates this logic in the private method `#getClientAuth`, located 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), which implements a deterministic precedence hierarchy based on cryptographic strength.

## Supported Client Authentication Methods

The SDK implements three distinct mechanisms for proving client identity to the authorization server. Each requires specific configuration options passed to the `AuthClient` constructor.

### mTLS (Mutual TLS)

**mTLS** provides the strongest security guarantee by authenticating the client at the TLS transport layer using X.509 certificates. To enable this method, set `useMtls: true` in your SDK configuration. When activated, `#getClientAuth` immediately returns `client.TlsClientAuth()` without evaluating other options. This method requires your HTTP client (configured via `customFetch`) to present a valid client certificate during the TLS handshake.

### private_key_jwt

The **`private_key_jwt`** method sends a signed JSON Web Token (JWT) as the client assertion. This requires the `clientAssertionSigningKey` option containing either a PEM-encoded PKCS#8 private key string or a WebCrypto `CryptoKey` object. Optionally specify `clientAssertionSigningAlg` (defaults to **RS256**) to control the signing algorithm. If you provide a string key, `#getClientAuth` asynchronously imports it using `importPKCS8` before returning `client.PrivateKeyJwt(key)`.

### client_secret_post

**`client_secret_post`** transmits the raw client secret in the HTTP POST request body. Configure this fallback method by providing the `clientSecret` option. While simple to implement, this is the least secure option as it exposes the secret in the request payload, making it vulnerable to interception if TLS is compromised.

## Prioritization Logic in `#getClientAuth`

The method implements a strict security hierarchy (high to low) as documented in the source comments at lines 1025–1032 of [`auth-client.ts`](https://github.com/auth0/auth0-auth-js/blob/main/auth-client.ts). The implementation at lines 1036–1054 executes this precedence:

1. **mTLS first** – If `this.#options.useMtls` is truthy, return `client.TlsClientAuth()` immediately
2. **Private key JWT second** – If `clientAssertionSigningKey` exists, import it as a `CryptoKey` if necessary, then return `client.PrivateKeyJwt(clientPrivateKey)`
3. **Client secret last** – Fallback to `client.ClientSecretPost(this.#options.clientSecret!)` if no prior method is configured

If none of these conditions are met, the method throws **MissingClientAuthError** to prevent unauthenticated privileged flows.

```typescript
// packages/auth0-auth-js/src/auth-client.ts (lines 1036-1054)
async #getClientAuth(): Promise<client.ClientAuth> {
  // 1️⃣ mTLS
  if (this.#options.useMtls) {
    return client.TlsClientAuth();
  }

  // 2️⃣ private_key_jwt (import PKCS#8 if needed)
  let clientPrivateKey = this.#options.clientAssertionSigningKey as CryptoKey | undefined;
  if (clientPrivateKey && !(clientPrivateKey instanceof CryptoKey)) {
    clientPrivateKey = await importPKCS8(
      clientPrivateKey,
      this.#options.clientAssertionSigningAlg || 'RS256'
    );
  }

  // 3️⃣ client_secret_post (fallback)
  return clientPrivateKey
    ? client.PrivateKeyJwt(clientPrivateKey)
    : client.ClientSecretPost(this.#options.clientSecret!);
}

```

The concrete authentication objects (`TlsClientAuth`, `PrivateKeyJwt`, `ClientSecretPost`) are implemented in [`packages/auth0-auth-js/src/client.ts`](https://github.com/auth0/auth0-auth-js/blob/main/packages/auth0-auth-js/src/client.ts) and returned as `client.ClientAuth` types compatible with the underlying OAuth library.

## Configuration Examples

The following configurations demonstrate how to trigger each authentication path through `createAuth0Client`:

```typescript
import createAuth0Client from '@auth0/auth0-auth-js';

// 1️⃣ mTLS authentication
const authMtls = await createAuth0Client({
  domain: 'YOUR_DOMAIN',
  clientId: 'YOUR_CLIENT_ID',
  useMtls: true,
  // Ensure customFetch provides a TLS client certificate
});

// 2️⃣ private_key_jwt authentication
const authJwt = await createAuth0Client({
  domain: 'YOUR_DOMAIN',
  clientId: 'YOUR_CLIENT_ID',
  clientAssertionSigningKey: `-----BEGIN PRIVATE KEY-----
  MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC...
  -----END PRIVATE KEY-----`,
  clientAssertionSigningAlg: 'RS256', // Optional, defaults to RS256
});

// 3️⃣ client_secret_post authentication (fallback)
const authSecret = await createAuth0Client({
  domain: 'YOUR_DOMAIN',
  clientId: 'YOUR_CLIENT_ID',
  clientSecret: 'YOUR_CLIENT_SECRET',
});

```

All three configurations invoke `#getClientAuth` internally when performing privileged flows requiring client authentication, such as token exchange or logout notifications.

## Summary

- The `auth0-auth-js` SDK supports **three client authentication methods**: mTLS, `private_key_jwt`, and `client_secret_post`.
- **`#getClientAuth`** implements a security-first priority order: mTLS → private_key_jwt → client_secret_post.
- **mTLS** requires `useMtls: true` and provides transport-layer authentication via `client.TlsClientAuth()`.
- **`private_key_jwt`** requires `clientAssertionSigningKey` and uses `client.PrivateKeyJwt()` after importing the key if necessary.
- **`client_secret_post`** requires `clientSecret` and serves as the fallback via `client.ClientSecretPost()`.
- The method throws **MissingClientAuthError** if no valid authentication configuration is detected.

## Frequently Asked Questions

### What happens if I configure multiple client authentication methods?

**The SDK always selects the first method in the priority chain regardless of additional configuration.** If you set `useMtls: true` while also providing `clientAssertionSigningKey`, `#getClientAuth` returns mTLS authentication immediately and ignores the signing key. To use `private_key_jwt`, you must omit `useMtls` or set it to false.

### How does the SDK handle PEM string keys versus CryptoKey objects for private_key_jwt?

**`#getClientAuth` automatically detects the key type and imports when necessary.** If `clientAssertionSigningKey` is a string, the method calls `importPKCS8()` with your specified algorithm (defaulting to RS256) to convert it to a WebCrypto `CryptoKey` before passing it to `client.PrivateKeyJwt()`. If you provide a `CryptoKey` directly, it skips the import step.

### Why does Auth0 prioritize mTLS over private_key_jwt?

**mTLS provides stronger authentication guarantees by binding the client identity to the TLS transport layer rather than application-layer tokens.** This prevents token theft and replay attacks, as the authentication is tied to the specific TLS session and certificate. The `private_key_jwt` method, while cryptographically sound, operates at the application layer where tokens could theoretically be extracted from logs or memory.

### Where is the client authentication logic implemented in the source code?

**The selection logic resides 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) (lines 1025–1054), while the concrete authentication factories are defined in [`packages/auth0-auth-js/src/client.ts`](https://github.com/auth0/auth0-auth-js/blob/main/packages/auth0-auth-js/src/client.ts).** The [`auth-client.ts`](https://github.com/auth0/auth0-auth-js/blob/main/auth-client.ts) file contains the `#getClientAuth` private method and its prioritization comment block, whereas [`client.ts`](https://github.com/auth0/auth0-auth-js/blob/main/client.ts) exports `TlsClientAuth()`, `PrivateKeyJwt()`, and `ClientSecretPost()` functions that create the actual authentication objects consumed by the OAuth client.