OpenID4VCI
OpenID for Verifiable Credential Issuance (OpenID4VCI) defines how an issuer offers credentials to a wallet and how the wallet retrieves them.
This page explains how to configure OpenID4VCI for issuing credentials.
- To configure a wallet to receive credentials, see OpenID4VCI and OpenID4VP for wallets
- For every supported parameter, see the configuration reference
Enable OpenID4VCI
To issue with OpenID4VCI, configure at least one enabled instance in the
issuanceProtocol object. The system supports one type:
OPENID4VCI_FINAL1: OpenID for Verifiable Credential Issuance 1.0
You can configure more than one instance of the same type, each with its own settings. When you create a credential, you choose which instance to issue it with. See URL scheme for a common reason to do this.
Example configuration
issuanceProtocol:
OPENID4VCI_FINAL1:
display: "exchange.openIdFinal1"
order: 1
type: "OPENID4VCI_FINAL1"
params:
public:
preAuthorizedCodeExpiresInSeconds: 300
tokenExpiresInSeconds: 86400
refreshExpiresInSeconds: 7776000
redirectUri:
enabled: true
allowedSchemes: ["https"]
webhookTask: "WEBHOOK1"
private:
encryption: "<32-byte hex>"
nonce:
signingKey: "<32-byte hex>"
expirationSeconds: 300
leewaySeconds: 60
dpop:
enforced: true
signingKey: "<32-byte hex>"
nonceValiditySeconds: 300
leewaySeconds: 60
signingAlgorithms: ["ECDSA"]
The sections below explain each part of this configuration.
Keys
Each OpenID4VCI instance needs its own keys:
nonce.signingKey: Signs the nonces the issuer generates during issuance. Required.encryption: Encrypts the access and refresh tokens Core receives from issuers when it holds credentials as a wallet. Required for every instance, even if you only use Core to issue.dpop.signingKey: Signs the nonces used in DPoP flows. Required ifdpop.enforcedistrue. See DPoP.
Keys are 32-byte hex strings. Supply them as environment variables rather than in configuration files. See Secrets and Keys for how to generate and supply keys, and what happens when you rotate them.
Nonces
OpenID4VCI uses nonces to make sure each credential request is fresh, which prevents replay attacks. Alongside the signing key, configure:
nonce.expirationSeconds: How long a nonce remains valid.nonce.leewaySeconds: Time tolerance when validating nonce timestamps, to allow for clock differences between systems.
Code and token lifetimes
These parameters control how long the codes and tokens in an issuance flow remain valid:
preAuthorizedCodeExpiresInSeconds: How long a pre-authorized code can be exchanged for an access token. Make this long enough for holders to complete their wallet interaction, but short enough to limit the risk of a leaked offer being used.tokenExpiresInSeconds: How long an access token can be used to retrieve credentials. Allow for network latency, retries, and how long your holders typically take.refreshExpiresInSeconds: How long a refresh token remains valid. As long as the wallet uses its refresh token before it expires, the wallet can obtain new access tokens and refresh a batch of credentials without repeating the full issuance flow, provided the credentials have not been suspended or revoked. A longer window is more convenient for holders but extends the lifetime of the original issuance tokens.
The validity period of the credentials themselves is set elsewhere. See Credential Expiration for Issuers.
DPoP
Demonstrating Proof of Possession (DPoP) binds the access tokens you issue to a key held by the wallet. A wallet must prove possession of that key each time it uses the token, so a stolen access token cannot be used by anyone else.
Configure DPoP with the following parameters:
dpop.enforced: Set totrueto require DPoP from wallets during issuance.dpop.signingKey: Signs the nonces used in DPoP flows. Required ifdpop.enforcedistrue.dpop.nonceValiditySeconds: How long a DPoP nonce remains valid.dpop.leewaySeconds: Time tolerance when validating DPoP nonce timestamps.dpop.signingAlgorithms: The key algorithms wallets can use for their DPoP key. OnlyECDSAis currently supported.
Redirect URIs
You can redirect holders to a URI after they accept your credential
offer. To allow this, set redirectUri.enabled to true and list the
URI schemes you accept in redirectUri.allowedSchemes, for example
https or myapp. If no schemes are listed, all redirect URIs are
rejected.
You then set the redirect URI for each credential when you create it.
URL scheme
Credential offers use the openid-credential-offer URL scheme, as
specified in the OpenID4VCI standard. To use a custom scheme instead,
set the urlScheme parameter.
To support more than one scheme at the same time, for example the standard scheme and a custom one, configure one instance for each scheme. When you create a credential, reference the instance whose scheme you want to use.
Webhooks
To send notifications for issuance events, set webhookTask to a
configured WEBHOOK_NOTIFY task. See Webhooks.