Skip to content

(Q)EAA Issuance with OpenID4VC

Basic Idea

The Q(EAA) Provider issues signed credentials to the Wallet which are stored for a longer period. The Wallet can then present the credentials (including a proof of possession by signing over a wallet-held key) to the Relying Party.

Cryptographic Formats

Long-Term keys:

  • (Q)EAA Provider has long-term key pair \((ep\_pub, ep\_priv)\) which is used to sign the Credential

Transaction-specific keys:

  • EUDIW generates device key \((device\_pub, device\_priv)\) which is used to generate proof of possession of a Credential
  • EUDIW optionally generates key pair \((cre\_eph\_pub, cre\_eph\_priv)\) which is used to encrypt the credential response

Artifacts:

  • EUDIW fetches Wallet Attestation from Wallet Provider: \(wallet\_attestation\)
  • (Q)EAA Provider issues
    • SD-JWT (plus Disclosures): \(sd\_jwt := \text{sign}(\mathit{hashed\_attestation\_data}, device\_pub)_{ep\_priv}\)
    • ISO mdoc: \(mdoc := \text{sign}(\mathit{hashed\_attestation\_data}, device\_pub)_{ep\_priv}\)

Dependencies

TODO: May want to expand to include metadata.

G cluster_eaa_provider (Q)EAA Provider cluster_wallet Wallet ep 🗝 (ep_priv, ep_pub) user_data attestation data ep->user_data sign (SD-JWT/ mdoc issuerAuth) device_key 🗝 (device_priv, device_pub) ep->device_key sign (SD-JWT/ mdoc issuerAuth) nonce_audience nonce, audience device_key->nonce_audience sign (KB-JWT/ mdoc deviceAuth)

Note: Wallet attestation not shown in this chart.

Sequence Diagram

Remote Issuance with Authorization Code Flow

User Journey: (Q)EAA Issuance - Authorization Code

(Q)EAA Issuance over OpenID4VCI with Authorization Code Flow(Q)EAA Issuance over OpenID4VCI with Authorization Code FlowUserOpenID HolderUserOpenID HolderUser's EUDI Wallet InstanceUser's EUDI Wallet InstanceBrowser App(same device)Browser App(same device)(Q)EAA ProviderLong-term Key: (ep_pub,ep_priv)(Q)EAA ProviderLong-term Key: (ep_pub,ep_priv)alt[Wallet initiated](001)open wallet, unlock walletScreen: launch_walletScreen: unlock_wallet(002)Select issuance ofpre-configured (Q)EAAPre-configured (Q)EAAs containscredential_issuer URLs and scopesScreen: credential_catalogScreen: next_steps[Issuer initiated](003)Open Issuer's Website(004)Query website: HTTP GET<credential_issuer_url>/(005)HTTP 200HTML with static CredentialOffer<Grant-Type: AuthorizationCode>Screen: same_device_issuer_website(006)open wallet, unlock walletScreen: launch_walletScreen: unlock_walletScreen: next_steps(007)[TLS] HTTP GET ./well-knownCredential Issuer Metadata(008)[TLS] HTTP 200 <CredentialIssuer Metadata>alt[optional Wallet Attestation](009)[TLS] HTTP POST</session_endpoint> walletattestation nonce(010)generate and store nonce(011)[TLS] HTTP 200 <walletattestation nonce>(012)get wallet attestation fromWallet Provider backend(wallet attestation nonce)(013)generate PoP for walletattestation(014)[TLS] PAR (code_challenge,wallet attestation + PoP,redirect_uri)alt[optional Wallet Attestation](015)verify wallet attestationcheck wallet solution statuson trust list(016)[TLS] request_uri(017)[TLS] HTTP GET <OpenID4VCIAuthorizationRequest(request_uri)>(018)[TLS] HTTP GET <OpenID4VCIAuthorizationRequest(request_uri)>User Authentication(019)<user authentication>the (Q)EAA Provider may perform any form ofuser authentication in the browser, this maybe:- username/password- OpenID4VP credential presentation- taking a foto- any other mechanism enabled through thebrowserScreen: same_device_issuer_authentication(020)[TLS] HTTP 302 redirect-uri<OpenID4VCI AuthorizationResponse(authorizationcode)>(021)[TLS] HTTP 302 redirect-uri<OpenID4VCI AuthorizationResponse(authorizationcode)>(022)user consent for receiving the(Q)EAAScreen: consent_add_credential(023)[TLS] HTTP POST <TokenRequest(authorization code,PKCE code_verifier, walletattestation + PoP, DPoPHeader)>(024)lookup authorization codegenerate TokenResponse withDPoP access tokenverify PKCE challengealt[optional Wallet Attestation](025)verify wallet attestation(026)[TLS] HTTP 200 <TokenResponse(DPoP-boundaccesss_token, c_nonce)>(027)generate device binding keypair (device_pub, device_priv)and proof of possession withc_nonceDevice key should be protected by platformsecurity mechanismsScreen: device_authenticatoralt[optional credential response encryption](028)generate credential responseencryption key pair(cre_eph_pub, cre_eph_priv)(029)createcredential_response_encryptionobject with jwk containingcre_eph_pub(030)[TLS] HTTP POST <CredentialRequest(DPoP-bound accesstoken, device_pub, optionallycredential_response_encryption)>(031)lookup access token validate key proofalt[SD-JWT (Q)EAA](032)generate SD-JWT (Q)EAA andDisclosures with attestationdata and device_pub as cnfkey, sign with ep_priv[mdoc (Q)EAA](033)generate mdoc (Q)EAA withattestation data anddevice_pub as deviceKey, signwith ep_privalt[credential_response_encryption present](034)generate encrypted credentialresponse JWT using the valuesreceived in thecredential_response_encryptionobject(035)[TLS] HTTP 200<JWT(CredentialResponse((Q)EAA))>(036)decrypt credential responseJWT and retrieve credential[not present](037)[TLS] HTTP 200 <CredentialResponse((Q)EAA)>(038)store (Q)EAAScreen: successScreen: homeit might be useful to have a redirect in thebrowser

