---
title: "Azure Key Vault ( Rest API)"
description: "Azure Key Vault is a cloud service for securely storing and managing cryptographic keys, secrets, and certificates. It provides a secure and reliable way to protect sensitive information and control access to keys used…"
stack: "Community Stack (open source) — version 0.21.0"
stack_version: "0.21.0"
stack_comparison: https://docs.walt.id/community-vs-enterprise.md
canonical_url: https://docs.walt.id/community-stack/issuer/key-management/azure-kms/rest-api
generated: 2026-07-20
---
# Azure Key Vault ( Rest API)

Azure Key Vault is a cloud service for securely storing and managing cryptographic keys, secrets, and certificates. It
provides a secure and reliable way to protect sensitive information and control access to keys used by cloud
applications and services.

## Prerequisites

- An Azure account with an active subscription. [Create an account](https://azure.microsoft.com/en-us/free/).
- An Azure Key Vault
  instance. [Create a Key Vault](https://docs.microsoft.com/en-us/azure/key-vault/quick-create-portal).
- An Azure AD application with access to the Key
  Vault. [Create an Azure AD application](https://docs.microsoft.com/en-us/azure/active-directory/develop/quickstart-register-app).

## Setup

1. **Create an Azure AD application** with access to the Key Vault. Note down the `Application (client) ID` and
   `Directory (tenant) ID`.
2. **Create a client secret** for the Azure AD application. Note down the `Client Secret`.
3. **Assign permissions** to the Azure AD application to access the Key Vault. Grant the `Key permissions` and
   `Secret permissions` to the application.
4. **Get the Key Vault URL**. Note down the `Key Vault URL` from the Azure portal.
5. **Configure the issuer API** to use the Azure Key Vault. Provide the `Key Vault URL`, `Application ID`, `Tenant ID`,
   and `Client Secret` in the issuer API configuration.
6. **Generate a key** in the Key Vault. Use the issuer API to generate a key in the Azure Key Vault.
7. **Sign and issue credentials** using the key stored in the Azure Key Vault.

## Key Generation

To create the key you can use the onboard endpoint provided by the issuer API and provide the necessary parameters
to create the key in the Azure Key Vault service.

#### Creation via Issuer API

**Option: Request**

**Endpoint:**
`/onboard/issuer` | [API Reference](https://issuer.demo.walt.id/swagger/index.html#/Issuer%20onboarding/post_onboard_issuer)

**Example Request**

```bash
curl -X 'POST' \
  'https://issuer.demo.walt.id/onboard/issuer' \
  -H 'accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
  "key": {
    "backend": "azure-rest-api",
    "keyType": "secp256r1",
    "config": {
       "auth": {
          "keyVaultUrl": "https://<key-vault-name>.vault.azure.net/",
          "clientId": "<application-id>",
          "tenantId": "<tenant-id>",
          "clientSecret": "<client-secret>"
      },
      "tags": {
        "key": "value"
      }
    }
  },
  "did": {
    "method": "jwk"
  }
}'
```

**Body**

```json
{
  "key": {
    "backend": "azure-rest-api",
    "keyType": "secp256r1",
    "config": {
      "auth": {
        "keyVaultUrl": "https://<key-vault-name>.vault.azure.net/",
        "clientId": "<application-id>",
        "tenantId": "<tenant-id>",
        "clientSecret": "<client-secret>"
      },
      "tags": {
        "key": "value"
      }
    }
  },
  "did": {
    "method": "jwk"
  }
}
```

**Body Parameters**

- `key`
    - `backend`: _String_ - Specifies the storage type of key. It can be `jwk` (managed by you), `azure` (managed
      by
      Azure Key Vault using Rest api requests ) and others. Learn more about different
      types [here](https://docs.walt.id/community-stack/issuer/key-management/overview.md).
    - `keyType`: _String_ - the algorithm used to generate the key. Supported Azure Key Vault values are `secp256r1`, `secp384r1`, `secp521r1`, `secp256k1`, `RSA`, `RSA3072`, and `RSA4096`. `Ed25519` is not supported.
    - `config`
        - `keyVaultUrl`: _String_ - The URL of the Azure Key Vault.
        - `clientId`: _String_ - The client ID of the Azure AD application.
        - `tenantId`: _String_ - The tenant ID of the Azure AD application.
        - `clientSecret`: _String_ - The client secret of the Azure AD application.
        - `tags`: _Object_ - The metadata tags to add to the key for [Azure](https://learn.microsoft.com/en-us/azure/azure-resource-manager/management/tag-resources)
- `did`:
    - `method`: _String_ - Specifies the DID method. It can be key, jwk, web, cheqd.

**Option: Response**

**Example Response**

The onboard/issuer endpoint will return an object containing both the generated key in JWK format and the related DID.

```json
{
  "issuerKey": {
    "type": "azure-rest-api",
    "id": "https://kv-nhd-vp-core-dev.vault.azure.net/keys/541693094/be4a95477f274b38826938a92f990fd5",
    "auth": {
      "keyVaultUrl": "https://<key-vault-name>.vault.azure.net/",
      "clientId": "<application-id>",
      "tenantId": "<tenant-id>",
      "clientSecret": "<client-secret>"
    },
    "_keyType": "secp256r1",
    "_publicKey": {
      "type": "jwk",
      "jwk": {
        "kty": "EC",
        "crv": "P-256",
        "kid": "https://kv-nhd-vp-core-dev.vault.azure.net/keys/541693094/be4a95477f274b38826938a92f990fd5",
        "key_ops": [
          "sign",
          "verify"
        ],
        "x": "gWLUzx_B-36rcSdwlf78IjCRqVzchZFj6ino_ueu1y8",
        "y": "dL6LiFRFDwSyQphljk5YB0gXGlB5eg8sPZV_m1DTl2o"
      }
    }
  },
  "issuerDid": "did:jwk:eyJrdHkiOiJFQyIsImNydiI6IlAtMjU2Iiwia2lkIjoiaHR0cHM6Ly9rdi1uaGQtdnAtY29yZS1kZXYudmF1bHQuYXp1cmUubmV0L2tleXMvNTQxNjkzMDk0L2JlNGE5NTQ3N2YyNzRiMzg4MjY5MzhhOTJmOTkwZmQ1Iiwia2V5X29wcyI6WyJzaWduIiwidmVyaWZ5Il0sIngiOiJnV0xVenhfQi0zNnJjU2R3bGY3OElqQ1JxVnpjaFpGajZpbm9fdWV1MXk4IiwieSI6ImRMNkxpRlJGRHdTeVFwaGxqazVZQjBnWEdsQjVlZzhzUFpWX20xRFRsMm8ifQ"
}
```

**Properties**

- `type`: _String_ - the type of key can be either "aws" when using AWS KMS or "jwk" when providing the key in
  full as JWK.
- `config`
    - `keyVaultUrl`: _String_ - The URL of the Azure Key Vault.
    - `clientId`: _String_ - The client ID of the Azure AD application.
    - `tenantId`: _String_ - The tenant ID of the Azure AD application.
    - `clientSecret`: _String_ - The client secret of the Azure AD application.
- `_publicKey` (optional): _Array_ - The public key can be fetched by the issuer API or directly provided, saving
  resources and reducing network requests.
- `_keyType` (optional): _String_ - The key type can be fetched by the issuer API or directly provided, saving resources
  and reducing network requests.
- `issuerDid`: _String_ - the DID of the issuer.

### Key Usage

Once you have successfully created a key that is one of the supported types listed above, you can use it in
sign and issue operations offered by the issuer API.

If you've already had a look at
our `/sign`, `/issue`, `/batchIssue`
endpoints, you have seen that they all follow a similar request body structure, where the key that should be
used for signing credentials is provided via the `issuerKey` property. Now instead of providing the key as JWK, we
provide
a reference to a key stored in Vault with the required parameters and access credentials.

Below you can see an example of
`issuerKey` object referencing a key stored in AWS.

**Option: Example IssuerKey Object**

```json 
{
  "issuerKey": {
    "type": "azure-rest-api",
    "id": "https://kv-nhd-vp-core-dev.vault.azure.net/keys/541693094/be4a95477f274b38826938a92f990fd5",
    "auth": {
      "keyVaultUrl": "https://<key-vault-name>.vault.azure.net/",
      "clientId": "<application-id>",
      "tenantId": "<tenant-id>",
      "clientSecret": "<client-secret>"
    },
    "_keyType": "secp256r1",
    "_publicKey": {
      "type": "jwk",
      "jwk": {
        "kty": "EC",
        "crv": "P-256",
        "kid": "https://kv-nhd-vp-core-dev.vault.azure.net/keys/541693094/be4a95477f274b38826938a92f990fd5",
        "key_ops": [
          "sign",
          "verify"
        ],
        "x": "gWLUzx_B-36rcSdwlf78IjCRqVzchZFj6ino_ueu1y8",
        "y": "dL6LiFRFDwSyQphljk5YB0gXGlB5eg8sPZV_m1DTl2o"
      }
    }
  },
  "issuerDid": "did:jwk:eyJrdHkiOiJFQyIsImNydiI6IlAtMjU2Iiwia2lkIjoiaHR0cHM6Ly9rdi1uaGQtdnAtY29yZS1kZXYudmF1bHQuYXp1cmUubmV0L2tleXMvNTQxNjkzMDk0L2JlNGE5NTQ3N2YyNzRiMzg4MjY5MzhhOTJmOTkwZmQ1Iiwia2V5X29wcyI6WyJzaWduIiwidmVyaWZ5Il0sIngiOiJnV0xVenhfQi0zNnJjU2R3bGY3OElqQ1JxVnpjaFpGajZpbm9fdWV1MXk4IiwieSI6ImRMNkxpRlJGRHdTeVFwaGxqazVZQjBnWEdsQjVlZzhzUFpWX20xRFRsMm8ifQ"
}
```

**Properties**

- `type`: _String_ - the type of key can be either "aws" when using AWS KMS or "jwk" when providing the key in
  full as JWK.
-
- `id`: _String_ - the ID of the key in the Transit Engine.
- `config`
    - `keyVaultUrl`: _String_ - The URL of the Azure Key Vault.
    - `clientId`: _String_ - The client ID of the Azure AD application.
    - `tenantId`: _String_ - The tenant ID of the Azure AD application.
    - `clientSecret`: _String_ - The client secret of the Azure AD application.
- `_publicKey` (optional): _Array_ - The public key can be fetched by the issuer API or directly provided, saving
  resources and reducing network requests.
- `_keyType` (optional): _String_ - The key type can be fetched by the issuer API or directly provided, saving resources
  and reducing network requests.

**Option: Example Issuance Request**

## Example Issuance Request

Below you can see example issuance request
to [`jwt/issue`](https://issuer.demo.walt.id/swagger/index.html#/Credential%20Issuance/post_openid4vc_jwt_issue) using
a key created in AWS kms to
sign the credential.

[Api Reference](https://issuer.demo.walt.id/swagger/index.html#/Credential%20Issuance/post_openid4vc_jwt_issue)

```bash
curl -X 'POST' \
  'https://issuer.demo.walt.id/openid4vc/jwt/issue' \
  -H 'accept: text/plain' \
  -H 'statusCallbackUri: https://example.com/$id' \
  -H 'Content-Type: application/json' \
  -d '{
  "issuerKey": {
    "type": "azure-rest-api",
    "id": "https://kv-nhd-vp-core-dev.vault.azure.net/keys/541693094/be4a95477f274b38826938a92f990fd5",
    "auth": {
      "keyVaultUrl": "https://<key-vault-name>.vault.azure.net/",
      "clientId": "<application-id>",
      "tenantId": "<tenant-id>",
      "clientSecret": "<client-secret>"
    },
    "_keyType": "secp256r1",
    "_publicKey": {
      "type": "jwk",
      "jwk": {
        "kty": "EC",
        "crv": "P-256",
        "kid": "https://kv-nhd-vp-core-dev.vault.azure.net/keys/541693094/be4a95477f274b38826938a92f990fd5",
        "key_ops": [
          "sign",
          "verify"
        ],
        "x": "gWLUzx_B-36rcSdwlf78IjCRqVzchZFj6ino_ueu1y8",
        "y": "dL6LiFRFDwSyQphljk5YB0gXGlB5eg8sPZV_m1DTl2o"
      }
    }
  },
  "issuerDid": "did:jwk:eyJrdHkiOiJFQyIsImNydiI6IlAtMjU2Iiwia2lkIjoiaHR0cHM6Ly9rdi1uaGQtdnAtY29yZS1kZXYudmF1bHQuYXp1cmUubmV0L2tleXMvNTQxNjkzMDk0L2JlNGE5NTQ3N2YyNzRiMzg4MjY5MzhhOTJmOTkwZmQ1Iiwia2V5X29wcyI6WyJzaWduIiwidmVyaWZ5Il0sIngiOiJnV0xVenhfQi0zNnJjU2R3bGY3OElqQ1JxVnpjaFpGajZpbm9fdWV1MXk4IiwieSI6ImRMNkxpRlJGRHdTeVFwaGxqazVZQjBnWEdsQjVlZzhzUFpWX20xRFRsMm8ifQ"
  "credentialData": {
    "@context": [
      "https://www.w3.org/2018/credentials/v1",
      "https://purl.imsglobal.org/spec/ob/v3p0/context.json"
    ],
    "id": "urn:uuid:THIS WILL BE REPLACED WITH DYNAMIC DATA FUNCTION (see below)",
    "type": [
      "VerifiableCredential",
      "OpenBadgeCredential"
    ],
    "name": "JFF x vc-edu PlugFest 3 Interoperability",
    ... 
  },
  "mapping": {
    "id": "<uuid>",
     ... 
  }
}'
```

**Header Parameters**

- `statusCallbackUri`: _URL_ - Receive updates on the created issuance process, e.g. when a credential was successfully
  claimed. The parameter expects a URL which can accept a JSON POST request. The URL can also hold a `$id`, which will
  be
  replaced by the issuance session id. For example: `https://myurl.com/$id`, `https://myurl.com`
  or `https://myurl.com/test/$id`
  <br/>
  <br />
  <details><summary>Expand To Learn More</summary>

  <br /> 

  **Body**

  The data send to the provided URL will contain a JSON body:
    - `id` : _String_ - the issuance session id
    - `type`: _String_ - the event type
    - `data`: _JsonObject_ - the data for the event

  **Event Types**

  Possible events (event types) and their data are:
    - `resolved_credential_offer` with the credential offer as JSON (in our Web Wallet: called when the issuance offer
      is
      entered into the wallet, but not processing / accepted yet)
    - `requested_token` with the issuance request for the token as json object (called for the token required to receive
      the
      credentials)

  Credential issuance (called for every credential that's issued (= requested from wallet))
    - `jwt_issue` with `jwt` being the issued jwt
    - `sdjwt_issue` with `sdjwt` being the issued sdjwt
    - `batch_jwt_issue` with `jwt` being the issued jwt
    - `batch_sdjwt_issue` with `sdjwt` being the issued sdjwt
    - `generated_mdoc` with `mdoc` being the CBOR (HEX) of the signed mdoc

  To allow for secure business logic flows, if a callback URL is set, and it cannot be reached, the issuance will not
  commence further (after that point). If no callback URL is set, the issuance logic does not change in any way.

  </details>

**Body**

As you can see for the property `issuerKey` we only provided the required parameters of the TSE Key Reference Object
described above and left out `_publicKey` and `_keyType`

```json
{
  "issuerKey": {
    "type": "azure-rest-api",
    "id": "https://kv-nhd-vp-core-dev.vault.azure.net/keys/541693094/be4a95477f274b38826938a92f990fd5",
    "auth": {
      "keyVaultUrl": "https://<key-vault-name>.vault.azure.net/",
      "clientId": "<application-id>",
      "tenantId": "<tenant-id>",
      "clientSecret": "<client-secret>"
    },
    "_keyType": "secp256r1",
    "_publicKey": {
      "type": "jwk",
      "jwk": {
        "kty": "EC",
        "crv": "P-256",
        "kid": "https://kv-nhd-vp-core-dev.vault.azure.net/keys/541693094/be4a95477f274b38826938a92f990fd5",
        "key_ops": [
          "sign",
          "verify"
        ],
        "x": "gWLUzx_B-36rcSdwlf78IjCRqVzchZFj6ino_ueu1y8",
        "y": "dL6LiFRFDwSyQphljk5YB0gXGlB5eg8sPZV_m1DTl2o"
      }
    }
  },
  "issuerDid": "did:jwk:eyJrdHkiOiJFQyIsImNydiI6IlAtMjU2Iiwia2lkIjoiaHR0cHM6Ly9rdi1uaGQtdnAtY29yZS1kZXYudmF1bHQuYXp1cmUubmV0L2tleXMvNTQxNjkzMDk0L2JlNGE5NTQ3N2YyNzRiMzg4MjY5MzhhOTJmOTkwZmQ1Iiwia2V5X29wcyI6WyJzaWduIiwidmVyaWZ5Il0sIngiOiJnV0xVenhfQi0zNnJjU2R3bGY3OElqQ1JxVnpjaFpGajZpbm9fdWV1MXk4IiwieSI6ImRMNkxpRlJGRHdTeVFwaGxqazVZQjBnWEdsQjVlZzhzUFpWX20xRFRsMm8ifQ"
  "credentialData": {
    "@context": [
      "https://www.w3.org/2018/credentials/v1",
      "https://purl.imsglobal.org/spec/ob/v3p0/context.json"
    ],
    "id": "urn:uuid:THIS WILL BE REPLACED WITH DYNAMIC DATA FUNCTION (see below)",
    "type": [
      "VerifiableCredential",
      "OpenBadgeCredential"
    ],
    "name": "JFF x vc-edu PlugFest 3 Interoperability",
    ...
  },
  "mapping": {
    "id": "<uuid>",
    ...
  }
}
```
