Skip to content

PID Option B': Authenticated Channel with Cloud Support

Basic Idea

On-demand issuance of PID credentials in ISO mdoc / SD-JWT VC format using the OpenID4VCI protocol for issuance and the OpenID4VP protocol for presentation. The PID credentials are HMAC'd by the PID Provider for the specific transaction.

To increase usability, a seed credential is derived from the national eID and stored on the mobile device. This seed credential can be used for a limited period of time to generate presentations instead of the national eID. To secure the seed credential, the user must set up a new PID PIN, which is verified by the PID provider on the server side during on-the-fly issuance.

Lifecycle

The credential is created on-demand by the PID Provider, i.e., a new credential is created for every transaction. The credential is not stored in the wallet. It is bound to the specific transaction through not only the nonce and audience, but also the symmetric key used for HMAC'ing, which is derived from ephemeral keys of the RP and PID Provider.

The seed credential issued and signed by the PID provider should only have a limited lifetime and should be bound to the same key as the wallet attestation issued by the wallet provider and to the key derived from the user PID PIN. The seed credential contains all available PID attributes and is intended exclusively for presentation to the PID provider, therefore it is a credential (in JWT format) that does not provide a mechanism for selective disclosure.

Credential formats

Two solutions are described:

  • ISO mdoc: The ISO mdoc credential format is used with:
  • issuerAuth as issuer data authentication, a COSE_Sign1 signature over the MobileSecurityObject (see ISO 23220-4 7.1.3.4.2.1) signed by the PID Provider
    • no signed hashes are transmitted, i.e., digestAlgorithm and valueDigests are omitted
  • deviceMAC as mdoc authentication method, a COSE_Mac0 MAC over the deviceAuthentication data (see ISO 18013-5 9.1.3.5) signed by the PID Provider
    • containing the PID data
  • SD-JWT VC: The SD-JWT VC credential format is used with:
  • SD-JWT issued by the PID Provider, a JOSE JWS with MAC key derived from ECDH* and signed by the PID Provider
    • containing the PID data
    • the Wallet provides an ephemeral, asymmetric key to the PID Provider for the key binding
  • KB-JWT issued by the Wallet, a JOSE JWS using digital signature and signed by the Wallet
    • containing nonce and audience of the Relying Party
    • containing a hash of the SD-JWT and the selected disclosures

Note that in mdoc, it is PID Provider and not the Wallet who creates DeviceSigned containing only the selectively disclosed data based on the Verifier's request and user consent. This is different from ISO 18013-5, where it is the Wallet who creates DeviceSigned. It is PID Provider who creates IssuerSigned.

In SD-JWT, it is PID Provider who creates SD-JWT and the Wallet who creates KB-JWT.

The establishment of the authenticated channel is defined: - for mdoc, in Chapter 9.1.3.5 in ISO 18013-5, in the mdoc MAC Authentication section - for SD-JWT, the IETF Draft for Designated Verifier Signatures defines a JOSE algorithm to be used

Cryptographic Formats

Long-Term keys:

  • PID Provider has long-term key pair \((pp\_pub, pp\_priv)\) which is used
  • to sign over the ephemeral issuer key, authenticating it for credential issuance
  • sign the Seed PID-Credential
  • RP has long-term key pair \((rp\_pub, rp\_priv)\) which is used
  • to sign over the authorization request, authenticating its contents
  • Wallet Instance has long-term device bound key pair \((device\_pub, device\_priv)\) which is used
  • to generate proof of possession of wallet attestation
  • to bind the PIN proof to the device
  • Wallet Instance has long-term AES key \((pin\_salt)\) which is used
  • to derive the pin_derived_eph_priv used as PoP of Wallet PIN
  • Wallet Backend long-term key pair \((wp\_pub, wp\_priv)\) which is used
  • to sign wallet instance's wallet attestations
  • Wallet Instance or Wallet Backend long-term key pair \((wallet\_backend\_dpop\_pub, wallet\_backend\_dpop\_priv)\) which is used
  • as the DPoP key

Transaction-specific keys:

  • Relying Party generates ephemeral key pair \((rp\_eph\_pub, rp\_eph\_priv)\) which is used
  • as contribution to HMAC key
  • PID Provider generates ephemeral key pair \((pp\_eph\_pub, pp\_eph\_priv)\) which is used as contribution to HMAC key
  • Wallet generates ephemeral key pair \((kb\_eph\_pub, kb\_eph\_priv)\) which is used
  • to sign KB-JWT (SD-JWT)
  • Wallet Instance generates PIN key pair \((pin\_derived\_eph\_pub, pin\_derived\_eph\_priv)\) which is used
  • to generate PIN proof of possession

Note: The PIN key pair is not stored by the Wallet Instance, instead is generated every time the user enters the PIN.

Artifacts:

  • PID Provider creates certificate for ephemeral issuer key: \(x5c\_header := \text{sign}(pp\_eph\_pub)_{pp\_priv}\)
  • Key for authenticating SD-JWT: \(hmac\_key := \text{ecdh}(pp\_eph\_priv, rp\_eph\_pub)\)
  • PID Provider creates SD-JWT: \(sd\_jwt := \text{hmac}(x5c\_header, \mathit{eID\_data}, kb\_eph\_pub)_{hmac\_key}\) and disclosures
  • Wallet Backend creates Wallet Attestation including \((device\_pub)\) and signed with \((wp\_priv)\), Wallet Attestion is stored by Wallet Instance
  • PID Provider creates Seed PID-Credential as JWT including \((device\_pub)\) and signed with \((pp\_priv)\), which is used to generate the credentials in the "On-the-fly PID Issuance" for presentation. Content of the Seed PID-Credential:
  • eID data of the holder (PID data set)
  • Key for the holder binding of the seed credential \((device\_pub)\)

Dependencies

SD-JWT

TODO: May want to expand to include metadata.

G cluster_wallet Wallet cluster_wscd WSCD cluster_rp Relying Party cluster_pid_provider PID Provider device_key 🗝 (device_priv, device_pub) w_attest_POP wallet attestation POP (wallet attestation nonce) device_key->w_attest_POP sign session_id pid_issuer_session_id device_key->session_id sign pin_salt 🗝 PIN salt key pin_key 🗝 (pin_derived_eph_priv, pin_derived_eph_pub) pin_salt->pin_key derived with PIN pin_key->session_id sign kb_key 🗝 (kb_eph_priv, kb_eph_pub) kb_jwt KB-JWT(nonce,aud,hash(SD-JWT,disclosures)) kb_key->kb_jwt sign rp 🗝 (rp_eph_priv, rp_eph_pub) hmac 🗝 HMAC key rp->hmac ecdh-ka sd_jwt SD-JWT(eID Data, kb_eph_pub) hmac->sd_jwt sign pp 🗝 (pp_priv, pp_pub) seed_C seed credential (device_pub, pin_derived_eph_pub) pp->seed_C sign pp_cert key certificate for pp_eph pp->pp_cert sign pp_eph 🗝 (pp_eph_priv, pp_eph_pub) pp_eph->hmac ecdh-ka