Step-by-Step Description

  1. (Wallet initiated) The user opens and unlocks his wallet.
  2. (Wallet initiated) The user navigates to a credential catalog of pre-configured (Q)EAA Providers and offered credentials in the Wallet. He selects a (Q)EAA and the Wallet continues the flow with the preconfigured Credential Issuer URL and credential identifier.
  3. (Issuer initiated) User browses to (Q)EAA Provider's website.
  4. (Issuer initiated) Browser app on the user's device opens the (Q)EAA Provider's website
  5. (Issuer initiated) (Q)EAA Provider returns an HTML page to the browser containing a Credential Offer; containing
    • the Credential Issuer URL
    • an identifier to the offered credential
    • an optional issuer_state parameter to bind this issuance to a pre-existing session
  6. (Issuer initiated) The user clicks on the link, the Wallet launches and he unlocks the wallet
  7. The Wallet fetches the Credential Issuer's metadata from the ./well-known files of the Credential Issuer URL
  8. The (Q)EAA Provider (from here on named Issuer in his OpenID4VCI role) return the Credential Issuer Metadata; containing:
    • technical information about the Issuer
    • translations and display data for the offered credentials
  9. The Wallet shows information about the (Q)EAA Provider and the offered (Q)EAA to the user and asks for consent
  10. The Wallet requests a fresh nonce for the wallet attestation nonce (wallet attestation)
  11. The Issuer generates a fresh nonce linked to the issuance session
  12. The Issuer returns the wallet attestation nonce to the Wallet
  13. The Wallet fetches fresh wallet attestation from the Wallet Provider backend
  14. The Wallet generates proof of possession (PoP) using the nonce fetched in the previous step
  15. The Wallet sends a Pushed Authorization Request (PAR) to the Issuer; containing:
    • the Wallet Provider's client_id
    • a PKCE code_challenge
    • the wallet attestation and proof of possession
    • a redirect_uri containing an app-link
    • an identifier for the requested (Q)EAA
  16. The Issuer verifies the wallet attestation and validates the status of the Wallet solution through a trust list
  17. The Issuer stores the Authorization Request, generates a request_uri and sends this back to the Wallet
  18. The Wallet uses the request_uri to create an Authorization Request and send this to the Authorization endpoint of the Issuer by issuing a HTTP GET request over the system's default browser.
  19. The Browser sends the Authorization Request to the Issuer
  20. In this authentication phase, the Issuer may exchange any information over the browser to the user, as he got the "screen control". This may be, but is not limited to:
    • username / password
    • OpenID4VP credential presentation of PID, other (Q)EAA, etc..
    • taking a photo
  21. The Issuer finalizes the authentication phase by responding with an Authorization Response; containing
    • the auth code
    • the redirect provided by the wallet in the PAR
  22. The browser follows the redirect, launching again the wallet
  23. The Wallet sends a Token Request to the PID Provider; containing:
    • the auth code from Authorization Response
    • the PKCE code_verifier matching the code_challenge from Authorization Request
    • the wallet attestation and Proof of possession
    • a DPoP key
  24. The Issuer matches the code, verifies the PKCE code_verifier to the previously received code_challenge and verifies the wallet attestation. It then generates an access token bound to the DPoP key.
  25. The Issuer verifies the wallet attestation and proof of possession
  26. The Issuer sends a Token Response; containing
    • DPoP-bound access token
    • a c_nonce
  27. The Wallet generates a key pair for the device binding of the (Q)EAA (kb_eph_pub, kb_eph_priv) and signs the c_nonce
  28. The Wallet may request an encrypted credential response. In order to do so, it generates a new ephemeral keypair (cre_eph_pub, cre_eph_priv).
  29. The Wallet creates the credential_response_encryption JSON object containing the following information:
    • a jwk containing the cre_eph_pub
    • the JWE alg parameter
    • the JWE enc parameter
  30. The Wallet sends the Credential Request to the Issuer; containing
    • the DPoP-bound access token
    • the proof of device binding key kb_eph_pub signed c_nonce
    • and optionally the credential_response_encryption object
  31. The Issuer validates the access_token and the proof
  32. (SD-JWT (Q)EAA) The Issuer creates the Disclosures from attestation data and signs the SD-JWT with ep_priv containing
    • attestation data and hashed Disclosures as the user claims
    • kb_eph_pub as cnf claim He then appends the Disclosures.
  33. (mdoc (Q)EAA) The Issuer creates the hashed Releases from attestation data and signs the mdoc with ep_priv containing
    • attestation data and hashed Releases as issuerAuth
    • kb_eph_pub as deviceKeyInfo
  34. In case credential_response_encryption information is present, the Issuer creates an encrypted JWT (JWE) using the values received in the credential_response_encryption object and adds it (among others) the (Q)EAA credential to the payload.
  35. The Issuer sends the Credential Response JWT; containing:
    • The (Q)EAA as credential
  36. The Wallet decrypts the Credential Response JWT using the cre_eph_priv and retrieves the credential.
  37. In case credential_response_encryption information are not present, the Issuer sends the plain Credential Response; containing:
    • The (Q)EAA as credential.
  38. The Wallet stores the (Q)EAA and the associated keys.

