Issuance Flows
Detailed walkthrough of the Authorization Code and Pre-Authorized Code flows, including deferred issuance for asynchronous credential generation.
Authorization Code Flow
The standard OAuth 2.0 Authorization Code flow extended for credential issuance. The user authenticates at the issuer and consents to credential issuance.
1 Discovery
Wallet fetches issuer metadata from /.well-known/openid-credential-issuer to learn about supported credentials, endpoints, and capabilities.
2 Authorization Request
Wallet redirects user to Authorization Server with requested credential type (via scope or authorization_details).
GET /authorize?
response_type=code
&client_id=wallet123
&redirect_uri=https://wallet.example/callback
&scope=openid UniversityDegreeCredential
&code_challenge=E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM
&code_challenge_method=S2563 Token Request
Wallet exchanges authorization code for access token. Response includes c_nonce for proof of possession.
POST /token
Content-Type: application/x-www-form-urlencoded
grant_type=authorization_code
&code=SplxlOBeZQQYbYS6WxSbIA
&redirect_uri=https://wallet.example/callback
&code_verifier=dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk4 Credential Request
Wallet creates proof of possession with c_nonce and requests credential.
POST /credential
Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6...
Content-Type: application/json
{
"credential_configuration_id": "UniversityDegreeCredential",
"proof": {
"proof_type": "jwt",
"jwt": "eyJ0eXAiOiJvcGVuaWQ0dmNpLXByb29mK2p3dCIs..."
}
}Pre-Authorized Code Flow
When the issuer has already verified the user (e.g., in-person at a DMV, via existing account), they can issue a pre-authorized code that the wallet exchanges directly for a token.
Token Request with Pre-Authorized Code
POST /token
Content-Type: application/x-www-form-urlencoded
grant_type=urn:ietf:params:oauth:grant-type:pre-authorized_code
&pre-authorized_code=SplxlOBeZQQYbYS6WxSbIA
&tx_code=493536Transaction Code (tx_code)
An optional PIN or code sent via separate channel (SMS, email) to bind the pre-authorized code to the legitimate user. Prevents interception attacks.
input_mode
"numeric" or "text"
length
Expected code length (e.g., 6)
Deferred Issuance
When credential generation takes time (e.g., requires human review), the issuer returns a transaction_id instead of the credential. The wallet polls the deferred endpoint until the credential is ready.
Initial Response (Deferred)
HTTP/1.1 202 Accepted
Content-Type: application/json
{
"transaction_id": "8xLOxBtZp8",
"c_nonce": "wlbQc6pCJp",
"c_nonce_expires_in": 86400,
"interval": 5
}Polling the Deferred Endpoint
POST /deferred
Authorization: Bearer eyJhbGciOiJSUzI1NiIs...
Content-Type: application/json
{
"transaction_id": "8xLOxBtZp8"
}When to Use Which Flow
| Scenario | Recommended Flow |
|---|---|
| User discovers credential in wallet app | Authorization Code |
| Issuer already verified user (DMV visit) | Pre-Authorized Code |
| QR code at physical location | Pre-Authorized Code |
| Email with credential claim link | Pre-Authorized Code |
| Real-time identity verification needed | Authorization Code |
| Manual review of application | Either + Deferred |