OID4VCI
OID4VCI
Section titled “OID4VCI”Standards
Section titled “Standards”- OpenID for Verifiable Credential Issuance 1.0 (final)
- OAuth 2.0 Authorization Framework (token and grant semantics)
- SD-JWT VC profile (
dc+sd-jwtcredential format) - W3C Verifiable Credentials Data Model 1.1 / 2.0 (
jwt_vc_json,jwt_vc_json-ld,ldp_vcformats) - W3C VC Data Integrity 1.0 (
ecdsa-rdfc-2019,eddsa-rdfc-2022cryptosuites forldp_vc)
Available Flows
Section titled “Available Flows”| Flow ID | Name | Steps | Description |
|---|---|---|---|
oid4vci-pre-authorized | Pre-Authorized Code | 6 | Resolve offer, discover metadata, exchange pre-authorized code, receive token + c_nonce, submit proof, receive issued credential |
oid4vci-pre-authorized-tx-code | Pre-Authorized + tx_code | 6 | Same flow with mandatory tx_code at token exchange |
oid4vci-deferred-issuance | Deferred Issuance | 8 | Full end-to-end flow: offer, metadata, token, credential request, deferred response with transaction_id, polling, credential ready |
Demo Scenarios
Section titled “Demo Scenarios”- Pre-Authorized Issuance — Resolve by-reference offer, exchange token, submit proof, receive issued credential (format per credential configuration)
- Pre-Authorized + tx_code — Enforce out-of-band
tx_codebefore token issuance - Deferred Issuance Polling — Receive
transaction_id, poll until credential is ready
Credential Details
Section titled “Credential Details”| Property | Value |
|---|---|
| Credential configuration selection | Wallet chooses from credential_configurations_supported (e.g., one configuration describing a university degree VC type) |
| Credential formats | dc+sd-jwt (SD-JWT VC), jwt_vc_json, jwt_vc_json-ld, ldp_vc (W3C Data Integrity) |
| Proof container | proof or proofs with proof_type: jwt (e.g., {"proof_type":"jwt","jwt":"<compact-jws>"}) |
| Proof JWT header type | openid4vci-proof+jwt |
| Proof JWT required claims | iss, sub, aud, nonce, iat, exp, cnf.jwk |
| Deferred issuance indicator | transaction_id returned by credential endpoint (e.g., an opaque identifier such as "txn_...") |
Pre-Authorized Code Issuance Flow (OID4VCI §4, §6.1, §7)
Section titled “Pre-Authorized Code Issuance Flow (OID4VCI §4, §6.1, §7)”- Resolve Credential Offer — Wallet receives
credential_offer_uriout-of-band and fetches the credential offer object from the Credential Issuer. Offer containscredential_issuer,credential_configuration_ids, andgrants.urn:ietf:params:oauth:grant-type:pre-authorized_code. - Discover Issuer Metadata — Wallet fetches
/.well-known/openid-credential-issuerto discovercredential_configurations_supported,credential_endpoint,nonce_endpoint,deferred_credential_endpoint, and token endpoint URL. - Token Request — Wallet calls token endpoint with
grant_type=urn:ietf:params:oauth:grant-type:pre-authorized_code,pre-authorized_code, andtx_codewhen required by the offer grant. - Token Response — Authorization Server validates the pre-authorized code (and
tx_codeif required) and returnsaccess_token,token_type,scope(if applicable),c_nonce, andc_nonce_expires_in. - Credential Request — Wallet submits
credential_configuration_idandproof/proofs(proof_type: jwt) with a proof JWT bound to the activec_nonceand the credential issuer audience. - Credential Response — Issuer validates proof key binding, nonce freshness, and audience/subject constraints, then returns:
- Immediate:
formatmatching the credential configuration (e.g.dc+sd-jwtwith disclosures,jwt_vc_json,jwt_vc_json-ld, orldp_vcwith Data Integrity proof),credential, nextc_nonce, or - Deferred:
transaction_id, nextc_nonce— wallet then pollsdeferred_credentialendpoint until credential is ready.
- Immediate:
Contract Enforcement
Section titled “Contract Enforcement”- Credential offer envelope enforces XOR: exactly one of
credential_offerorcredential_offer_uri. tx_codeis required when the offer grant includes atx_codeobject.- Proofs are required when proof types are declared for the credential configuration.
- Proof JWT header
typmust beopenid4vci-proof+jwt. - Proof must include
iss,sub,aud,nonce,iat,exp, andcnf.jwk. - Nonce is freshness-bound and one-time in issuance requests (replay and expiry are rejected).
- Deferred polling requires matching
transaction_idand same access token lineage.
Endpoints
Section titled “Endpoints”| Endpoint Role | Discovery Source | Purpose |
|---|---|---|
| Credential Issuer Metadata Endpoint | /.well-known/openid-credential-issuer/{issuer-path} | Discover issuer metadata, credential configurations, and endpoint URLs |
| Credential Offer URI | credential_offer_uri | Retrieve a credential offer by reference |
| Token Endpoint | Issuer/Authorization Server metadata | Exchange pre-authorized_code (or authorization grant) for access token and nonce |
| Nonce Endpoint | nonce_endpoint from issuer metadata | Request a fresh c_nonce challenge when needed |
| Credential Endpoint | credential_endpoint from issuer metadata | Submit proof and request credential issuance |
| Deferred Credential Endpoint | deferred_credential_endpoint from issuer metadata | Poll a pending issuance transaction with transaction_id |
Illustrative Examples (Non-Normative)
Section titled “Illustrative Examples (Non-Normative)”- Pre-authorized token request body (form-encoded):
grant_type=urn:ietf:params:oauth:grant-type:pre-authorized_code&pre-authorized_code=... - Proof JWT protected header:
{"typ":"openid4vci-proof+jwt","alg":"<wallet-signing-alg>"}and payload includesaud,nonce,cnf.jwk - Deferred credential response shape:
{"transaction_id":"...","c_nonce":"...","c_nonce_expires_in":...}
What To Validate
Section titled “What To Validate”- Credential offer envelope: exactly one of
credential_offerorcredential_offer_uri - Metadata retrieval: well-known endpoint resolves to issuer metadata and endpoint URLs
- Token exchange:
pre-authorized_codegrant processing andtx_codeenforcement when offered - Proof JWT:
typ=openid4vci-proof+jwt,cnf.jwkkey binding,audmatches issuer,noncematches activec_nonce - Nonce behavior: replayed or expired
c_nonceis rejected; next nonce is returned after successful issuance - Credential response: serialization matches negotiated format (e.g.
dc+sd-jwtincludes issuer-signed JWT + disclosures,ldp_vcincludes Data Integrity proof) - Deferred flow:
issuance_pendingbefore ready time, then final credential on successful poll