Signed Credential Issuer Metadata

Issuer2 can return its OpenID4VCI Credential Issuer metadata as a signed JWT. Signed metadata is available automatically for every Issuer2 service, using the same discovery endpoint as JSON metadata. Wallets can select the representation with the HTTP Accept header.

How It Works

  1. The client requests the Issuer2 Credential Issuer metadata endpoint.
  2. The client sends Accept: application/jwt.
  3. Issuer2 builds the current metadata and signs it with the private key referenced by the service's tokenKeyId.
  4. Issuer2 returns a compact JWS using the requested media type.

Rotating tokenKeyId changes the key used for subsequent metadata responses.

Prerequisites

Signed metadata reuses the Issuer2 service's existing tokenKeyId — the same key that signs OID4VCI access tokens — so no additional setup is required.

Request Signed Metadata

For an issuer whose identifier is:

https://{host}/v2/{target}/issuer-service-api/openid4vci

the Credential Issuer metadata URL is:

https://{host}/.well-known/openid-credential-issuer/v2/{target}/issuer-service-api/openid4vci
CURL

Endpoint: GET /.well-known/openid-credential-issuer/v2/{target}/issuer-service-api/openid4vci

Example Request
curl --request GET \
  'https://{orgID}.enterprise-sandbox.waltid.dev/.well-known/openid-credential-issuer/v2/{target}/issuer-service-api/openid4vci' \
  --header 'Accept: application/jwt'

Path Parameters

  • orgID: String (required) - Your organization ID, e.g. test.enterprise-sandbox.waltid.dev.
  • target: String (required) - The resource identifier of the issuer service, {organizationID}.{tenantID}.{issuerServiceID}.

Example Response
<protected-header>.<payload>.<signature>

The response has status 200, the requested Content-Type, and the singed Issuer Metadata.

JWT Structure

The protected header contains:

HeaderDescription
algJWS algorithm of the signing key.
typAlways openidvci-issuer-metadata+jwt.
kidKey ID of the signing key.
jwkPublic signing JWK.

The payload contains the complete JSON Credential Issuer metadata plus these JWT claims:

ClaimDescription
issThe credential_issuer identifier.
subThe credential_issuer identifier.
iatTime at which Issuer2 generated the signed response, as a Unix timestamp.

Issuer2 does not add an exp claim. A client that caches signed metadata should therefore apply its own refresh policy and respect HTTP caching controls.

Verify Signed Metadata

A consuming client should:

  1. Confirm that the HTTP Content-Type is the signed media type it requested.
  2. Parse the body.
  3. Reject alg: none and symmetric algorithms.
  4. Verify the signature with a trusted issuer key.
  5. Confirm that typ is openidvci-issuer-metadata+jwt.
  6. Confirm that iss, sub, and credential_issuer all equal the expected Issuer2 identifier.
  7. Evaluate iat against the client's freshness policy.
  8. Process the remaining payload fields as Credential Issuer metadata.

Verifying with only the JWK embedded in the same JWT proves internal integrity, but does not by itself establish that the key belongs to the expected issuer. Bind the key to trusted issuer configuration, a trusted key distribution mechanism, or another deployment-specific trust policy.

Unsigned JSON Metadata

Request JSON explicitly when a client does not support signed metadata:

curl --request GET \
  'https://{orgID}.enterprise-sandbox.waltid.dev/.well-known/openid-credential-issuer/v2/{target}/issuer-service-api/openid4vci' \
  --header 'Accept: application/json'

The signed JWT payload and JSON response are generated from the same current Credential Issuer metadata.

Last updated on August 18, 2026