Remote Issuance Pre-Authorized Code Flow

User Journey: (Q)EAA Issuance - Pre-Authorized Code

(Q)EAA Issuance over OpenID4VCI with Pre-Authorized Code Flow(Q)EAA Issuance over OpenID4VCI with Pre-Authorized Code FlowUserOpenID HolderUserOpenID HolderUser's EUDI Wallet InstanceUser's EUDI Wallet InstanceBrowser AppBrowser App(Q)EAA ProviderLong-term Key: (ep_pub,ep_priv)(Q)EAA ProviderLong-term Key: (ep_pub,ep_priv)(001)Open Issuer's WebsiteUser Authenticationthe (Q)EAA Provider may perform any form ofuser authentication prior to creating thecredential offer(002)Query website: HTTP GET<credential_issuer_url>/(003)HTTP 200HTML with dynamic CredentialOffer<pre-authorized code,tx_code>alt[Issuer initiated - Same Device]Screen: same_device_issuer_website(004)open wallet, unlock walletScreen: launch_walletScreen: unlock_wallet[Issuer initiated - Cross Device]Screen: cross_device_issuer_website(005)scan QR-CodeScreen: launch_walletScreen: unlock_walletScreen: device_camera(006)[TLS] HTTP GET ./well-knownCredential Issuer Metadata(007)[TLS] HTTP 200 <CredentialIssuer Metadata>(008)user consent for receiving the(Q)EAAScreen: consent_add_credentialalt[optional Wallet Attestation](009)[TLS] HTTP POST</session_endpoint> walletattestation nonce(010)generate and store nonce(011)[TLS] HTTP 200 <walletattestation nonce>nonce may be provided in credential offer orreuse pre-auth code(012)perform and get walletattestation from WalletProvider backend (walletattestation nonce)(013)generate PoP for walletattestation(014)[TLS] HTTP POST <TokenRequest(pre-authorizationcode, wallet attestation, DPoPHeader, optional txCode)>alt[optional Wallet Attestation](015)verify wallet attestationcheck wallet solution statuson trust list(016)lookup authorization codegenerate TokenResponse withDPoP access token(017)[TLS] HTTP 200 <TokenResponse(DPoP-boundaccesss_token, c_nonce)>(018)generate device binding keypair (device_pub, device_priv)and proof of possession withc_nonceDevice key should be protected by platformsecurity mechanismsScreen: device_authenticatoralt[optional credential response encryption](019)generate credential responseencryption key pair(cre_eph_pub, cre_eph_priv)(020)createcredential_response_encryptionobject with jwk containingcre_eph_pub(021)[TLS] HTTP POST <CredentialRequest(DPoP-bound accesstoken, device_pub, optionallycredential_response_encryption)>(022)lookup access token validate key proofalt[SD-JWT (Q)EAA](023)generate SD-JWT (Q)EAA andDisclosures with attestationdata and device_pub as cnfkey, sign with ep_priv[mdoc (Q)EAA](024)generate mdoc (Q)EAA withattestation data anddevice_pub as deviceKey, signwith ep_privalt[credential_response_encryption present](025)generate encrypted credentialresponse JWT using the valuesreceived in thecredential_response_encryptionobject(026)[TLS] HTTP 200<JWT(CredentialResponse((Q)EAA))>(027)decrypt credential responseJWT and retrieve credential[not present](028)[TLS] HTTP 200 <CredentialResponse((Q)EAA)>(029)store (Q)EAAScreen: successScreen: homeit might be useful to have a redirect in thebrowser for same-device flow

