# JWT bearer

Commerce Layer, through OAuth2, provides the support of token exchange in the *on-behalf-of* (delegation) scenario which allows, for example, to make calls on behalf of a user and get an access token of the requesting user without direct user interaction. **Sales channels** and **webapps** can accomplish it by leveraging the JWT Bearer flow, which allows a client application to obtain an access token using a JSON Web Token (JWT) *assertion*.

{% hint style="info" %}
By [including a scope](https://docs.commercelayer.io/core/authentication/..#authorization-scopes) in the access token request, all the resources that you fetch are automatically filtered.
{% endhint %}

{% hint style="warning" %}
The JWT bearer flow is available **for enterprise plans only**.
{% endhint %}

At a high level, the JWT bearer token authorization grant follows the steps listed below:

1. **Obtaining a JWT assertion** — The client application [creates a JWT assertion](#creating-the-jwt-assertion), which is a digitally signed JSON object containing information about the client and the user on whose behalf the access token is being requested. This JWT assertion can include information such as the issuer (typically the client), the owner (the user on whose behalf the request is made), expiration time, and any other relevant claims. Custom claims can also be added.
2. **Requesting an access token** — The client [sends a token request](#getting-an-access-token) to the Commerce Layer authorization endpoint, including the JWT assertion as part of the request. This request must include the grant type indicating it's a JWT bearer token request, the assertion itself, and any additional parameters required.
3. **Validating the JWT assertion** — Commerce Layer decodes the JWT assertion without verifying its signature but [ensuring its integrity](#invalid-assertions) (e.g. checking that the assertion is well-formed and not too big, that the user exists and that the client is authorized to request an access token on behalf of the specified user).
4. **Issuing an access token** — If the JWT assertion is valid, Commerce Layer Auth API issues an access token to the client application. This access token represents the authorization granted to the client to access Commerce Layer resources on behalf of the user specified in the JWT assertion.
5. **Using the access token** — The client application can now use the access token to make authorized requests to Commerce Layer resources endpoints on behalf of the user, provided that the token has not expired or been [revoked](https://docs.commercelayer.io/core/authentication/revoking-a-token).

## Creating the JWT assertion

The assertion parameter must contain a single JWT encoded with an algorithm of your choice. Populate the `https://commercelayer.io/claims` object with the keys you need to pass all the desired information, such as:

* `owner` — the customer or user you want to make the calls on behalf of.
* `custom_claim` — any other information (key/value pairs) you want to enrich the token with.

<pre class="language-json"><code class="lang-json">{
<strong>  "https://commercelayer.io/claims": {
</strong><strong>    "owner": {
</strong>      "type": "Customer",
      "id": "zxcVBnMASd"
    },
<strong>    "custom_claim": {
</strong>      "foo": "bar"
    }
  },
  "iat": 1707238036,
  ...
}
</code></pre>

### Invalid assertions

The provided assertion is decoded without verifying its signature. Anyway, the [token request](#getting-an-access-token) will fail if the assertion is malformed or doesn't meet specific requirements. For example, the API will return a `400 Bad request` error:

* If the provided assertion resource owner doesn't exist.
* If the JWT assertion byte size is too big (the maximum allowed size is **4KB**).

## Getting an access token

To get an access token using the `urn:ietf:params:oauth:grant-type:jwt-bearer` grant type, send a `POST` request to the `/oauth/token` endpoint, passing the API client credentials in the request body.

{% hint style="warning" %}
For security reasons, the JWT bearer flow requires a client secret, even for sales channels.&#x20;
{% endhint %}

### Request

**POST** <https://auth.commercelayer.i&#x6F;**/oauth/token>\*\*

### Arguments

| Body parameter      | Type   | Required | Description                                                                           |
| ------------------- | ------ | -------- | ------------------------------------------------------------------------------------- |
| **`grant_type`**    | String | Required | `urn:ietf:params:oauth:grant-type:jwt-bearer`                                         |
| **`client_id`**     | String | Required | Your client ID (from your API credentials).                                           |
| **`client_secret`** | String | Required | Your client secret (from your API credentials).                                       |
| **`scope`**         | String | Optional | Your access token scope (market, stock location).                                     |
| **`assertion`**     | String | Required | A single JSON Web Token ([learn more](#creating-the-jwt-assertion)). Max size is 4KB. |

### Examples

#### Sales channel

{% tabs %}
{% tab title="Request" %}
The following request tries to get an access token for a sales channel API client on behalf of the customer identified by the ID "zxcVBnMASd", using the JWT bearer grant type with the [assertion](#creating-the-jwt-assertion) above:

<pre class="language-sh"><code class="lang-sh">curl -g -X POST \
  'https://auth.commercelayer.io/oauth/token' \
  -H 'Accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
<strong>  "grant_type": "urn:ietf:params:oauth:grant-type:jwt-bearer",
</strong><strong>  "client_id": "{{your_client_id}}",
</strong><strong>  "client_secret": "{{your_client_secret}}",
</strong><strong>  "assertion": "{{your_jwt_assertion}}"
</strong>}'
</code></pre>

{% endtab %}

{% tab title="Response" %}
On success, the API responds with a `200 OK` status code, returning the requested access token and owner info, along with a [refresh token](https://docs.commercelayer.io/core/refresh-token#sales-channel):

<pre class="language-json"><code class="lang-json">{
<strong>    "access_token": "acC3sSt0K3Nwrt6kic7.abc4bnm5...",
</strong>    "token_type": "bearer",
    "expires_in": 7200,
<strong>    "refresh_token": "r3fResHt0k3nvbn7mnr9ert123",
</strong>    "scope": "market:all",
    "created_at": 123456789,
<strong>    "owner_id": "zxcVBnMASd",
</strong><strong>    "owner_type": "customer"
</strong>}
</code></pre>

{% endtab %}
{% endtabs %}

The issued token's payload will have the following structure:

<pre class="language-json"><code class="lang-json">{
  "organization": {
    "id": "mzRmbZFPyO",
    "slug": "your-org-slug",
<strong>    "enterprise": true,
</strong>    "region": "eu-west-1"
  },
  "application": {
    "id": "jpYdqiDvMJ",
    "client_id": "cL13nT1Df7f7619d235e4d94b9ab",
<strong>    "kind": "sales_channel",
</strong>    "public": true,
    "confidential": true
  },
  "custom_claim": {
    "foo": "bar"
  },
<strong>  "owner": {
</strong><strong>    "id": "zxcVBnMASd",
</strong><strong>    "type": "Customer"
</strong><strong>  },
</strong>  "scope": "market:all",
  "exp": 1708098399,
  "test": true,
  "rand": 0.3594449293000671,
  "iat": 1707493599,
  "iss": "https://auth.commercelayer.io"
}
</code></pre>

### JWT single sign-on

Commerce Layer lets you authenticate users in your systems and use SSO with JWT so that a user is automatically verified with an identity provider of your choice (such as Auth0, Okta, or even a custom one) when they sign in. To do that you can leverage the JWT bearer flow with the correct assertion.

{% hint style="warning" %}
The customer must exist (or be created) in Commerce Layer. In order to use a [customer token](https://docs.commercelayer.io/core/authentication/password) to manage registered customers, make sure that you have defined a password for the [customer](https://app.gitbook.com/s/RWJeylueWkzLadK710XZ/customers) in Commerce Layer. Otherwise, some customer account functionalities may be unavailable (e.g. payment methods won't be saved in the customer wallet and cannot be reused). For security reasons, we strongly recommend choosing strong/random passwords.
{% endhint %}

{% hint style="info" %}
This feature is available **for enterprise plans only**. Read [this blog post](https://commercelayer.io/blog/single-sign-on-with-commerce-layer-using-next-js-and-auth0) to see an example of how to implement SSO with Commerce Layer, using Auth0 and Next.js.
{% endhint %}

{% embed url="<https://commercelayer.io/blog/single-sign-on-with-commerce-layer-using-next-js-and-auth0>" %}
