PingOne Platform APIs

OpenID for Verifiable Credential Issuance Offers

The credentials service supports the OpenID for Verifiable Credential Issuance (OpenID4VCI) standard. By adhering to standards, Ping delivers the following values:

  • Interoperability: Enables seamless credential issuance across different identity wallets and verification platforms that support OpenID4VCI.

  • Enhanced Privacy: Minimizes unnecessary exposure of user data by allowing for selective disclosure via SD-JWT.

  • Regulatory Compliance: Aligns with OAuth 2.0, OpenID Connect, and W3C Verifiable Credential standards, supporting GDPR and other privacy regulations.

To use OpenID4VCI to issue a credential to a user, two conditions must be met:

  1. You must create a verifiable credential for the user either with an issuance rule, for credential types with management.mode of AUTOMATIC, or directly creating a user credential, for credential types with management.mode of MANAGED. The credential remains queued until retrieved by the user.

  2. You must create a workflow that notifies the user of the credential and that enables the user to retrieve the credential offer. For example, the workflow can be a DaVinci flow or a web app that interacts with the user. Your use case determines how your user interacts with your issuance application.

After those conditions are met, your workflow has your PingOne Worker App call Initiate OpenID4VCI Offers that returns the OpenID4VCI offer details. That credential offer is valid for 30 minutes. The user’s wallet must call the credentialOfferUrl.href endpoint to initiate the OpenID4VCI flow. Your workflow must induce the user’s wallet to start the OpenID4VCI flow, and the credential offer includes two methods:

  • qrCode.href: A base64 encoded PNG image of a QR Code that contains the openid-credential-offer URL. This can be embedded in a web view and shown to a user to be scanned by their mobile phone, which will open the wallet app and start the OpenID4VCI flow.

  • openid-credential-offer.href: A link with an openid-credential-offer scheme that a wallet will understand. If that link is read by the phone, clicked in an email or text message, or a page in the mobile browser, it will open the wallet app and start the OpenID4VCI flow.

When the wallet app follows that link, it communicates directly with the credential service to transfer the credential using the OpenID4VCI protocol. The wallet first requests the credential issuer metadata and then requests the credentials offered and available authentication methods. At this point, the OpenID4VCI protocol requires that the wallet (the user) authenticate with the credential issuer. How the user authenticates depends on the credential issuer’s configuration and how you choose to implement it.

The OpenID4VCI protocol supports two authentication methods: authorization_code and urn:ietf:params:oauth:grant-type:pre-authorized_code:

  • The authorization_code method requires the user to authenticate with the credential issuer, typically by entering their username and password. If the user initiates your workflow on their desktop, they might authenticate to the workflow to begin. When the workflow later transfers control to the wallet, the wallet must also authenticate because it is a different device. Repeating authentication is not an ideal user experience.

  • The pre-authorized_code method does not require the user to authenticate again with the credential issuer. The user authenticates to begin your workflow. However, when the user transfers control to the wallet, the credential issuer provides a pre-authorized code to the wallet, which the wallet can use to request the credentials without requiring the wallet to authenticate again.

After the wallet authenticates, the wallet and the credentials service continue with the OID4VCI protocol to deliver the queued credentials requested by the user to the wallet.

Use of NATIVE protocol and OID4VCI protocol are not mutually exclusive. If a user has a wallet with the PingOne Wallet SDK that uses NATIVE and another wallet that uses OID4VCI, you can issue a credential to both wallets using their respective protocols.

OpenID4VCI Credentials Issuance Offers data model

Property Type Required? Mutable? Description

_links.credentialOfferUrl.href

String

N/A

Read-only

The same URL from the response body credentialOfferUrl.

_links.environment.href

String

N/A

Read-only

URL to retrieve more information about the environment for this credential offer.

_links.openid-credential-offer.href

String

N/A

Read-only

Credential offer URL using the openid-credential-offer URI scheme defined in the standard. This can be used to trigger the mobile OS opening a Wallet app that supports this scheme.

_links.qrCode.href

String

N/A

Read-only

A base64 encoded PNG image of a QR Code that contains the openid-credential-offer URL. This can be embedded in a web view and shown to a user to be scanned by their mobile phone.

_links.self.href

String

N/A

Read-only

URL to return this same response.

_links.user.href

String

N/A

Read-only

URL to retrieve information about the user associated with this credential offer.

createdAt

String

Required

Immutable

The timestamp indicating when the credential offer was created.

grantTypes

String[]

Optional

Mutable

Array of strings that indicate allowable code grant types for this credential issuance. Can be authorization_code, the default, or urn:ietf:params:oauth:grant-type:pre-authorized_code.

credentials

String[]

Optional

Mutable

Indicates the list of credentials to be issued. If not provided, all credentials for the user will be provisioned.

credentialOfferUrl

String

Required

Immutable

URL to show or send to the wallet to start the OpenID4VCI flow in the wallet. This URL will use the environment’s custom domain if one is configured.

