Verify a Credential (OID4VP)
Build an OID4VP presentation request, receive the vp_token, and validate it.
Verify a Credential walks through the OID4VP authorization flow: building the presentation request, redirecting the user to Proof, and validating the response.
Proof's presentation endpoint is documented in the API reference:
GET https://api.proof.com/verifiable-credentials/v1/presentation/authorize
This is a standard OAuth 2.0 authorization request extended with OID4VP parameters.
Flow
- Redirect. The application constructs the authorization URL and redirects the user to Proof.
- Authenticate. Proof authenticates the user against their Cloud Wallet. If the user has not enrolled, Proof initiates identity verification.
- Consent. Proof shows the user which claims are being requested and by whom.
- Build presentation. On consent, Proof constructs the
vp_tokenwith only the requested disclosures and a Key Binding JWT. - Callback. Proof redirects the user back to the registered
redirect_uriwith thevp_tokenin the URL fragment.
Authorization request
| Parameter | Type | Description | |
|---|---|---|---|
response_type | String | Required | Must be vp_token. |
client_id | String | Required | The Proof OAuth Application Client ID. |
redirect_uri | String | Required | The callback URL where the user is returned. Must match a registered URI. |
scope | String | Required | Space-separated list of scopes that translate to DCQL queries. See Scopes and claims below. |
login_hint | String | Required | The email address associated with the end-user. |
nonce | String | Required | Cryptographically random string of at least 16 characters. Bound into the Key Binding JWT to prevent replay. |
state | String | Optional | Opaque value to maintain state between request and callback. Returned unmodified. |
transaction_data | String | Optional | Space-separated base64url-encoded JSON objects to bind into the presentation. See Transaction Data Templates. |
Example:
GET /verifiable-credentials/v1/presentation/authorize?
response_type=vp_token
&client_id=your_client_id
&redirect_uri=https://app.example.com/callback
&scope=urn:proof:params:scope:verifiable-credentials:basic
&[email protected]
&nonce=n-0S6_WzA2Mj_6a8bRs2TU
&state=af0ifjsldkj
The URL is shown with line breaks for readability. In production, the URL must be a single line with no whitespace.
Scopes and claims
Each scope maps to a predefined set of selective disclosures included in the Verifiable Presentation. Pass one or more scopes in the scope parameter to control which claims are requested.
| Scope | Selective disclosures |
|---|---|
urn:proof:params:scope:verifiable-credentials:basic | given_name, family_name, age_equal_or_over.18 |
Each disclosure corresponds to an attribute documented in Verifiable Credential Types.
Transaction data
For Signing Transactions use cases, attach transaction_data to bind specific terms into the presentation. Each transaction_data value is a base64url-encoded JSON object:
{
"type": "urn:proof:params:vc:transaction-data:wire-instructions:v1",
"credential_ids": ["proof_credential"],
"payload": { /* template-specific payload */ }
}| Property | Type | Description | |
|---|---|---|---|
type | String | Required | A supported transaction data type. |
credential_ids | String[] | Required | Credential query IDs this transaction data applies to. |
payload | Object | Required | Type-specific data to bind into the presentation. |
The full catalog of supported types and their payload shapes is in Transaction Data Templates.
Authorization response
After authentication and consent, Proof redirects the browser back to the registered redirect_uri. The response parameters are appended as a URL fragment.
REDIRECT https://app.example.com/callback#vp_token=...&state=...
| Parameter | Type | Description | |
|---|---|---|---|
vp_token | String | Always | The SD-JWT VC presentation. |
state | String | Conditional | Returned if a state value was provided in the request. |
The vp_token is a tilde-delimited string: the Issuer-Signed JWT, the disclosures, and the Key Binding JWT. The full anatomy is documented in SD-JWT VC Format.
Validation
Validating the vp_token involves the following checks. Most SD-JWT VC libraries handle the first two in a single call.
- Issuer signature. Validate the SD-JWT VC signature using the public key from Proof's JWKS, matched by
kid. - Disclosures. Confirm each disclosure hashes to a digest in the credential's
_sdarray. - Key Binding JWT. Verify the KB-JWT signature with
cnf.jwkfrom the credential. Confirmnonce,aud,iat, andsd_hashare correct. - Certificate chain. Walk the
x5cchain in the JWT header up to Proof Root CA R1 in your trust store. See Proof Certificate Authority.
For Signing Transactions presentations, additionally verify the transaction_data hash in the Key Binding JWT matches the canonicalized JSON of the original terms.
Together, those checks ensure the vp_token is cryptographic proof that Proof issued the credential, the verified Holder consented, and (for Signing Transactions) the original terms remain unchanged.
Suggested libraries:
- JavaScript: @sd-jwt/core.
- Python: sd-jwt.
Both libraries handle the SD-JWT envelope, disclosure verification, and KB-JWT validation in one call. Pair with the language's standard X.509 library to walk the certificate chain to Proof Root CA R1.
Errors
For OAuth 2.0 error responses returned via the redirect, see the OID4VP error specification.
See also: SD-JWT VC Format · Transaction Data Templates · Proof Certificate Authority
Updated about 2 hours ago