mdoc

TODO: May want to expand to include metadata.

G cluster_wallet Wallet cluster_wscd WSCD cluster_rp Relying Party cluster_pid_provider PID Provider device_key 🗝 (device_priv, device_pub) w_attest_POP wallet attestation POP (wallet attestation nonce) device_key->w_attest_POP sign session_id pid_issuer_session_id device_key->session_id sign pin_salt 🗝 PIN salt key pin_key 🗝 (pin_derived_eph_priv, pin_derived_eph_pub) pin_salt->pin_key derived with PIN pin_key->session_id sign rp 🗝 (rp_eph_priv, rp_eph_pub) hmac 🗝 HMAC key rp->hmac ecdh-ka devAuth deviceAuth(eID Data, SessionTranscript) hmac->devAuth sign pp 🗝 (pp_priv, pp_pub) seed_C seed credential (device_pub, pin_derived_eph_pub) pp->seed_C sign issuerAuth issuerAuth(pp_eph_pub) pp->issuerAuth sign pp_eph 🗝 (pp_eph_priv, pp_eph_pub) pp_eph->hmac ecdh-ka

Sequence Diagram

Wallet Initialization

User Journey: Wallet Initialization - Authenticated Channel - Cloud

To initialize the wallet, the Wallet obtains wallet attestation as defined in Wallet Attestation.

PID Seed-Credential Issuance

User Journey: PID Issuance - Authenticated Channel - Cloud