environment.id

String

N/A

Read-only

Identifier (UUID) of the environment this credential offer belongs to. A credential offer is valid for 30 minutes.

expiresAt

String

Required

Immutable

The timestamp indicating when the credential offer expires. Credential offer is valid for 30 minutes.

id

String

Required

Immutable

The unique identifier (UUID) for the credential offer.

requiredScopes

String[]

Optional

Mutable

Indicates the list of OAuth 2.0 scopes required for the credential issuance. The wallet must receive and use an access token that contains these scopes when requesting the credentials.

status

String

Required

Immutable

The current status of the credential offer. Can be CREATED, the credential offer has been created but the user has not received any credentials yet; ISSUING, the credential offer is for multiple different credential types and at least one credential but not all credentials have been provisioned; or COMPLETED: the credential offer has been fully provisioned.

user.id

String

N/A

Read-only

Identifier (UUID) of the user associated with this credential offer.

OpenID4VCI Offers errors

In addition to the general error codes, OpenID4VCI offer operations can return the following errors:

HTTP status Top‑level code Detail code When it happens and what the response contains

400

INVALID_DATA

EMPTY_VALUE

Message: Validation Error : [<property> <message>]

When and details

When: A POST /users/{userID}/openid4vciOffers request supplies a credentials entry that is null, including an empty-string entry, which is reported as null after deserialization

Details: must not be null for the null credentials entry (for example Validation Error : [credentials[0] must not be null])

400

INVALID_DATA

INVALID_VALUE

Message: The request could not be completed. One or more validation errors were in the request.

When and details

When: A POST /users/{userID}/openid4vciOffers request supplies an empty credentials array, an empty grantTypes array, or a grantTypes entry that is not authorization_code or urn:ietf:params:oauth:grant-type:pre-authorized_code

Details: must not be empty for the credentials property, grantTypes cannot be empty for the grantTypes property, or unsupported grant types: [<unsupported grant types>] for the grantTypes property

400

INVALID_DATA

INVALID_VALUE

Message: The request could not be completed. One or more validation errors were in the request.

When and details

When: A POST /users/{userID}/openid4vciOffers request references a credentials[<index>] identifier that is not a user credential of that user, or a user credential whose credential type does not support OpenID4VCI

Details: credential for ID <credentialID> not found or credential for ID <credentialID> does not support OID4VCI, reported against the credentials[<index>] entry

400

INVALID_DATA

INVALID_VALUE

Message: The request could not be completed. One or more validation errors were in the request.

When and details

When: The environment does not have the capability to use PingOne Credentials

Details: Environment does not have capability to use credentials

400

INVALID_REQUEST

INVALID_VALUE

Message: The request could not be completed. The request was malformed or invalid.

When and details

When: A path identifier cannot be parsed as a UUID, or the request body cannot be deserialized as JSON, such as a credentials entry that is not a UUID or a property with the wrong JSON type

Details: For a JSON field conversion error, the target is the field path and the detail message is Invalid value for attribute.. Otherwise no detail is returned

400

REQUEST_FAILED

CONSTRAINT_VIOLATION

Message: The request could not be completed. There was an issue processing the request.

When and details

When: A POST /users/{userID}/openid4vciOffers request is made for a user who has no queued user credentials whose credential type supports OpenID4VCI

Details: user does not have any Credentials that support OpenID4VCI

401

None

None

Message: None; the body contains only an error field

When and details

When: An OpenID4VCI protocol endpoint (openid4vci/credential or openid4vci/notification) rejects the access token; these endpoints return a standard OAuth 2.0 error response instead of the general error codes

Details: invalid_token for a missing or incorrect user or environment ID in the access token, or insufficient_scope when the access token does not contain the offer’s required scopes

403

ACCESS_FAILED

INSUFFICIENT_PERMISSIONS

Message: The request could not be completed. You do not have access to this resource.

When and details

When: The caller has the operation permission but lacks population-level or group-level access to the target user and is not an environment-level administrator (applies to both offer operations, which are gated by the user access enforcer)

Details: Insufficient permissions to access this user resource

403

ACCESS_FAILED

None

Message: The actor attempting to perform the request is not authorized.

When and details

When: The actor lacks the credentialsIssuance:create:openid4vciOffer permission (POST) or the credentialsIssuance:read:openid4vciOffer permission (GET)

Details: None

404

NOT_FOUND

None

Message: The request could not be completed. The requested resource was not found.

When and details

When: A GET /users/{userID}/openid4vciOffers/{offerID} request references an offer that does not exist or belongs to a different user, or the request is made for an environment that has no credential issuer profile, or the target user does not exist in the directory (the user access enforcer and issuer lookup run before the operation)

Details: None

500

UNEXPECTED_ERROR

None

Message: There was an unexpected error with the service. Please try again later.

When and details

When: The service encounters an internal error while processing the request.

Details: None