# How `getTokenByClientCredentials` Differs from Other Token Retrieval Methods

> Discover how getTokenByClientCredentials uses OAuth 2.0 Client Credentials Grant for M2M authentication. Learn its unique approach compared to user-centric token retrieval methods.

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

---

**`getTokenByClientCredentials` implements the OAuth 2.0 Client Credentials Grant to obtain access tokens for machine-to-machine authentication without user involvement, unlike user-centric flows that require authorization codes or refresh tokens.**

The `auth0-auth-js` SDK provides multiple methods for obtaining access tokens, each designed for specific authentication scenarios. While most methods focus on user-centric flows, `getTokenByClientCredentials` serves a distinct purpose for server-to-server communication. Understanding these differences ensures you implement the correct OAuth 2.0 flow for your application's architecture.

## Architectural Comparison of Token Methods

The SDK offers several token retrieval strategies, each targeting different authentication contexts. The fundamental distinction lies in whether the flow involves a user or operates purely between machines.

| Method | Grant Type | User Context | Primary Use Case | Key Parameters |
|--------|------------|--------------|------------------|----------------|
| **`getTokenByClientCredentials`** | `client_credentials` | None | Machine-to-machine APIs | `audience`, optional `organization` |
| **`getTokenByCode`** | `authorization_code` | Required | User login (SPA, web, mobile) | `codeVerifier` (PKCE) |
| **`getTokenByRefreshToken`** | `refresh_token` | Required | Silent token renewal | `refreshToken`, optional `scope` |
| **`exchangeToken`** | Token Exchange (RFC 8693) | Context-dependent | Token delegation, vault scenarios | `subjectToken`, `subjectTokenType` |
| **`backchannelAuthenticationGrant`** | CIBA | Required | Decoupled authentication | `authReqId` |

### No User Context Required

