PID Option C'': Signed Credential with eID Card¶
Basic Idea¶
In this design, PID credentials are issued on-demand in ISO mdoc / SD-JWT VC format using the OpenID4VCI protocol and directly presented using the OpenID4VP protocol. While this Option is similar to Option B, the PID credentials are signed by the PID Provider for the specific transaction. The user is authenticated by utilizing the eID card towards the PID Provider in every presentation.
In this design, the device key for signing the presentation is generated by the PID Provider in order to achieve a high level of assurance and perform critical key management outside the Wallet. To ensure that the PID Provider does not get to know where a PID credential is used and which claims are provided, the payload of the presentation part (deviceAuth for mdoc or KB-JWT for SD-JWT) is created by the Wallet and only its hash is sent to the PID Provider for signing. This design therefore results in the following properties:
- The complexity of implementation is lower for the Wallet, as it does not need to handle and secure the device key.
- The PID Provider can enforce that there is exactly one presentation for the PID credential, ensuring a tight binding between the eID Card process and the PID presentation.
- It is expected that certification for LoA High is easier for this design, as the PID Provider has full control over all keys and a secure authentication is guaranteed each time via the usage of the eID.
Note that this design assumes that the signing algorithm performs a hashing step on the data first; this step is happening at the Wallet, while the rest of the signing is done at the PID Provider. In particular, this works well with ECDSA.
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); containing
- an ephemeral key in
deviceKeyInfo
- signed hashes in the
valueDigests
- an ephemeral key in
- deviceSignature as mdoc authentication method, a COSE_Sign1 signature over the deviceAuthentication data (see ISO 18013-5 9.1.3.6); containing
- the PID data
- SD-JWT VC: The SD-JWT VC credential format is used with
- SD-JWT signed with JWS by the PID Provider; containing
- an ephemeral key in
cnf
- the signed hashes in
_sd
arrays
- an ephemeral key in
- KB-JWT signed by the PID Provider with the Hash; containing
- nonce and audience of the Relying Party
- a hash of the SD-JWT and the selected disclosures
- Disclosures containing the PID data
Cryptographic Formats¶
(to be defined)
Issuance¶
Long-Term keys:
Transaction-specific keys:
Artifacts:
Presentation¶
Long-Term keys:
Transaction-specific keys:
Artifacts:
Dependencies¶
Sequence Diagram¶
Issuance¶
Step-by-Step Description¶
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.
- User browses to Relying Party (RP) website
- Browser app on the user's device opens the RP website
- RP generates a key pair to be used for response encryption
- RP generates an OpenID4VP Authorization Request and stores it under a
request_uri
(e.g.,https://rp.example.com/oidc/request/1234
); - The request is bound to the user's browser session
- It is signed using a key bound to the RP's metadata that can be retrieved using the RP's client_id
- It contains ephemeral key for response encryption
- It contains RP's nonce and state
- It contains the RP's response_uri endpoint for sending the Authorization Response over POST
- RP generates a new browser session and binds the generated Authorization Request to it
- RP returns an 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 - The user clicks on the link
- The RP website navigates to the custom scheme link to launch the wallet app
- The user unlocks the wallet app (see notes below)
- The wallet app retrieves the Authorization Request from the RP website (e.g.,
https://rp.example.com/oidc/request/1234
) - The wallet app receives the Authorization Request
- 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.
- The Wallet displays information about the identity of the Relying Party and the purpose, the user gives consent to present the PID.
- The Wallet fetches fresh wallet attestation from the Wallet Provider backend.
- The Wallet requests a fresh nonce for the wallet attestation nonce from the PID Provider (wallet attestation nonce).
- The PID Provider generates a fresh nonce linked to the issuance session.
- The PID Provider returns the wallet attestation nonce to the Wallet.
- The Wallet generates a Wallet Attestation PoP and signs it with dev_priv; containing
- audience
- expiration time
- wallet attestation nonce
- The wallet sends the Pushed Authorization Request to the PID Provider; containing
- PKCE code_challenge
- wallet attestation + PoP
- redirect_uri
- an authorization_details object requesting a PID with a list of claims
- 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.
- The PID Provider returns a request_uri that is bound to the Pushed Authorization Request.
- The Wallet sends the Authorization Request; containing
- the PAR request_uri
- The PID Provider responds with the first step to start the eID process with the wallet app, e.g. the tcToken. Note that this is the direct HTTP Response to Step 14.
- Further communication is exchanged to perform the eID process
- The user provides the eID PIN to the wallet app.
- Further communication is exchanged to perform the eID process
- The eID process is finished and as a final step the Wallet sends a request to the PID Provider calling the refreshURL. From now on Wallet and PID Provider are using the TLS-PSK channel generated by the eID flow.
- The PID Provider responds to the Wallet with an Authorization Response; containing
- the auth code
- 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
- a DPoP key
- 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.
- The PID Provider sends a Token Response; containing
- DPoP-bound access token
- a c_nonce
- (mdoc) The Wallet send a Credential Request; containing
- DPoP-bound access token
- sessionTranscript
- it does not contain a "proof"
- (mdoc) The PID Provider looks up and validates the access token.
- (mdoc) The PID Provider generate an ephemeral DeviceKey pair (device_pub,device_priv).
- (mdoc) The PID Provider creates the mdoc issuerSigned; containing
- issuerAuth (MSO) with the public part of DeviceKey and the hashes of the data elements and signs it with pp_priv
- nameSpaces with the data elements
- (mdoc) The PID Provider returns the issuerSigned to the Wallet.
- (mdoc) The Wallet calculates the SessionTranscript according to ISO-18013-7 Annex B.4.4 from mDocGeneratedNonce, client_id, responseUri, nonce. The final result is a SHA-256 hash, thus not revealing the client_id and ResponseUri to the PID Provider.
- (mdoc) The Wallet generates the deviceAuth utilizing the SessionTranscript and the requested data elements for nameSpaces and calculates the hash of it
- (mdoc) The Wallet sends the hash of the deviceAuth to the Presentation Signing Endpoint of the PID Provider; the request is protected by a DPoP-bound access token.
- (mdoc) The PID Provider creates the signature for the deviceAuth hash.
- (mdoc) The PID Provider returns the signature to the Wallet.
- (mdoc) The Wallet creates the mdoc using the issuerAuth, the deviceAuth payload and the deviceAuth signature returned by the PID Provider.
- (SD-JWT) The Wallet send a Credential Request; containing - DPoP-bound access token - it does not contain a "proof"
- (SD-JWT) The PID Provider looks up and validates the access token.
- (SD-JWT) The PID Provider generate an ephemeral DeviceKey pair (device_pub,device_priv).
- (SD-JWT) The PID Provider creates the issuer-signed part of the SD-JWT and signs it with pp_priv; containing
- eID as the user claims
- device_pub as cnf claim
- (SD-JWT) The PID Provider sends the Credential Response; containing:
- SD-JWT VC PID with Disclosures
- (SD-JWT) The Wallet creates the header and payload for the KB-JWT from audience, nonce, and the hash of SD-JWT and selected disclosures and hashes it. The Wallet appends the KB-JWT to the SD-JWT. Note that this step can only happen after the SD-JWT has been issued and received by the Wallet, as the KB-JWT payload includes the sd_hash parameter, that is a hash over issuerSigned JWT and the Disclosures.
- (SD-JWT) The Wallet sends a Request to the Presentation Signing Endpoint transmitting the hash of the KB-JWT. The request is protected by a DPoP-bound access token.
- (SD-JWT) The PID Provider recognizes the device key from the provided public key reference and uses device_priv to create the signature of the KB-JWT using the hash of the KB-JWT. Afterwards, it must ensure that the device key pair is deleted and not used again.
- (SD-JWT) The PID Provider sends the response containing the signature of KB-JWT.
- (SD-JWT) The Wallet assembles the PID presentation from SD-JWT and KB-JWT payload/signature.
- The wallet app creates a VP token and a presentation submission from the received SD-JWT PID.
- Optional: The wallet app can add further presentations with keys under its own control as the communication channel between Relying Part and PID Provider is not E2EE
- The wallet app sends the VP token and presentation submission to the RP (encrypted to the RP's public key rp_eph_pub).
- The RP finds a session with the state and generates a response_code for this session.
- The RP returns the redirect_uri with the response_code to the wallet app.
- The wallet app launches the browser with the redirect_uri and response_code.
- The browser sends the redirect_uri and response code to the RP, attaching the browser session id as a cookie.
- The RP looks up whether there exists a session with the session id from the cookie and a matching response_code
- (mdoc) The RP verifies the PID in the VP token with the MAC key and verifies the SessionTranscript calculated from nonce, mDocGeneratedNonce, clientID, response_uri.
- (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
- The RP considers the user to be identified in the session context and continues the UX flow.
Extensions to the Protocols¶
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:
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"
}
Presentation Signing Endpoint¶
This endpoint is used by the Wallet to obtain a signature over the KB-JWT or deviceAuth structure. Support for this endpoint is REQUIRED.
Communication with this endpoint MUST use TLS and this endpoint MUST be protected using the DPoP-bound access token, similar to the Credential Endpoint.
To fetch the bytes of the signature, the Wallet MUST send an HTTP request using the POST method and the application/json
media type. The request contains a JSON-encoded object with the following parameters:
hash_bytes
: REQUIRED. base64url-encoded bytes of the hash over the bytes of the deviceAuth structure or the KB-JWT structure, respectively. Note that the hash algorithm MUST be matched to the signing algorithm used by the PID Provider for signing the deviceAuth or KB-JWT structure.
The PID Provider MUST return the HTTP Status Code 200 and a signature_bytes
parameter defined below.
signature_bytes
: REQUIRED. base64url-encoded bytes of the signature over the deviceAuth or KB-JWT, respectively.
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 thehttps
scheme and MAY contain port, path, and query parameter components.presentation_signing_endpoint
: REQUIRED: URL of the Presentation Signing Endpoint, as defined above. This URL MUST use thehttps
scheme and MAY contain port, path, and query parameter components.