3.2.2 PID Presentation¶
This flow describes the PID presentation process as introduced here in the blueprint. The PID presentation flow uses the standards following the High-Assurance Interoperability Profile (HAIP) for OpenID4VP as defined in the blueprint:
The current flow allows both Wallets and Verifiers to only use same-device flows, as the cross-device using OpenID4VP redirect-based flows does not fulfil LoA high requirements. In future iterations, cross-device PID presentations may be supported.
Data Flow¶
This section describes the data flow of the PID presentation in a sequence diagram and a more detailed table. Artifacts in italics are further explained in the data register chapter.
Sequence Diagram¶
Detailed Description¶
| No | Description |
|---|---|
| 001 | The user browses to a Relying Party (RP) website using the browser on its Wallet Instance (WI). |
| 002 | The browser calls the Relying Party website, most likely using one or multiple HTTP GET requests. One of these requests triggers the Relying Party's server to generate the OpenID4VP Authorization Request as described in steps 003-008. |
| 003 | The RP generates random values for rp_openid4vp_state and rp_key_binding_nonce with sufficient entropy and an ephemeral response encryption key pair (rp_response_enc_prvk, rp_response_enc_pubk) used for additional application-level encryption with response mode direct_post.jwt. |
| 004 - 005 | The RP creates the OpenID4VP Authorization Request rp_openid4vp_request as a JWT-Secured Authorization Request (JAR) using RFC9101 including:
|
| 006 | The RP stores rp_openid4vp_request as a Pushed Authorization Request according to RFC9126 under rp_request_uri. |
| 007 | The RP creates an HTTP session ID cookie rp_cookie_id and binds it to rp_openid4vp_request. |
| 008 | The RP returns the rp_request_uri and sets the rp_cookie_id (using Set-Cookie HTTP headers). The request is embedded into the HTML code of the website, likely as a button using either the WI's app link or a custom URL scheme such as haip-vp:// for wallet invocation. |
| 009 - 010 | The user initiates the PID presentation on the RP's website, likely by pushing a button. The WI is launched by the operating system, passing the rp_request_uri as a parameter within the app link/custom URL. |
| 011 - 012 | The WI requests the rp_request_uri as a Pushed Authorization Request using a HTTP GET call according to RFC9126. The RP responds with the rp_openid4vp_request as a Pushed Authorization Response that corresponds to the rp_request_uri. |
| 013 | The WI validates the fetched rp_openid4vp_request by:
|
| 014 | The WI matches the available, stored credentials (i.e. the PID and optionally additional credentials) against the RP's requested credentials from rp_dcql_query. The following situations may appear:
|
| 015 - 016 | The WI displays the relevant information from rp_openid4vp_request to the user:
|
| 017 (optional) | If step 014 flagged that the batch of pp_pid_credential is exhausted or expired, the WI triggers a PID re-issuance flow using the pp_refresh_token to obtain a fresh batch before continuing, reusing the user authentication just collected in step 015 - 016. Otherwise, this step is skipped. |
| 018 | The WI prepares the PID presentation and applies the selective disclosure to pp_pid_credential according to rp_dcql_query:
|
| 019 | The WI generates wi_key_binding_data:
|
| 020 | The WI generates the hash wi_key_binding_data_hash from the wi_key_binding_data, as only the hash is passed to the Remote WSCA for signing. |
| 021 - 023 | The WI requests the Remote WSCA Start Session PIN authenticating with two factor authentication (wi_mdvm_prvk and wi_rwsca_pin_prvk derived from user_rwsca_pin). The RWSCA returns the PIN session token (rwsca_pin_session_token) that attests the user authentication. The WI then deletes the user_rwsca_pin and the derived wi_rwsca_pin_prvk. |
| 024 - 026 | The WI sends the Remote WSCA Sign operation authenticating with the possession factor wi_mdvm_prvk and the rwsca_pin_session_token as a proof of user authentication to sign wi_key_binding_data_hash with the rwscd_pid_device_prvk belonging to rwsca_bound_wrapped_key associated to the particular pp_pid_credential. The RWSCA ensures, based on the two factor authentication, that only the account which has created the wscd_pid_device_prvk is allowed to use this key for a signing operation. The RWSCA supported by RWSCD then signs the hashed input data wi_key_binding_data_hash ( without knowing the payload) of wi_key_binding_data using rwscd_pid_device_prvk and responds the signature rwscd_key_binding_signature to the WI. If the presentation process was finished successfully and no further re-issuance is required, the cached rwsca_pin_session_token should be flushed, as explained in the PIN Session token section. |
| 027 | The WI assembles the PID presentation wi_pid_presentation from pp_pid_credential, wi_key_binding_data and rwscd_key_binding_signature and embeds it into the vp_token structure:
|
| 028 - 029 | The WI generates an ephemeral response encryption key pair (wi_response_enc_prvk, wi_response_enc_pubk used for additional application-level encryption with response mode direct_post.jwt. The WI then encrypts wi_pid_presentation using keys derived from Elliptic Curve Diffie-Hellman using wi_response_enc_prvk and rp_response_enc_pubk using JWE. |
| 030 | The WI creates the wi_openid4vp_response from the encrypted wi_pid_presentation and the unencrypted rp_openid4vp_state. |
| 031 | The WI deletes the presented pp_pid_credential and the corresponding rwsca_bound_wrapped_key, as the WI follows a one-time-use policy to enable unlinkability. |
| 032 | The WI sends the OpenID4VP Authorization Response wi_openid4vp_response as a HTTP POST request to the RP's rp_response_uri. |
| 033 | The RP matches the OpenID4VP session using rp_openid4vp_state and store the encrypted wi_pid_presentation without validating it yet. The RP must perform a redirect to the WI's browser first to prevent session fixation attacks. |
| 034 - 035 | The RP therefore creates a unique rp_redirect_uri and binds it to the OpenID4VP session of rp_openid4vp_state and responds to the WI with a HTTP 200 containing the rp_redirect_uri. |
| 036 - 037 | The WI launches the user device browser with rp_redirect_uri. The browser then makes the HTTP GET request to rp_redirect_uri. As the browser has been in this session before, it provides the rp_cookie_id. |
| 038 | The RP matches the browser session using the provided rp_cookie_id and can securely map it to the OpenID4VP session bound to rp_redirect_uri. |
| 039 | The RP decrypts the stored wi_openid4vp_response from Step 030 using keys derived from Elliptic Curve Diffie-Hellman using wi_response_enc_pubk and rp_response_enc_prvk, equivalent to what WI did in Step 029. |
| 040 - 041 | The RP verifies the contents of the wi_pid_presentation using pp_pid_auth_pubk and rwscd_pid_device_pubk and extracts the selectively disclosed es_eid_data:
|
| 042 | The RP responds to the WI in the browser session. |
| 043 | After the presentation, the WI evaluates the remaining batch of one-time-use pp_pid_credential, as one credential is consumed and deleted per presentation (see step 031). The WI optionally triggers a PID re-issuance flow using the pp_refresh_token to refill the batch if either:
|
Batch Credential Refresh¶
The WI uses the PID as a batch of one-time-use pp_pid_credential, requests a batch size of 5 for each format during PID issuance and consumes exactly one credential per PID presentation (see step 031). For a PID, the WI stores a long-lived refresh token and the batch of credentials that is refreshed through it:
- the refresh token, which authorizes a batch refresh via PID re-issuance and is retained across batch refreshes:
- the pp_refresh_token itself
- the rwsca_bound_wrapped_key for rwscd_rt_prvk for DPoP-binding the refresh token
- the expiry of the pp_refresh_token
- the batch, which is fully replaced on each refresh:
- a list of pp_pid_credential in both SD-JWT VC and mdoc format, each with the same dataset and expiry but with different rwscd_pid_device_pubk
- a list of rwsca_bound_wrapped_key for rwscd_pid_device_prvk for each pp_pid_credential
If the WI refreshes a batch of pp_pid_credential, it must delete all remaining credentials and only keep the new batch to ensure they have a homogeneous data set and the same expiry date. The refresh token is not part of the batch and is retained during a batch refresh; it is only renewed through a new eID-authenticated PID issuance once the pp_refresh_token itself has expired.
A batch can no longer be presented in two situations:
- Expiry: the pp_pid_credential are expired, determined by the
expclaim for SD-JWT VC and thevalidityInfo.validUntilclaim for mdoc. - Exhaustion: all pp_pid_credential of a batch have been consumed.
The WI evaluates the batch before a PID presentation (step 017) and after a PID presentation (step 043). The WI triggers a PID re-issuance flow using the pp_refresh_token whenever one of the following refresh conditions is met:
- Expiry:
- before a PID presentation (step 017): pp_pid_credential is expired (as it may not be presented in time to be evaluated as valid by the Relying Party)
- after a PID presentation (step 043): pp_pid_credential expires within
10 days(to avoid a time-consuming refresh before the next PID presentation, while a hidden refresh afterwards will not be noticed by the user)
- Exhaustion:
- before a PID presentation (step 017): remaining count of pp_pid_credential of the requested format is
0 - after a PID presentation (step 043): remaining count of pp_pid_credential of either format is
1or fewer
- before a PID presentation (step 017): remaining count of pp_pid_credential of the requested format is
The user_rwsca_pin should only be entered once by the user and the WI should utilize the rwsca_pin_session_token for the subsequent operations.