Unlike `getTokenByCode` or `getTokenByRefreshToken`, `getTokenByClientCredentials` operates entirely without user interaction. In [`src/auth-client.ts`](https://github.com/auth0/auth0-auth-js/blob/main/src/auth-client.ts), the implementation creates a `URLSearchParams` object containing only `audience` and optional `organization` parameters, then forwards these to `client.clientCredentialsGrant(configuration, params)` [auth-client.ts#L913-L931](https://github.com/auth0/auth0-auth-js/blob/main/packages/auth0-auth-js/src/auth-client.ts#L913-L931).

### Fixed Grant Type

The method internally hardcodes `grant_type=client_credentials` through the underlying `clientCredentialsGrant` call. Other methods like `getTokenByCode` dynamically set `grant_type=authorization_code`, while `exchangeToken` supports multiple RFC 8693 exchange types. This fixed grant type simplifies the API surface but restricts the method to machine-to-machine scenarios only.

## Implementation Details

### Core Implementation

The `getTokenByClientCredentials` method resides in [`src/auth-client.ts`](https://github.com/auth0/auth0-auth-js/blob/main/src/auth-client.ts) and follows a consistent pattern with other token helpers while maintaining its unique characteristics:

```typescript
// src/auth-client.ts#L913-L931
async getTokenByClientCredentials(
  options: TokenByClientCredentialsOptions
): Promise<TokenResponse> {
  const params = new URLSearchParams();
  params.append('audience', options.audience);
  
  if (options.organization) {
    params.append('organization', options.organization);
  }

  try {
    return await this.client.clientCredentialsGrant(
      this.configuration, 
      params
    );
  } catch (error) {
    throw new TokenByClientCredentialsError(error);
  }
}

```

### Type Definitions

The method accepts `TokenByClientCredentialsOptions`, defined in [`src/types.ts`](https://github.com/auth0/auth0-auth-js/blob/main/src/types.ts) [types.ts#L185-L194](https://github.com/auth0/auth0-auth-js/blob/main/packages/auth0-auth-js/src/types.ts#L185-L194):

```typescript
interface TokenByClientCredentialsOptions {
  /**
   * The unique identifier of the target API you want to access.
   */
  audience: string;
  
  /**
   * The ID of the organization to log in to (optional).
   */
  organization?: string;
}

```

Notice the minimal parameter surface compared to `TokenByCodeOptions` or `TokenByRefreshTokenOptions`, reflecting the simplicity of the client credentials flow.

### Error Handling

Errors are wrapped in `TokenByClientCredentialsError`, defined in [`src/errors.ts`](https://github.com/auth0/auth0-auth-js/blob/main/src/errors.ts) [errors.ts#L64-L68](https://github.com/auth0/auth0-auth-js/blob/main/packages/auth0-auth-js/src/errors.ts#L64-L68):

```typescript
export class TokenByClientCredentialsError extends ApiError {
  constructor(cause: unknown) {
    super('token_by_client_credentials_error', cause);
  }
}

```

This follows the SDK's consistent error handling pattern, allowing developers to catch specific error types for different token retrieval failures.

## Practical Usage Examples

### Server-to-Server API Call

The primary use case involves backend services authenticating against protected APIs:

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

const authClient = new AuthClient({
  domain: 'my-tenant.auth0.com',
  clientId: 'YOUR_CLIENT_ID',
  clientSecret: 'YOUR_CLIENT_SECRET', // Required for client credentials
});

async function fetchServiceData() {
  // Obtain token representing the application itself
  const tokenResponse = await authClient.getTokenByClientCredentials({
    audience: 'https://api.myservice.com',
  });

  // Call protected API
  const response = await fetch('https://api.myservice.com/data', {
    headers: {
      Authorization: `Bearer ${tokenResponse.accessToken}`,
    },
  });

  return response.json();
}

```

### Contrast with User Authentication

For comparison, user-based flows require different parameters and contexts:

```typescript
// Authorization Code flow - requires user interaction and PKCE
async function handleUserLogin(callbackUrl: URL) {
  const tokenResponse = await authClient.getTokenByCode(callbackUrl, {
    codeVerifier: 'PKCE_VERIFIER_GENERATED_DURING_AUTHORIZE',
  });
  return tokenResponse.accessToken;
}

// Refresh Token flow - requires existing user session
async function renewUserAccess(refreshToken: string) {
  const tokenResponse = await authClient.getTokenByRefreshToken({
    refreshToken,
    audience: 'https://api.myservice.com',
    scope: 'read:data',
  });
  return tokenResponse.accessToken;
}

```

## Summary

- **`getTokenByClientCredentials`** implements the OAuth 2.0 Client Credentials Grant for machine-to-machine authentication, requiring only `audience` and optional `organization` parameters.
- **No user context** distinguishes it from `getTokenByCode`, `getTokenByRefreshToken`, and CIBA flows, making it ideal for backend services and background jobs.
- **Fixed grant type** internally sets `grant_type=client_credentials` through `client.clientCredentialsGrant` in [`src/auth-client.ts`](https://github.com/auth0/auth0-auth-js/blob/main/src/auth-client.ts) [auth-client.ts#L913-L931](https://github.com/auth0/auth0-auth-js/blob/main/packages/auth0-auth-js/src/auth-client.ts#L913-L931).
- **Minimal parameter surface** compared to user flows, with type definitions in [`src/types.ts`](https://github.com/auth0/auth0-auth-js/blob/main/src/types.ts) [types.ts#L185-L194](https://github.com/auth0/auth0-auth-js/blob/main/packages/auth0-auth-js/src/types.ts#L185-L194).
- **Specific error handling** via `TokenByClientCredentialsError` in [`src/errors.ts`](https://github.com/auth0/auth0-auth-js/blob/main/src/errors.ts) [errors.ts#L64-L68](https://github.com/auth0/auth0-auth-js/blob/main/packages/auth0-auth-js/src/errors.ts#L64-L68).

## Frequently Asked Questions

### What is the difference between getTokenByClientCredentials and getTokenByCode?

`getTokenByClientCredentials` implements the Client Credentials Grant for machine-to-machine scenarios without user involvement, requiring only an `audience` parameter. In contrast, `getTokenByCode` implements the Authorization Code Grant for user authentication, requiring an authorization `code` obtained after user login and a `codeVerifier` for PKCE validation.

### When should I use getTokenByClientCredentials instead of getTokenByRefreshToken?

Use `getTokenByClientCredentials` when your application needs to authenticate itself to access protected resources in server-to-server scenarios where no user is present. Use `getTokenByRefreshToken` when you have an existing user session with a valid refresh token and need to obtain a new access token without requiring the user to re-authenticate.

### What parameters are required for getTokenByClientCredentials?

According to the `TokenByClientCredentialsOptions` interface in [`src/types.ts`](https://github.com/auth0/auth0-auth-js/blob/main/src/types.ts) [types.ts#L185-L194](https://github.com/auth0/auth0-auth-js/blob/main/packages/auth0-auth-js/src/types.ts#L185-L194), only the `audience` parameter is required, specifying the unique identifier of the target API. The `organization` parameter is optional and used when requesting tokens for a specific organization context.

### How does error handling work for getTokenByClientCredentials?

Errors are wrapped in the `TokenByClientCredentialsError` class defined in [`src/errors.ts`](https://github.com/auth0/auth0-auth-js/blob/main/src/errors.ts) [errors.ts#L64-L68](https://github.com/auth0/auth0-auth-js/blob/main/packages/auth0-auth-js/src/errors.ts#L64-L68). This extends the base `ApiError` class and allows developers to catch specific client credentials failures separately from other token retrieval errors like `TokenByCodeError` or `TokenByRefreshTokenError`.