OID4VP
OID4VP
Section titled “OID4VP”Standards
Section titled “Standards”- OpenID for Verifiable Presentations 1.0 (final)
- OAuth 2.0 Authorization Framework (request/response parameter model)
- JOSE (JWT/JWS/JWE processing for request objects and
direct_post.jwt) - DID Core / did:web (for
decentralized_identifierclient_id scheme handling) - RFC 5280 / PKIX (X.509 certificate chain validation for
x509_san_dns)
Available Flows
Section titled “Available Flows”| Flow ID | Name | Steps | Description |
|---|---|---|---|
oid4vp-direct-post | DCQL + direct_post | 4 | Verifier creates signed request object, wallet fetches from request_uri, posts vp_token + state to response_uri, verifier validates and evaluates policy |
oid4vp-direct-post-jwt | DCQL + direct_post.jwt | 4 | Verifier creates signed request, wallet fetches from request_uri, posts encrypted JWE containing signed oauth-authz-resp+jwt, verifier decrypts and evaluates policy |
Demo Scenarios
Section titled “Demo Scenarios”- DCQL direct_post — Create request object, hand off to wallet, evaluate verifier policy
- DCQL direct_post.jwt — Same flow with encrypted response transport and inner JWT validation
Wallet Credential Profile Matching
Section titled “Wallet Credential Profile Matching”The Looking Glass OID4VP controls preflight the selected VC credential profile against the DCQL preset before wallet submission. If the preset requests dc+sd-jwt, jwt_vc_json, jwt_vc_json-ld, or ldp_vc, the wallet auto-issue profile must issue one of those formats. Otherwise the wallet action is blocked with an explanation, because the wallet cannot build a matching vp_token from the selected profile.
When a credential_jwt is pasted manually, the UI allows submission but warns when the selected auto-issue profile does not match the DCQL format. The wallet and verifier still validate the actual credential and will reject the presentation if the credential evidence does not satisfy the request.
Example DCQL Query
Section titled “Example DCQL Query”Example DCQL query requesting a university_degree credential with degree and graduation_year claims:
{ "credentials": [{ "id": "university_degree", "claims": [ { "path": ["degree"] }, { "path": ["graduation_year"] } ], "meta": { "vct_values": ["https://protocolsoup.com/credentials/university_degree"] } }]}Request and Response Contracts
Section titled “Request and Response Contracts”- Authorization request enforces XOR: exactly one of
dcql_queryorscope. - For
response_modedirect_postanddirect_post.jwt,response_uriis required andredirect_urimust be absent. - Request object header
typmust beoauth-authz-req+jwt. - VP token header
typmust bevp+jwt. direct_post.jwtinner response headertypmust beoauth-authz-resp+jwt.
Client ID Schemes
Section titled “Client ID Schemes”OpenID4VP defines multiple client identification schemes. ProtocolSoup implements the following:
redirect_uri
Section titled “redirect_uri”Verifier identity is established by the redirect URI trust context. The client_id equals the response_uri.
decentralized_identifier (did:web)
Section titled “decentralized_identifier (did:web)”Verifier identity is resolved via DID document. The DID document is fetched and validated at runtime — id must match the presented DID, and verification material must be present in authentication, assertionMethod, or verificationMethod.
verifier_attestation
Section titled “verifier_attestation”Verifier presents a signed attestation JWT. The verifier’s attestation issuer publishes OpenID discovery metadata and JWKS. The wallet validates the attestation JWT against the published JWKS. When OID4VP_VERIFIER_ATTESTATION_PRIVATE_KEY_PEM is unset, an ephemeral in-memory key is auto-provisioned at startup.
x509_san_dns (OpenID4VP Section 5.9)
Section titled “x509_san_dns (OpenID4VP Section 5.9)”Verifier identity is bound to a DNS name via X.509 certificate Subject Alternative Name. The request object carries an x5c JOSE header containing the certificate chain. Trust validation requires:
- PKIX chain validation (leaf signed by CA, validity period, key usage)
- Leaf certificate DNS SAN matches the
client_idDNS name response_urihostname matches theclient_idDNS name- JWT signature verifies against the leaf certificate public key
- The
client_id_schemeclaim is present in the signed request object
When no certificate material is configured via environment variables, the verifier auto-provisions an ephemeral ECDSA P-256 self-signed CA + leaf chain at startup, with the leaf SAN bound to the deployment hostname.
Not implemented
Section titled “Not implemented”pre_registered,x509_hash,openid_federationare defined in the spec but not currently implemented.
Verifier Evaluation Flow (OID4VP §5, §6, §8)
Section titled “Verifier Evaluation Flow (OID4VP §5, §6, §8)”- Create Authorization Request — Verifier builds a signed request object (
typ=oauth-authz-req+jwt) containingclient_id,response_type=vp_token,response_mode,response_uri,dcql_query(orscope),nonce,state, andexp. Publishes it at arequest_uri. - Wallet Fetches Request Object — Wallet fetches the signed request from
request_urivia GET or POST. Validates JWT signature,typheader, and expiry before processing. - Wallet Submits Response — Wallet evaluates DCQL query, selects matching credentials, creates signed
vp_token(typ=vp+jwt), and submits toresponse_uri:direct_post: form-postvp_token+statedirect_post.jwt: form-post encryptedresponseJWE containing signed inner JWT (typ=oauth-authz-resp+jwt) withvp_token,state, and audience bound toresponse_uri
- Verifier Validates + Policy Decision — Verifier resolves session by
state, then validates:- nonce binding (VP token nonce matches request nonce)
- audience binding (VP token audience includes
client_id) - token expiry
- holder binding (
iss/submatches wallet identity,cnf.jktmatches key thumbprint)
- credential evidence (issuer signature, subject binding, disclosure integrity, and trust policy checks)
- DCQL claim-path completeness (all required claim paths present in disclosed claims)
- Result — Policy decision is stored and returned as
allowed/deniedwithcode,message,reasons, andreason_codes.
Endpoints
Section titled “Endpoints”| Endpoint Role | Purpose |
|---|---|
| Authorization Request Endpoint | Verifier creates and publishes a request object / request URI |
| Request URI Retrieval Endpoint | Wallet fetches request object by request_uri |
| Verifier Attestation Discovery | OpenID discovery metadata for the verifier attestation issuer |
| Verifier Attestation AS Metadata | OAuth 2.0 Authorization Server metadata for the attestation issuer |
| Verifier Attestation JWKS | Public signing keys used to validate verifier_attestation request objects |
| Response URI Endpoint | Wallet submits direct_post or direct_post.jwt response payloads |
| Verification Result Endpoint (optional) | Verifier exposes policy evaluation outcome to client tooling |
Illustrative Examples (Non-Normative)
Section titled “Illustrative Examples (Non-Normative)”direct_postresponse parameters:state=<opaque-value>&vp_token=<compact-jws>direct_post.jwtresponse parameter:response=<compact-jwe>where the decrypted plaintext is an inner JWT withtyp=oauth-authz-resp+jwt- VP token essentials:
typ=vp+jwt, nonce bound to request nonce, audience bound to verifierclient_id
What To Validate
Section titled “What To Validate”- Authorization request: signed request object with
typ=oauth-authz-req+jwt,client_id,response_mode,response_uri,nonce,state,exp - DCQL contract: exactly one of
dcql_queryorscope; required claim paths derived from DCQL are enforced - Client identification: chosen client_id scheme follows OpenID4VP scheme-specific trust validation
direct_postresponse:statemaps to active request andvp_tokenis presentdirect_post.jwtresponse: decrypts successfully and inner JWT signature/type/audience/subject/expiry checks pass- VP token checks:
typ=vp+jwt, nonce match, audience match, expiry valid, holder binding verified - Credential evidence checks: presented credential subject/issuer/signature/disclosures satisfy verifier trust policy and required claim paths
- Policy output: verifier returns explicit decision with status, code, and reason details