Presentation Flows
OID4VP supports multiple presentation flows to accommodate different verification scenarios. The choice of flow depends on whether the wallet and verifier are on the same device and who initiates the interaction.
Flow Comparison
| Property | Type | Required | Description |
|---|---|---|---|
| Optional | |||
| Optional | |||
| Optional |
OptionalOptionalOptionalSame-Device Flow
In the same-device flow, both the relying party application and wallet are on the same device (typically mobile). The verifier triggers the wallet using a custom URL scheme or universal link.
Custom Scheme
openid4vp:// is the standard custom URL scheme. Wallets register to handle this scheme on the device.
Requires wallet app to be installed. May show app chooser if multiple wallets are registered.
Universal Links
Uses HTTPS URLs that wallets claim via apple-app-site-association (iOS) or assetlinks.json (Android).
More reliable and secure. Falls back to browser if wallet not installed.
Deep Link Examples
// iOS/Android Deep Link handling
// Custom scheme
openid4vp://authorize?
response_type=vp_token
&client_id=https://verifier.example.com
&response_mode=direct_post
&response_uri=https://verifier.example.com/callback
&nonce=n-0S6_WzA2Mj
&presentation_definition_uri=https://verifier.example.com/pd/age-check
// Universal Link (iOS) / App Link (Android)
https://wallet.example/verify?
request_uri=https://verifier.example.com/request/xyz789Cross-Device Flow
The cross-device flow handles scenarios where the user is browsing on one device (e.g., desktop) but their wallet is on another (e.g., mobile phone). A QR code bridges the gap.
QR Code Content
The QR code contains the authorization request, typically using request_uri to keep the QR code small and scannable.
// QR Code Content (Cross-Device)
openid4vp://authorize?
request_uri=https://verifier.example.com/request/abc123
&client_id=https://verifier.example.com
// Or using Universal Links
https://wallet.example/.well-known/openid4vp?
request_uri=https://verifier.example.com/request/abc123
&client_id=https://verifier.example.comSession Synchronization
The browser session doesn't automatically know when the mobile wallet completes the presentation. Common approaches:
- WebSocket: Real-time push notification
- Server-Sent Events (SSE): One-way push
- Polling: Periodic status checks (fallback)
Session Status Polling
// Verifier backend: Check presentation status
GET /presentation-status/abc123 HTTP/1.1
Host: verifier.example.com
Authorization: Bearer session-token
// Response (pending)
{
"status": "pending",
"expires_at": "2024-01-15T10:05:00Z"
}
// Response (completed)
{
"status": "completed",
"vp_token_hash": "sha256:abc123...",
"verified_claims": {
"age_over_21": true
}
}Wallet-Initiated Flow
In the wallet-initiated flow, the user proactively shares a credential from their wallet. The wallet discovers compatible verifiers and initiates the presentation without a prior request.
Use Cases
- Proactively sharing proof of age at a venue
- Presenting membership credentials at a facility
- Sharing professional certifications with employers
- Self-service credential verification kiosks
Wallet Metadata
Wallets can advertise their capabilities through metadata, enabling verifiers to craft compatible requests.
// Wallet metadata for discovery
{
"authorization_endpoint": "openid4vp://authorize",
"response_types_supported": ["vp_token"],
"response_modes_supported": ["direct_post", "direct_post.jwt"],
"vp_formats_supported": {
"jwt_vp_json": {
"alg_values_supported": ["ES256", "EdDSA"]
},
"mso_mdoc": {
"alg_values_supported": ["ES256"]
}
},
"request_object_signing_alg_values_supported": ["ES256", "EdDSA"]
}