Step-by-Step Description

  1. User browses to (Q)EAA Provider's website. At this point it is assumed that the user authentication already took place before the OpenID4VCI protocols starts. This may happen through any mechanism, e.g. username/password, providing OTPs, etc..
  2. Browser app on the user's device opens the (Q)EAA Provider's website
  3. (Q)EAA Provider returns a HTML page to the browser containing a Credential Offer; containing
    • the Credential Issuer URL
    • an identifier to the offered credential
    • a pre-Authorized Code for authorization, linked to the identified user
    • the flag tx_code indicating whether the Wallet is expected to provide a Transaction Code in the Token Request. The Transaction Code is sent by the Issuer over a second channel, e.g., via e-mail or SMS, and helps to strengthen security by additional session binding.
  4. (Same-Device) The user clicks on the link, the Wallet launches and he unlocks the wallet
  5. (Cross-Device) The user opens and unlocks his wallet and scans the QR-Code
  6. The Wallet fetches the Credential Issuer's metadata from the ./well-known files of the Credential Issuer URL
  7. The (Q)EAA Provider (from here on named Issuer in his OpenID4VCI role) return the Credential Issuer Metadata; containing:
    • technical information about the Issuer
    • translations and display data for the offered credentials
  8. The Wallet shows information about the (Q)EAA Provider and the offered (Q)EAA to the user and asks for consent
  9. The Wallet requests a fresh nonce for the wallet attestation nonce (wallet attestation)
  10. The Issuer generates a fresh nonce linked to the issuance session
  11. The Issuer returns the wallet attestation nonce to the Wallet
  12. The Wallet fetches fresh wallet attestation from the Wallet Provider backend
  13. The Wallet generates proof of possession (PoP) using the nonce fetched in the previous step
  14. The Wallet sends a Token Request to the PID Provider; containing:
    • the pre-authorized code from Authorization Response
    • the wallet attestation and Proof of possession
    • a DPoP key
    • the Transaction Code that the user received over a second communication channel from the Issuer, if tx_code was present in the Credential Offer
  15. The Issuer verifies the wallet attestation and validates the status of the Wallet solution through a trust list
  16. The Issuer matches the pre-authorized code and generates an access token bound to the DPoP key.
  17. The Issuer sends a Token Response; containing
    • DPoP-bound access token
    • a c_nonce
  18. The Wallet generates a key pair for the device binding of the (Q)EAA (kb_eph_pub, kb_eph_priv) and signs the c_nonce
  19. The Wallet may request an encrypted credential response. In order to do so, it generates a new ephemeral keypair (cre_eph_pub, cre_eph_priv).
  20. The Wallet creates the credential_response_encryption JSON object containing the following information:
    • a jwk containing the cre_eph_pub
    • the JWE alg parameter
    • the JWE enc parameter
  21. The Wallet sends the Credential Request to the Issuer; containing
    • the DPoP-bound access token
    • the proof of device binding key kb_eph_pub signed c_nonce
    • and optionally the credential_response_encryption object
  22. The Issuer validates the access_token and the proof
  23. (SD-JWT (Q)EAA) The Issuer creates the Disclosures from attestation data and signs the SD-JWT with ep_priv containing
    • attestation data and hashed Disclosures as the user claims
    • kb_eph_pub as cnf claim He then appends the Disclosures.
  24. (mdoc (Q)EAA) The Issuer creates the hashed Releases from attestation data and signs the mdoc with ep_priv containing
    • attestation data and hashed Releases as issuerAuth
    • kb_eph_pub as deviceKeyInfo
  25. In case credential_response_encryption information is present, the Issuer creates an encrypted JWT (JWE) with the information and adds (among others) the (Q)EAA credential to the payload.
  26. The Issuer sends the Credential Response JWT; containing:
    • The (Q)EAA as credential
  27. The Wallet decrypts the Credential Response JWT using the cre_eph_priv and retrieves the credential.
  28. In case credential_response_encryption information are not present, the Issuer sends the plain Credential Response; containing:
    • The (Q)EAA as credential.
  29. The Wallet stores the (Q)EAA and the associated keys.

Usability Considerations

Common Considerations

  • (Q)EAA Provider / Credential catalogue should inform users in advance of what is required for the successful issuance of the (Q)EAA and what steps follow
  • For reasons of transparency and to increase trust, (Q)EAA Providers should provide sufficient information (metadata) for the consent screen. This allows users to learn everything relevant e.g. about the provider itself.
  • User must confirm the process with the Device Authenticator
  • User can have a (Q)EAA credential on several end devices at the same time

Authorization Code Flow Considerations

  • User needs to authenticate successfully on (Q)EAA Provider website
  • If the user has to go through more than 2 context switches (issuer initiated flow), it can be confusing, might create unnecessary complexity and additional potential points of failure, and ultimately leads to friction.

Pre-Authorized Code Flow Considerations

  • User is already authenticated on (Q)EAA Provider website or no authentication is required
  • To obtain/copy the transaction code, an additional context switch may be necessary

Privacy Considerations

  • Unlinkability has to be achieved with batch issuance

Security Considerations

  • (Q)EAA Providers may choose to require a wallet attestation
  • the security guarantees of the Pre-Authorized Code Flow, especially in the Cross-Device Flow, are not intended for higher security levels

Implementation Consideration

TBD