> For the complete documentation index, see [llms.txt](https://docs.payments.thalescloud.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.payments.thalescloud.io/dynamic-cvv/integrate-the-d1-api/get-oauth-2.0-access-token.md).

# Get OAuth 2.0 access token

D1 APIs use the OAuth 2.0 JWT bearer flow ([RFC 7523](https://datatracker.ietf.org/doc/html/rfc7523)).

Your issuer backend signs a JSON Web Token (JWT) and exchanges it for a D1 access token.

Use the D1 access token to call D1 APIs.

## Sequence Diagram

**Prerequisite**

* Issuer certificate exchanged with Thales
* Connectivity with mTLS in place

<figure><img src="/spaces/62lLFDcmLCeqqwmy4Fee/files/c4ZmHgF4sFtpl1QB5Kag" alt=""><figcaption><p>OAuth 2.0 JWT bearer flow between the issuer backend and the D1 backend.</p></figcaption></figure>

## Use the D1 access token

All issuer backend to D1 backend APIs require a D1 access token.

Send it in the `Authorization` header using the `Bearer` scheme:

`Authorization: Bearer <Base64_Encoded_JWT>`

The D1 access token is valid for 15 minutes.

Reuse the token until it expires.

Do not call `/oauth2/token` before every D1 API call.

## JWT assertion

The `/oauth2/token` API expects a JWT assertion ([RFC 7519](https://datatracker.ietf.org/doc/html/rfc7519)).

Your issuer backend must generate a valid JWT and sign it.

You can:

* Generate JWTs using an identity provider (for example, Keycloak).
* Generate JWTs in your issuer backend.

In both cases, provision the public key used for signature verification in the D1 backend.

If you do not use an identity provider, generate the key pair and JWTs as described below.

### Supported algorithms

Only JWTs signed with `ES256` are supported ([RFC 7518](https://datatracker.ietf.org/doc/html/rfc7518)).

D1 uses asymmetric cryptography.

The D1 backend stores only public keys.

### JWT format

A JWT consists of three parts separated by dots (.):

* Header
* Payload
* Signature

Therefore, a JWT typically looks like the following: `hhhhhhh.pppppppp.ssssssssss`

### Header

The header part contains the algorithm to use and the type of token to generate.

`kid` is required.

The D1 backend uses it to select the correct public key.

Header example:

```json
{
  "alg": "ES256",
  "typ": "JWT",
  "kid": "your_tenant_key_id"
}
```

### Payload

The payload supports the following claims:

| Claim | Type    | Required | Description                                                                                                                                                             |
| ----- | ------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `iss` | string  | Yes      | Use the issuerId provided during D1 onboarding. D1 uses it to look up the provisioned public key. If you use an aggregator model, set this to the aggregatorId.         |
| `sub` | string  | Yes      | Use the issuerId. (In case of aggregator, this value is equal to the aggregatorId.)                                                                                     |
| `exp` | integer | Yes      | Expiration time in UTC epoch seconds. Maximum value is current time + 15 minutes.                                                                                       |
| `aud` | string  | No       | D1 authorization server base URL. Use the URL for your target environment: Sandbox = `https://api.d1-stg.thalescloud.io`, Production = `https://api.d1.thalescloud.io`. |

{% hint style="info" %}
D1 enforces the maximum expiration period. If `exp` exceeds the allowed window, D1 rejects the request.
{% endhint %}

#### **Payload example**

```json
{
  "iss": "your_issuer_id",
  "sub": "your_user_for_audit",
  "exp": 1545222654,
  "aud": "https://api.d1.thalescloud.io"
}
```

### Signature

The signature is computed over the Base64URL-encoded header and payload.

The three JWT parts are joined using dots (`.`).

### Generate the key pair

Use OpenSSL to generate a P-256 key pair:

Generate a private key for the issuer backend.

Protect it in your environment.

```bash
openssl ecparam -name prime256v1 -genkey -noout -out issuerId-jwt-priv-key.pem
```

Generate a public key to provision in the D1 backend.

```bash
openssl ec -in issuerId-jwt-priv-key.pem -pubout > issuerId-jwt-pub-key.pem
```

The issuer backend uses the private key to sign JWTs.

The D1 backend uses the public key (and its `kid`) to verify JWT signatures.

Share the public key and `kid` with the Thales Delivery Team during D1 Onboarding.

### Generate the JWT

There are many ways to generate JWTs.

This example uses the `jose` Node.js library:

```js
/*
Please install *jose* library in your project.
https://www.npmjs.com/package/jose

For this example we use 3.19.0
*/
const { SignJWT } = require("jose/jwt/sign");
const { createPrivateKey } = require("crypto");

const alg = "ES256";
const kid = "your_tenant_key_id";
const iss = "your_issuer_id";
const aud = "your_audience";
const expirationTime = "3mins";
const sub = "our_user_for_audit";

const privateKeyPem = `-----BEGIN EC PRIVATE KEY----- 
MHcCAQEEILlIXMnH1if8EuWykPmWw/LyXZuoNVCzMp3Yhbj9/sEUoAoGCCqGSM49 
AwEHoUQDQgAE6swczLIRn/lPxQPpdUb2pHjCr0YeC02lkG7vMmqCNpalwIQSl+TR 
fZVDwCKJmajRgK3+n5SyAgCp4oH8qNluwQ==
-----END EC PRIVATE KEY-----`;

async function generateJwt() {
  const privateKey = createPrivateKey(privateKeyPem);

  console.log(
    await new SignJWT({})
      .setProtectedHeader({ alg, kid })
      .setIssuedAt()
      .setIssuer(iss)
      .setAudience(aud)
      .setExpirationTime(expirationTime)
      .setSubject(sub)
      .sign(privateKey)
  );
}

(async () => {
  await generateJwt();
})();
```

Example JWT output:

```shellscript
eyJhbGciOiJFUzI1NiIsImtpZCI6InlvdXJfdGVuYW50X2tleV9pZCJ9.eyJpYXQiOjE2MzYwMzMxODYsImlzcyI6InlvdXJfaXNzdWVyX2lkIiwiYXVkIjoieW91cl9hdWRpZW5jZSIsImV4cCI6MTYzNjAzMzM2Niwic3ViIjoib3VyX3VzZXJfZm9yX2F1ZGl0In0.lgVzN8k9IGcv1s-FZACpEyVxXcS9LAh4ahY3DO5Fg6MRl-Twa_wVAfw_Oe0XiH1Am-RFfafgDrepNi3Jz05Gvg
```


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.payments.thalescloud.io/dynamic-cvv/integrate-the-d1-api/get-oauth-2.0-access-token.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