PID Seed Credential Issuance over OpenID4VCIPID HolderPIN: (user_pin)PID HolderPIN: (user_pin)User's EUDI Wallet Instance (eID-Client)Device Key: (device_pub,device_priv)Wallet Attestion bound todevice_pubPIN Salt:pin_saltUser's EUDI Wallet Instance (eID-Client)Device Key: (device_pub,device_priv)Wallet Attestion bound todevice_pubPIN Salt:pin_saltPID Provider(eService+eID Server)Long-term Key: (pp_pub,pp_priv)PID Provider(eService+eID Server)Long-term Key: (pp_pub,pp_priv)(001)open wallet, unlock walletScreen: launch_walletScreen: unlock_wallet(002)request issuance of PIDScreen: credential_catalogPID Issuer and EUDI Wallet have inherenttrust relationship, metadata may bepre-configured or retrieved(003)[TLS] HTTP POST</session_endpoint> walletattestation nonce(004)generate and store nonce(005)[TLS] HTTP 200 <walletattestation nonce>(006)create and sign walletattestation PoP JWT (incl.wallet attestation nonce)(007)[TLS] HTTP POST PAR (PKCEcode_challenge, walletattestation JWT, walletattestation PoP JWT,redirect_uri)(008)verify wallet attestation & PoPcheck Wallet Provider solutionstatus on trust list(009)[TLS] HTTP 200 request_uriAttestation guarantees with high certaintythat Wallet is trustworthy and notmanipulated(010)[TLS] HTTP GET <OpenID4VCIAuthorizationRequest(request_uri)>Screen: consent_add_credentialScreen: eid_startRead eID or Smart eID acc. to BSI TR-03130(011)[TLS] starting the eID Process(012)eID Process(013)<eID-PIN>Screen: eid_pin(014)eID Processall PID attributes are requested(015)[TLS] HTTP GET finishing theeID process with refreshUrlScreen: eid_nfc_data(016)[TLS] HTTP 302 <OpenID4VCIAuthorizationResponse(authorizationcode)>(017)[TLS] HTTP POST <TokenRequest(authorization code,PKCE code_verifier, DPoPHeader)>(018)lookup authorization codegenerate TokenResponse withDPoP access tokenverify PKCE challenge(019)[TLS] HTTP 200 <TokenResponse(DPoP-boundaccess_token, c_nonce)>set PID PIN(020)generate and store AES key:pin_salt(021)set PID PINScreen: set_pid_pin(022)generate key pair(pin_derived_eph_pub,pin_derived_eph_priv) fromKDF(encrypt_AES(pin_salt,PIN), PIN)(023)generate PoP for pin derivedephemeral key - sign(nonce,device_pub) pin_derived_eph_priv(024)generate PoP for device_key -sign(nonce,pin_derived_eph_pub)device_priv(025)generate credential responseencryption key pair(cre_eph_pub, cre_eph_priv)(026)createcredential_response_encryptionobject with jwk containingcre_eph_pub(027)[TLS] HTTP POST <CredentialRequest(DPoP-bound accesstoken, new credential format"seed_credential",pin_derived_eph_pub, PoP forpin derived ephemeral key,proof (PoP for device_key),credential_response_encryptionobject>(028)lookup access token(029)check signatures on the PoPs(030)Set up retry counter and savetogether withpin_derived_eph_pub usinghash(device_pub) as identifier(031)generate PID seed credentialwith eID data, device_pub andsigned by pp_priv(032)generate encrypted credentialresponse JWT using the valuesreceived in thecredential_response_encryptionobject(033)[TLS] HTTP 200<JWT(CredentialResponse(seed credentialJWT))>(034)decrypt credential responseJWT and retrieve seedcredential JWT(035)store seed credentialScreen: successScreen: home

PID Presentation

User Journey: PID Presentation - Authenticated Channel - Cloud

PID presentation over OpenID4VP and On-the-fly PID Issuance over OpenID4VCI with SD-JWTUserOpenID HolderUserOpenID HolderBrowser App(same device)Browser App(same device)Relying PartyLong-term Key: (rp_pub,rp_priv)Relying PartyLong-term Key: (rp_pub,rp_priv)User's EUDI Wallet Instance (eID-Client)Device Key: (device_pub,device_priv)PIN Salt:pin_saltUser's EUDI Wallet Instance (eID-Client)Device Key: (device_pub,device_priv)PIN Salt:pin_saltPID Provider(eService+eID Server)Long-term Key: (pp_pub,pp_priv)PID Provider(eService+eID Server)Long-term Key: (pp_pub,pp_priv)(001)browse to applicationScreen: same_device_relying_party_start(002)[TLS] HTTP GET <rp-website>(003)generate ephemeral key pair(rp_eph_pub, rp_eph_priv)every RP in the ecosystem must alwaysinclude ephemeral key in client metadata forECDH-KA for MAC(004)create OpenID4VPAuthorization Request, sign with rp_priv, store under <request_uri>Authorization Request includes:- presentation_definition- purpose- state- nonce- rp_eph_pub with PoP bound to client_id- response_uri(005)generate new browser sessionsession_id and bind theauthorization request to it(006)[TLS] HTTP 200 HTMLcontaining wallet-linkopenid4vp://authorize?")client_id=..&request_uri=<request_uri>Set-Cookie: sid=session_id(007)action to start flow/launchwallet(008)launch with wallet-linkopenid4vp://Potential security risk: Wallet app may bespoofed by malicious appScreen: launch_wallet(009)unlock walletmay be moved to later point in flow orremoved, see notes.Screen: unlock_wallet(010)[TLS] HTTP GET<request_uri>Potential privacy risk: RP learns existence ofwallet app and potentially identifyinginformation (e.g., headers)(011)[TLS] HTTP 200 <JWT-SecuredAuthorization Request>(012)validate AuthorizationRequest JWT using rp_pubrp_pub can be retrieved from metadata usingthe RP client_id(013)user consent to present PID toRelying Party for givenpurposeScreen: consent_present_credential(014)[TLS] HTTP POST</session_endpoint> PIDissuer session id(015)generate and storepid_issuer_session_id(016)[TLS] HTTP 200<pid_issuer_session_id>(017)load PID seed credential fromcredential store(018)enter PID PINScreen: pid_pin(019)generate key pair(pin_derived_eph_pub,pin_derived_eph_priv) fromKDF(encrypt_AES(pin_salt,PIN), PIN)(020)generate PoP for pin derivedephemeral key -sign(pid_issuer_session_id |device_pub)pin_derived_eph_priv(021)generate PoP for device_key -sign(pid_issuer_session_id |pin_derived_eph_pub)device_priv(022)Wallet fetches fresh walletattestation from WalletBackend and generates PoPwith pid_issuer_session_idon demand PID issuance(023)[TLS] HTTP POST TokenRequest(PoP for pin derivedephemeral key, PoP fordevice_key, seed credential,grant_type=urn:ietf:params:oauth:grant-type:seed_credential,wallet_attestation and PoP,DPoP key)seed credential presentation serves as grantto get access token. new grant type(urn:ietf:params:oauth:grant-type:seed_credential)is defined in this document.the seed credential + PoP (PoP for pinderived ephemeral key + PoP for device_key)is used to authenticate with the PID issuerand convey the user data required togenerate the actual PID(024)verify wallet attestation & PoPcheck Wallet Provider solutionstatus on trust list(025)load pin retry counter andpin_derived_eph_pub forhash(device_pub)(026)check user pin retryrequest would be refused in case of lockedpin(027)check signaturesuser pin retry counter would be increased incase of failed pin signature check, user pinwould be locked after threshold is exeeded(028)store user data from seed PIDin session(029)generate TokenResponse withDPoP-bound access token(030)[TLS] HTTP 200 TokenResponse(DPoP-boundaccess_token, c_nonce)(031)generate credential responseencryption key pair(cre_eph_pub, cre_eph_priv)(032)createcredential_response_encryptionobject with jwk containingcre_eph_pubalt[B.1.1: ISO mdoc](033)calculateSessionTranscript(mDocGeneratedNonce,clientId, responseUri, nonceprovided by the Verifier in thepresentation request)(034)[TLS] Credential Request(DPoP-bound access token,rp_eph_pub,credential_response_encryptionobject, SessionTranscript)-rp_eph_pub is sent in `verifier_pub`parameter-SessionTranscript is sent in`session_transcript` parameter-no `proof`/`proofs` parameters(035)generate device key pair(pp_eph_pub, pp_eph_priv), create issuerAuth withpp_eph_pub and w/o dataitems and sign with pp_priv[B.1.2: SD-JWT VC](036)generate ephemeral key pairfor KB-JWT (kb_eph_pub,kb_eph_priv) and sign nonce(037)[TLS] Credential Request(DPoP-bound access token,rp_eph_pub,credential_response_encryptionobject, kb_eph_pub)rp_eph_pub is sent in `verifier_pub`parameter(038)generate issuer key pair(pp_eph_pub, pp_eph_priv), create certificate for chainwith pp_eph_pub as x5cheader and sign with pp_priv(039)perform DH key exchangewith rp_eph_pub andpp_eph_priv, generate shared secret kand derive MAC key for PIDECDH-MAC not specified for JOSE yetSD-JWT is HMAC'd, not signedalt[B.1.1: ISO mdoc](040)create deviceAuth using MACkey with eID data andSessionTranscript provided bythe Wallet(041)generate encrypted credentialresponse JWT using the valuesreceived in thecredential_response_encryptionobject(042)[TLS] HTTP 200JWT(CredentialResponse(mdoc))(043)decrypt credential responseJWT and retrieve PID[B.1.2: SD-JWT VC](044)- create SD-JWT with eID data,include kb_eph_pub and x5cwith pp_eph_pub, HMAC usingMAC key(045)generate encrypted credentialresponse JWT using the valuesreceived in thecredential_response_encryptionobject(046)[TLS] HTTP 200JWT(CredentialResponse(SD-JWT +Disclosures))SD-JWT contains no KB-JWT(047)decrypt credential responseJWT and retrieve PID(048)Assemble SD-JWT withrespective disclosures andcreate KB-JWT payload withnonce, audience, and hash ofSD-JWT and selecteddisclosures and sign withkb_eph_priv(049)create vp_token andpresentation_submission(050)add mDL presentationaccording to<presentation_definition>with <nonce> to vp_tokenand presentation_submissionWallet may add presentations with keysunder its own control as thecommunication channel between Relying Partand PID Provider is not E2EE(051)[TLS] HTTP POST encrypted<AuthorizationResponse(presentation_submission,vp_token, state)>(052)look up state in existingsessionscreate & store response_codefor session(053)[TLS] HTTP 200 <redirect_uriincl. response_code>(054)launch browser with<redirect_uri withresponse_code>Screen: success_redirect(055)[TLS] HTTP GET <redirect_uriwith response_code>Cookie: sid=session_id(056)look up session withsession_id and matchresponse_code(057)perform DH key exchangewith rp_eph_priv from sessionand pp_eph_pub, generate shared secret k derive MAC keyalt[B.1.1: ISO mdoc](058)verify contents of<vp_token>:- verify mdocissuerAuth/deviceAuth PIDwith MAC key- calculate and validatecorrect SessionTranscript[B.1.2: SD-JWT VC](059)verify contents of<vp_token>:- verify SD-JWT PID with MACkey- verify KB-JWT withkb_eph_pub from SD-JWT- validate nonce and audiencefrom KB-JWT(060)[TLS] HTTP 200 <HTML withcontinued UX flow>Screen: same_device_relying_party_identified

Step-by-Step Description

PID Seed-Credential Issuance

  1. The User opens the Wallet App
  2. The User requests a PID issuance
  3. The Wallet requests a fresh nonce for the wallet attestation nonce from the PID Provider (wallet attestation nonce)
  4. The PID Provider generates a fresh nonce linked to the issuance session
  5. The PID Provider returns the wallet attestation nonce to the Wallet
  6. The Wallet generates a Wallet Attestation PoP and signs it with device_priv; containing
  7. audience
  8. expiration time
  9. wallet attestation nonce
  10. The wallet sends the Pushed Authorization Request to the PID Provider; containing
  11. PKCE code_challenge
  12. wallet attestation + PoP
  13. The PID Provider verifies the wallet attestation and its proof of possession and validates the certification status of the Wallet Solution on a trust list
  14. The PID Provider returns a request_uri that is bound to the Pushed Authorization Request
  15. The Wallet sends the Authorization Request containing the PAR request_uri.
  16. The Wallet starts user authentication process using eID by sending a redirect (303) to the eID Server in response to the Authorization Request.
  17. Further communication is exchanged to perform the eID process.
  18. The user provides the eID PIN to the wallet app.
  19. Further communication is exchanged to perform the eID process
  20. The eID process is finished and as a final step the Wallet sends a request to the PID Provider calling the refreshURL.
  21. The PID Provider responds to the Wallet with an Authorization Response in response to a request sent as part of an eID process. It contains the authorization code.
  22. The Wallet sends a Token Request to the PID Provider; containing:
    • the authorization code from Authorization Response
    • the PKCE code_verifier matching the code_challenge from Authorization Request
    • a DPoP key
  23. The PID Provider matches the code and verifies the PKCE code_verifier to the previously received code_challenge. It then generates an access token bound to the DPoP key.
  24. The PID Provider sends a Token Response; containing
    • DPoP-bound access token
    • c_nonce
  25. The Wallet generates an AES key (pin_salt)
    • This key will be used to generate a salt used by the PID PIN key derivation mechanism
  26. The User enters the new PID PIN (most likely twice to ensure that the user has entered the intended PIN)
  27. The Wallet generates the key pair (pin_derived_eph_pub/priv) derived from the PID PIN
    • This key pair is used as knowledge factor for authentication with the PID Provider and is discarded after every use
    • Description of the key derivation:
      • encryption of the PID PIN with an AES key bound to the device -> pin_secret
        • Used to generate a salt for the KDF used in the next step.
        • Could possibly be replaced by the generation & storage of a conventional salt (due to differences in AES in iOS/Android)
      • use of pin_secret and PID PIN in a KDF -> pin_seed
        • Generates a cryptographic secret from the PIN and the salt (pin_secret) for use as a seed for creating the key pair in the next step
      • use pin_seed to seed the EC key generation -> pin_derived_eph_pub and pin_derived_eph_priv
  28. The Wallet signs over the nonce and the device-bound public key device_pub using the key pin_derived_eph_priv
    • This is a Proof of Knowledge (over the PID PIN) realized as a Proof of Possession
    • The nonce is c_nonce received in Token Response
    • The nonce and the device_pub key are included as JWT claims
  29. The Wallet signs over the nonce and the PID PIN derived public key pin_derived_eph_pub using the key device_priv
    • This is a Proof of Possession over the device bound key
    • The nonce is c_nonce received in Token Response
    • The nonce and the pin_derived_eph_pub key are included as JWT claims
    • It contains audience, expiration time
  30. The Wallet generates a new ephemeral keypair (cre_eph_pub, cre_eph_priv).
  31. 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
  32. The Wallet sends a Credential Request to the PID Provider for a newly defined credential format seed_credential; containing
    • the DpoP-bound access token
    • PoP for device_key (in a proof parameter)
    • PoP for pin_derived_eph_pub containing pin_derived_eph_pub
    • the credential_response_encryption object
  33. The Issuer validates the access token and PoP
  34. The PID Provider validates the PoPs for pin_derived_eph and *device_key*s
  35. The PID Provider sets up the retry counter for the PID PIN and stores it with pin_derived_eph_pub under their identifier: hash(device_pub)
  36. The PID Provider generates the Seed Credential with eID data, device_pub and signed by pp_priv
  37. The PID Provider creates an encrypted JWT (JWE) using the values received in the credential_response_encryption object and adds (among others) the Seed Credential JWT to the payload.
  38. The PID Provider sends the Credential Response JWT; containing:
    • Seed Credential as JWT
  39. The Wallet decrypts the Credential Response JWT using the cre_eph_priv and retrieves the Seed Credential JWT.
  40. The Wallet stores the Seed Credential.

PID Presentation

Note: While certain assumptions about session management of the Relaying Party are made here, the concrete implementation is considered out of scope for this document. The usual security considerations for web session management apply.

  1. User browses to Relying Party (RP) website
  2. Browser app on the user's device opens the RP website
  3. RP generates a key pair to be used for ECDH key agreement for SD-JWT HMAC'ing
  4. RP generates an OpenID4VP Authorization Request and stores it under a request_uri (e.g., https://rp.example.com/oidc/request/1234);
  5. The request is bound to the user's browser session
  6. It is signed using a key bound to the RP's metadata that can be retrieved using the RP's client_id
  7. It contains the ephemeral key for ECDH key agreement for SD-JWT HMAC'ing
  8. It contains RP's nonce and state
  9. It contains the RP's response_uri endpoint for sending the Authorization Response over POST
  10. RP generates a new browser session and binds the generated Authorization Request to it
  11. RP returns a HTML page to the browser containing a link to the wallet app (e.g., openid4vp://authorize?client_id=..&request_uri=https://rp.example.com/oidc/request/1234); a cookie with the browser session id is set
  12. The user clicks on the link
  13. The RP website navigates to the custom scheme link to launch the wallet app
  14. The user unlocks the wallet app (see notes below)
  15. The wallet app retrieves the Authorization Request from the RP website (e.g., https://rp.example.com/oidc/request/1234)
  16. The wallet app receives the Authorization Request
  17. The wallet app validates the Authorization Request using the RP's public key
    • Was the signature valid and the key bound to the RP's metadata?
    • Security: This ensures that the Authorization Request was not tampered with; it does not ensure that the party that sent the Authorization Request is the RP.
  18. The Wallet displays information about the identity of the Relying Party and the purpose, the user gives consent to present the PID.
  19. The Wallet requests a fresh PID issuer session id from the PID Provider (pid_issuer_session_id)
  20. The PID Provider generates a fresh session id linked to the session
  21. The PID Provider returns the PID issuer session id to the Wallet
  22. The Wallet loads the PID seed credential from the credential store
  23. The User enters the PID PIN
  24. The Wallet generates the key pair (pin_derived_eph_pub/priv) derived from the PID PIN
    • See PID Seed-Credential Issuance Steps 20 to 22 for a detailed description of the authentication process
  25. The Wallet signs over the PID issuer session id and the device-bound public key device_pub using the key pin_derived_eph_priv
  26. The Wallet signs over the PID issuer session id and the PID PIN derived public key pin_derived_eph_pub using the key device_priv
  27. The Wallet fetches fresh wallet attestation from the Wallet Provider backend, generates proof of possession PoP (incl. PID issuer session id)
  28. The wallet sends a Token Request to the PID Provider; containing
    • PoP for pin_derived_eph key
    • PoP for device_key
    • Seed Credential (bound to device_pub)
    • Wallet Attestation + PoP (incl. pid_provider_session_id)
    • a DPoP key
    • grant_type (urn:ietf:params:oauth:grant-type:seed_credential)
      • seed credential + Wallet attestation PoP (both bound to the same key) + PoP for pin_derived_eph and device_key serves as grant to get access token. New grant type (urn:ietf:params:oauth:grant-type:seed_credential) is defined in this document.
  29. The PID Provider verifies the wallet attestation and its proof of possession and validates the certification status of the Wallet Solution on a trust list
  30. The PID Provider loads the retry counter and pin_derived_eph_pub with the identifier hash(device_pub)
  31. The PID Provider checks the users PID PIN retry counter
    • If the PIN retry counter has exceeded the defined maximum value, the request is rejected
  32. The PID Provider validates the PoP for pin_derived_eph and device_key
  33. The PID Provider stores the user data from the PID seed credential in the session
  34. The PID Provider generates a TokenResponse with a DPoP-bound access token
  35. The PID Provider sends a Token Response; containing
    • DPoP-bound access token
    • a c_nonce
  36. The Wallet generates a new ephemeral keypair (cre_eph_pub, cre_eph_priv).
  37. 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
  38. (mdoc) The Wallet calculates the SessionTranscript according to ISO-18013-7 Annex B.4.4 from mDocGeneratedNonce, client_id, responseUri, nonce (provided by the Verifier in the presentation request). The final result is a SHA-256 hash, thus not revealing the client_id and ResponseUri to the PID Provider.
  39. (mdoc) The Wallet sends a Credential Request; containing
    • the DPoP-bound access token
    • SessionTranscript(mdocGeneratedNonce, client_id, responseUri, nonce)
    • the ephemeral RP key rp_eph_pub from the RP's Authorization Request
    • the credential_response_encryption object
    • it does not contain a "proof"
  40. (mdoc) The PID Provider generate an ephemeral DeviceKey pair (pp_eph_pub,pp_eph_priv) and creates the mdoc issuerAuth (MSO) with the public part of DeviceKey and without the IssuerSignedItems and signs it with pp_priv.
  41. (SD-JWT) The Wallet generates an ephemeral key pair for the KB-JWT (kb_eph_pub, kb_eph_priv) and signs the nonce
  42. (SD-JWT) The wallet app sends the Credential Request to the PID Provider; containing
    • the DPoP-bound access token
    • the ephemeral RP key rp_eph_pub from the RP's authorization request
    • the credential_response_encryption object
    • the ephemeral KB-JWT key kb_eph_pub
  43. (SD-JWT) The PID Provider generates the ephemeral issuer key pair (pp_eph_pub, pp_eph_priv) and creates a certificate for the chain with pp_eph_pub as x5c header and signs it with pp_priv.
  44. The PID Provider performs DH key exchange with the ephemeral RP public key rp_eph_pub and the ephemeral issuer private key pp_eph_priv, generates a shared secret k and derives a MAC key for the PID.
  45. (mdoc) The PID Provider creates the mdoc deviceAuth (using the MAC key) containing
    • the user claims
    • the OpenID4VP SessionTranscript(mdocGeneratedNonce, client_id, responseUri, nonce)
    • SessionTranscript used by the PID Provider is generated by the Wallet and is passed to the PID Provider in step 32, so PID Provider does not need to be aware of the values used to generate SessionTranscript
  46. (mdoc) The PID Provider creates an encrypted JWT (JWE) using the values received in the credential_response_encryption object and adds (among others) the PID credential to the payload.
  47. (mdoc) The PID Provider sends the Credential Response JWT; containing:
    • PID as mdoc
  48. (mdoc) The Wallet decrypts the Credential Response JWT using the cre_eph_priv and retrieves the PID.
  49. (SD-JWT) The PID Provider creates the issuer-signed part of the SD-JWT (using the MAC key) containing
    • eID as the user claims
    • kb_eph_pub as cnf claim
  50. (SD-JWT) The PID Provider creates an encrypted JWT (JWE) using the values received in the credential_response_encryption object and adds (among others) the PID credential to the payload.
  51. (SD-JWT) The PID Provider sends the Credential Response JWT; containing:
    • PID as SD-JWT VC
    • Disclosures
  52. (SD-JWT) The Wallet decrypts the Credential Response JWT using the cre_eph_priv and retrieves the PID.
  53. (SD-JWT) The Wallet assembles the SD-JWT with the selected disclosures and creates the header and payload for the KB-JWT from audience, nonce, and the hash of SD-JWT and selected disclosures and signs it with its generated kb_eph_priv. The Wallet appends the KB-JWT to the SD-JWT + Disclosures.
  54. The wallet app creates a VP token and a presentation submission from the received SD-JWT PID.
  55. Optional: The wallet app can add further presentations with keys under its own control as the communication channel between Relying Party and PID Provider is not E2EE
  56. The wallet app sends the VP token and presentation submission to the RP (encrypted to the RP's public key rp_eph_pub).
  57. The RP finds a session with the state and generates a response_code for this session
  58. The RP returns the redirect_uri with the response_code to the wallet app
  59. The wallet app launches the browser with the redirect_uri and response_code.
  60. The browser sends the redirect_uri and response code to the RP, attaching the browser session id as a cookie.
  61. The RP looks up whether there exists a session with the session id from the cookie and a matching response_code
  62. Using the data from the session the RP performs DH key exchange with the PID Provider's public key, generates a shared secret k and derives a MAC key.
  63. (mdoc) The RP verifies the PID in the VP token with the MAC key and verifies the SessionTranscript.
  64. (SD-JWT) The RP verifies the SD-JWT PID in the VP token with the MAC key, verifies the KB-JWT using the kb_eph_pub in the SD-JWT, and verifies the nonce and audience in the KB-JWT
  65. The RP considers the user to be identified in the session context and continues the UX flow.

Extensions to the Protocols

This section defines extensions to the protocols required to implement this flow (Option B').

In this document, the term RP has been used, but this since this section is an extension to an OpenID4VCI protocol, a term from that specification is being used, which is verifier.

Issuer Session Endpoint (at the PID Provider)

Note that this extension is the same across multiple flows.

This endpoint is used by the Wallet to obtain session_id from the PID Provider that is used to bind PoPs to the session and prove their freshness. Support for this endpoint is REQUIRED.

To fetch the session_id, the Wallet MUST send an HTTP request using the POST method and the application/json media type. The PID Provider MUST return the HTTP Status Code 200 and a session_id parameter defined below.

  • session_id: REQUIRED. String that is a unique session identifier, chosen as a cryptographically random nonce with at least 128 bits of entropy.

Communication with the Session Endpoint MUST utilize TLS.

Below is a non-normative example of a request to a Session Endpoint:

POST /session_endpoint HTTP/1.1
Host: server.example.com
Content-Type: application/json

Below is a non-normative example of a response from a Session Endpoint:

HTTP/1.1 200 OK
Content-Type: application/json
Cache-Control: no-store

{
  "session_id": "iOiJSUzI1NiIsInR"
}

OpenID4VCI Credential Issuer Metadata

Note that this extension is the same across multiple flows.

This document defines the following additional Credential Issuer Metadata parameters:

  • session_endpoint: REQUIRED. URL of the Credential Issuer's Session Endpoint, as defined in a previous section. This URL MUST use the https scheme and MAY contain port, path, and query parameter components.

OpenID4VCI Credential Request for Seed Credential Issuance

This section defines a Credential Format Profile for a Seed Credential.

The Credential Format identifier is seed_credential.

The following Credential Format specific parameter must be included in the Credential Request to issue a seed credential of this format: - pin_derived_eph_key_pop: A string containing a JWT which is generated by the Wallet signing over the nonce (c_nonce received in Token Response) and the device-bound public key device_key parameters using the pin_derived_eph_priv key. A PIN-derived ephemeral public key that is needed to validate the signature on this JWT must be included in the jwk header parameter. The JWT header must contain a typ key with the value being pin_derived_eph_pub_pop. The JWT payload must contain an aud claim whose value is equal to the PID Provider's Credential Issuer Identifier.

Either a proof parameter or a proofs parameter containing one proof must be present. Proof type must be jwt. A proof MUST be a JWT which is generated by the Wallet signing over the nonce (c_nonce received in Token Response) and the pin_derived_eph_pub using the device_key. A device_pub key that is needed to validate the signature on this JWT must be included in the jwk Header parameter.

Below is a non-normative example of a Credential Request during Seed Credential issuance:

POST /credential HTTP/1.1
Host: server.example.com
Content-Type: application/json
Authorization: DPoP czZCaGRSa3F0MzpnWDFmQmF0M2JW
DPoP: ey…

{
  "format": "seed_credential",
  "pin_derived_eph_key_pop": "eyJ0eX...Lh1WlA",
  "proof": {
    "proof_type": "jwt",
    "jwt": "eyJraW...KPxgihac0aW9E"
  },
  "credential_response_encryption": {
    "jwk": {
      "kty": "EC",
      "crv": "P-256",
      "x": "Q71r9rep9wGjorxnnTrxzrN6CxJTc_0vucTkAQSFSzM",
      "y": "jh7gtLKEMH2PQ6hz2USSvsMAvhyF90OBScZ9KJ-1Z-o"
    },
    "alg": "ECDH-ES",
    "enc": "A256GCM"
  }
}

Below is a non-normative example of a JWT sent in a pin_derived_eph_key_pop parameter used as a PoP for pin derived ephemeral key during Seed Credential issuance:

{
  "alg": "...",
  "typ": "pin_derived_eph_key_pop",
  "jwk": {
    "kty": "EC",
    "crv": "P-256",
    "x": "bPP7f...gW_ao",
    "y": "38_Lg...VUCfW"
  }
}.
{
  "nonce": "123456",
  "aud": "https://pid-issuer.example.com",
  "device_key": {
    "jwk": {
      "kty": "EC",
      "crv": "P-256",
      "x": "...",
      "y": "..."
    }
  }
}.[signature by the pin derived ephemeral pub key]

The jwk claim contains the public key of a PIN-derived ephemeral key pair.

Below is a non-normative example of a JWT used as a proof during Seed Credential issuance, which is a PoP for device_key:

{
  "alg": "...",
  "typ": "openid4vci-proof+jwt",
  "jwk": {
    "kty": "EC",
    "crv": "P-256",
    "x": "...",
    "y": "..."
  }
}.
{
  "nonce": "123456",
  "pin_derived_eph_pub": {
    "jwk": {
    "kty": "EC",
    "crv": "P-256",
    "x": "V03QP...LHN53",
    "y": "xjilK...i0_tT"
    }
  },
  "aud": "https://pid-issuer.example.com",
  "iat": 1701960444
}.[signature by the device_key]

Here, the jwk claim contains a public key of a device key pair.

The payload contains aud and iat claims and the header contains alg and typ claims, which is a requirement for jwt proof type as defined in OpenID4VCI specification.

Below is a non-normative example of a Credential Response JWT (JWE) during the during Seed Credential issuance::

HTTP/1.1 200 OK
Content-Type: application/jwt
Cache-Control: no-store

{
  "epk": {
    "kty": "EC",
    "crv": "P-256",
    "x": "GNIg9Vdq4gytYyVsANPZGtS_eKWjjWJQYDGaM1olFZI",
    "y": "Vjk0mlZD_CwXrtIJkPH-ZzdwqJp3QBRVp83pEeQUDC0"
  },
  "enc": "A256GCM",
  "alg": "ECDH-ES"
}..
3tQxSrYcfmbEWw-Y.
yp9e0Kh0THo498bg5nnUIpkS-CwxlS8i6G9RfZBOzUOeohaVnAPAWHY.
PhU-FNmCt_ZZPzj5RgPNmQ

The decrypted payload of the Credential Response JWT example results in the following structure:

{
  "credential": "<Seed Credential JWT>"
}

OpenID4VCI Token Request for PID Issuance using Seed Credential

A new grant type urn:ietf:params:oauth:grant-type:seed_credential is defined by this document.

The following parameters must be included in the Token Request: - seed_credential: A string containing a JWT that is a previously issued seed credential. - pin_derived_eph_pub_pop: A string containing a JWT which is generated by the Wallet signing over the pid_issuer_session_id and the device-bound public key device_key parameters using the pin_derived_eph_priv key. A PIN-derived ephemeral public key that is needed to validate the signature on this JWT must be included in the jwk header parameter. There must be a JWT header parameter typ with the value being pin_derived_eph_pub_pop. The JWT payload must contain an aud claim whose value is equal to the PID Provider's Credential Issuer Identifier. - device_key_pop: A string containing a JWT which is generated by the Wallet signing over the pid_issuer_session_id and the device-bound public key pin_derived_eph_pub parameters using the device_priv key. A device public key that is needed to validate the signature on this JWT must be included in the jwk header parameter. There must be a JWT header parameter typ with the value being device_key_pop. The JWT payload must contain an aud claim whose value is equal to the PID Provider's Credential Issuer Identifier.

Below is a non-normative example of a Token Request during the PID issuance (including DPoP and wallet attestation):

POST /token HTTP/1.1
Host: server.example.com
Content-Type: application/x-www-form-urlencoded
DPoP: ey...
OAuth-Client-Attestation: ey...
OAuth-Client-Attestation-PoP: ey...

grant_type=urn:ietf:params:oauth:grant-type:seed_credential
&seed_credential=ey...
&pin_derived_eph_key_pop=ey...
&device_key_pop=ey...

Note: client_id will be present instead of OAuth-Client-Attestation and OAuth-Client-Attestation-PoP headers used to pass wallet attestation, when wallet attestation is not used.

Below is a non-normative example of a JWT sent in a pin_derived_eph_key_pop parameter used as a PoP for pin derived ephemeral key during PID issuance:

{
  "alg": "...",
  "typ": "pin_derived_eph_key_pop",
  "jwk": {
    "kty": "EC",
    "crv": "P-256",
    "x": "bPP7f...gW_ao",
    "y": "38_Lg...VUCfW"
  }
}.
{
  "pid_issuer_session_id": "123456",
  "aud": "https://pid-issuer.example.com",
  "device_key": {
    "jwk": {
      "kty": "EC",
      "crv": "P-256",
      "x": "...",
      "y": "..."
    }
  }
}.[signature by the pin derived ephemeral pub key]

The jwk claim contains the public key of a PIN-derived ephemeral key pair.

Below is a non-normative example of a JWT used as a proof during PID issuance, which is a PoP for device_key:

{
  "alg": "...",
  "typ": "device_key_pop",
  "jwk": {
    "kty": "EC",
    "crv": "P-256",
    "x": "...",
    "y": "..."
  }
}.
{
  "pid_issuer_session_id": "123456",
  "aud": "https://pid-issuer.example.com",
  "pin_derived_eph_pub": {
    "jwk": {
    "kty": "EC",
    "crv": "P-256",
    "x": "V03QP...LHN53",
    "y": "xjilK...i0_tT"
    }
  },
}.[signature by the device_key]

Here, the jwk claim contains a public key of a device key pair.

OpenID4VCI Credential Request and Response for PID Issuance in mdoc Credential Format using Authenticated Channel

Note that this section is the same as in Option B.

Credential Format identifier is mso_mdoc_authenticated_channel.

The following parameters are defined in addition to those defined for the Credential Format mso_mdoc in Annex A.2 of OpenId4VCI: * session_transcript: REQUIRED. String that is a base64url encoded SessionTranscriptBytes as defined in Section 9.1.5.1 of ISO 18013-5. * verifier_pub: REQUIRED. A JSON object as defined in Section 2 of RFC7591. It contains the ephemeral RP key rp_eph_pub from the RP's Authorization Request.

proof or proofs parameter MUST NOT be present.

DPoP-bound Access token MUST be present.

credential_response_encryption parameter MUST be present. Note: The wallet can find out about the supported cryptographic algorithms by using the Issuer's metadata parameter credential_response_encryption.

Below is a non-normative example of a Credential Request during the PID issuance in ISO mso Credential Format over Authenticated Channel:

POST /credential HTTP/1.1
Host: server.example.com
Content-Type: application/json
Authorization: DPoP czZCaGRSa3F0MzpnWDFmQmF0M2JW
DPoP: ey…

{
  "format": "mso_mdoc_authenticated_channel",
  "doctype": "org.iso.18013.5.1.mDL",
  "session_transcript": "...",
  "verifier_pub": {
    "kty": "EC",
    "crv": "P-256",
    "x": "aPPK-...2-Drn",
    "y": "FqJqG...ksKHp"
  },
  "credential_response_encryption": {
    "jwk": {
      "kty": "EC",
      "crv": "P-256",
      "x": "1SptQyCUQiQD3dBcVHTclxRtcqhZlF1rIKcBR-i_WK4",
      "y": "8ayoQrh52zNuRQx8Q0gpmCpOjzbH397mOsaSi8X10c4"
    },
    "alg": "ECDH-ES",
    "enc": "A256GCM"
  }
}

credential parameter in the Credential Response MUST contain a base64url-encoded Document which contains IssuerSigned and the DeviceSigned parameters defined in section 8.3.2.1.2.2 of 18013-5.

The Device key included in the IssuerSigned and used to secure DeviceSigned is generated by the PID Provider, and not by the Wallet as defined in ISO 18013-5.

SessionTranscript used by the PID Provider when calculating DeviceSigned is calculated by the Wallet. Therefore, there is no need for the PID Provider to know the specific values of mdocGeneratedNonce, client_id, responseUri, and nonce parameters used for SessionTranscript calculation by the Wallet. Moreover, there is also no way for the PID Provider to reconstruct these values, as the SessionTranscript is hashed and contains random values chosen by the wallet (i.e. mdocGeneratedNonce).

Below is a non-normative example of a Credential Response JWT (JWE) during the PID issuance in mso Credential Format over Authenticated Channel:

HTTP/1.1 200 OK
Content-Type: application/jwt
Cache-Control: no-store

{
  "epk": {
    "kty": "EC",
    "crv": "P-256",
    "x": "VJUVl-ZqLKzzncZ4Gs_nJfcqY_YBHPkGVN0sRSlF-3s",
    "y": "y4maAWKte676d0wL6um-8wAUJ9pW-mlc528BFeiXn2Y"
  },
  "enc": "A256GCM",
  "alg": "ECDH-ES"
}..
nLuW9PwrGl76pjTy.
nH_XE2LJ2u-N0o8M-tanqoYhJr7hbjo.
3uNrPqJazT9ZSf54sk1Ueg

The decrypted payload of the Credential Response JWT example results in the following structure:

{
  "credential": "..."
}

OpenID4VCI Credential Request and Response for PID Issuance in SD-JWT Credential Format using Authenticated Channel

Note that this section is the same as in Option B.

The following parameter is defined in addition to those defined for the Credential Format vc+sd-jwt in Annex A.3 of OpenId4VCI: * verifier_pub: REQUIRED. A JSON object as defined in Section 2 of RFC7591. It contains the ephemeral RP key rp_eph_pub from the RP's Authorization Request.

New Credential Format identifier is not defined PID Issuance in SD-JWT Credential Format using Authenticated Channel, because the issued Credential in the Credential Response is SD-JWT, which is the same as the one defined in Annex A.3 of OpenId4VCI. Since during PID Issuance in SD-JWT Credential Format using Authenticated Channel, not just IssuerSigned, but also DeviceSigned is returned in the Credential Response as part of the Document structure as defined above, it is a significant deviation that necessitated the definition of a new Credential Format identifier mso_mdoc_authenticated_channel.

credential_response_encryption parameter MUST be present. Note: The wallet can find out about the supported cryptographic algorithms for the credential response encryption by using the Issuer's metadata parameter credential_response_encryption.

Below is a non-normative example of a Credential Request during the PID issuance in IETF SD-JWT VC Credential Format over Authenticated Channel: Note: The wallet can find out about the supported cryptographic algorithms by using the Issuer's metadata parameter credential_signing_alg_values_supported.

POST /credential HTTP/1.1
Host: server.example.com
Content-Type: application/json
Authorization: DPoP czZCaGRSa3F0MzpnWDFmQmF0M2JW
DPoP: ey…

{
  "format": "vc+sd-jwt",
  "vct": "SD_JWT_VC_example",
  "proof": {
    "proof_type": "jwt",
    "jwt": "eyJ0e...h1WlA"
  },
  "verifier_pub": {
    "kty": "EC",
    "crv": "P-256",
    "x": "aPPK-...2-Drn",
    "y": "FqJqG...ksKHp"
  },
  "credential_response_encryption": {
    "jwk": {
      "kty": "EC",
      "crv": "P-256",
      "x": "1SptQyCUQiQD3dBcVHTclxRtcqhZlF1rIKcBR-i_WK4",
      "y": "8ayoQrh52zNuRQx8Q0gpmCpOjzbH397mOsaSi8X10c4"
    },
    "alg": "ECDH-ES",
    "enc": "A256GCM"
  }
}

Implementation Considerations

  • The JWA to use the x5c in the SD-JWT and perform ECDH key agreement and derive the MAC key is to be defined.

Usability Considerations

Initialization

  • The wallet can only be used after successful initialization

Issuance

  • Credential catalogue should inform users in advance of what is required for the successful issuance of the PID and what steps follow
    • For reasons of transparency and to increase trust, PID Provider should provide sufficient information (metadata) for the consent screen. This allows users to learn everything relevant e.g. about the PID Provider itself
  • eID process is integrated in Wallet. No context switch to the AusweisApp is requiredPhysical ID card is required for issuing the PID seed credential
  • Online-Ausweisfunktion must be activated
  • eID PIN must be set by the user (replacement of the Transport PIN) and be known to them so that they can successfully confirm the process
  • User can have a PID seed credential derived from the eID on several end devices at the same time
  • A PID-specific PIN must be set. The distinction between eID PIN and PID PIN is certainly not easy for users and must be communicated accordingly
  • In addition to the PID-specific PIN, several PINs will probably be required to use the wallet (especially for LoA High Credentials). This will also require multiple error counters. This can lead to user confusion, unnecessary complexity and ultimately friction

Presentation

  • The device must be online for the PID presentation
  • Relying Party should inform users in advance of what is required for the process to be completed successfully and what steps follow
  • It needs to be clarified whether the wallet app needs to be unlocked in this flow and how this should be implemented.
  • For reasons of transparency and to increase trust, Relying Parties should provide sufficient information (metadata) for the consent screen. This allows users to learn everything relevant e.g. about the relying party itself, privacy and data retention
  • The user's data values for the requested attributes can be displayed on the consent screen
  • The user only needs to enter the PID PIN for each PID presentation
  • Physical ID card is not required for PID presentation
  • It must be ensured that users return to the correct tab in the correct browser in order to continue the process or know how to get there manually if necessary (especially for iOS devices, if the process was not started in the default browser)

Security Considerations

  • It is to be discussed whether the setting of the PID PIN should be more closely linked to the eID process. In this case, the public keys and PoPs required for the PID PIN check could be transferred as an additional attribute in the eID process.
  • In Step 8 of the presentation, a malicious app may spoof the wallet app by registering to the same custom URL scheme; an attacker may
  • on the attacker's own device: Capture the request and replay it to a victim on another device, thus having the victim identify itself in a context of the attacker (Relaying Attack breaking Identification Context); or
  • on the victim's device: Capture the request and spoof the whole identification process or parts of it (Wallet App Spoofing).
  • In Step 10 of the presentation: An attacker acting as an RP can forward a request from a different RP.
  • As long as the request remains unchanged, we're in the Relaying Attack breaking Identification Context
  • If the attacker changes anything in the request, this will break the signature. The attacker could otherwise attempt to
    • insert the attacker's own ephemeral key, leading to an SD-JWT artifact that could be used in a different flow between the attacker and some other RP.
    • modify state or nonce or other data. Q: Any useful attacks resulting from this?
  • In Step 46 of the presentation: The RP must not consider the user identified at this point; it is important to have the browser redirect in the later steps.
  • In Step 11 and onward of the PID Seed Credential issuance: Security of PID Provider Interface:
  • Are additional steps required to protect the interface to the PID Provider?
  • What exactly is the transaction binding?
  • How is the eID process tied to the process at the PID Provider?

Privacy Considerations

  • Due to the differences in the selective disclosure process of SD-JWT VC and mDoc, it is only possible with the SD-JWT variant to prevent the PID Provider from knowing which attributes are to be disclosed to a relying party.
  • An initiating step before the authorization request (Step 10 of the presentation) that is performed without the user's interaction might leak information about the user's device to the RP (Initial Request Privacy Leak). For example:
  • the fact that the wallet app is installed,
  • the fact which wallet app is installed,
  • some metadata about the wallet app contained in request headers (e.g., version, language, etc.),
  • network information if the browser uses a VPN but the wallet app does not
  • Unlinkability: Each Relying Party sees a new credential for each use of the flow. Only ephemeral keys are used. Unless the eID data itself enables linkability, there is no information enabling linkablility between different uses of the flow.

Open Questions

  • Should the purpose be included in the KB-JWT?