PID/(Q)EAA Presentation

This section describes how a Relying Party Instance requests to a Wallet Instance the presentation of the PID/EAAs.

In this section the following flows are described:

  • Remote Flow, where the User presents a Digital Credential to a web Relying Party Instance according to OpenID4VP. In this scenario the user-agent and the Wallet Instance can be used in the same device (Same Device Flow), or in different devices (Cross Device Flow).

  • Proximity Flow, where the User presents a Digital Credential to a mobile Relying Party Instance according to ISO18013-5. The User interacts with a Verifier using proximity connection technologies such as using QR Codes and Bluetooth Low Energy (BLE).

Remote Flow

Depending on whether the User is using a mobile device or a workstation, the Relying Party MUST support the following remote flows:

  • Same Device, the Relying Party MUST provide an HTTP location to the Wallet Instance using a redirect (302) or an HTML href in a web page;

  • Cross Device, the Relying Party MUST provide a QR Code which the User frames with the Wallet Instance.

Once the Wallet Instance establishes the trust with the Relying Party and evaluates the request, the User gives the consent for the disclosure of the Digital Credentials, in the form of a Verifiable Presentation.

_images/High-Level-Flow-Presentation.svg

Fig. 16 High Level Remote Protocol Flow

A High-Level description of the remote flow, from the User's perspective, is given below and shown in High Level Remote Protocol Flow:

  1. Authorization Request: the Wallet Instance obtains a URL in the Same Device flow or a QR Code containing the URL in Cross Device flow where the signed presentation Request Object is available for download.

  2. Request URI Request: the Wallet Instance extracts from the payload the following parameters: client_id, request_uri, state, request_uri_method.

  • If request_uri_method is provided and set with the value post, the Wallet Instance SHOULD transmit its metadata to the Relying Party's request_uri endpoint using the HTTP POST method.

  • If request_uri_method is set with the value get or not present, the Wallet Instance MUST fetch the signed Request Object using an HTTP request with method GET to the endpoint provided in the request_uri parameter.

  1. Request URI Response: the Relying Party returns a signed Request Object to the Wallet Instance.

  2. WI Checks: the Wallet Instance:

  1. verifies the signature of the signed Request Object using the public key identified in the JWT header of the Request Object. Using that reference, the Wallet Instance is able to select the correct Relying Party's public key for signature verification.

  2. verifies that the client_id contained in the Request Object issuer (Relying Party) matches with the one obtained at the step number 2 and with the sub parameter contained in the Relying Party's Entity Configuration within the Trust Chain.

  3. evaluates the requested Digital Credentials and checks the eligibility of the Relying Party in asking for these by applying the policies related to that specific Relying Party, obtained with the Trust Chain.

  1. User Consent: the Wallet Instance asks User disclosure and consent by showing the Relying Party's identity and the requested attributes.

  2. POST Authorization Response: the Wallet Instance presents the requested information to the Relying Party, along with the Wallet Attestation if requested.

  3. RP Checks: The Relying Party validates the presented Credentials by verifying the trust with their Issuers and checks the Wallet Attestation to ensure the Wallet Provider is trusted.

  4. Relying Party Response: the Wallet Instance informs the User about the successful authentication with the Relying Party, and the User continues the navigation.

Below is a sequence diagram that details the interactions between all the involved parties.

_images/cross_same_device_auth_seq_diagram.svg

Fig. 17 Remote Protocol Flow

The details of each step shown in the previous picture are described below.

Steps 1-2: The User requests to access to a protected resource of the Relying Party.

Steps 3-5: The Relying Party creates a state value bound to the user-agent (e.g., using an HTTP secured cookie), the Request Object available for download at the request_uri location. It then inspects the user-agent to determine whether the flow occurs on the same device as the user-agent.

Steps 6-9 (Authorization Request): The Relying Party provides the user-agent with a JavaScript page inspecting the status endpoint and the Wallet Instance with a URL containing the Authorization Request.

In the Cross Device Flow, the Request URI is presented as a QR Code displayed to the User. The User scans the QR Code using the Wallet Instance and retrieves a URL with the parameters client_id, request_uri, state and request_uri_method.

Below is represented a non-normative example of a QR Code issued by the Relying Party.

_images/verifier_qr_code.svg

Below is represented a non-normative example of the QR Code raw payload:

https://wallet-solution.example.org/authorization?client_id=https%3A%2F%2Frelying-party.example.org&request_uri=https%3A%2F%2Frelying-party.example.org&request_uri_method=post

Note

The error correction level chosen for the QR Code MUST be Q (Quartily - up to 25%), since it offers a good balance between error correction capability and data density/space. This level of quality and error correction allows the QR Code to remain readable even if it is damaged or partially obscured.

Conversely, in the Same Device Flow, the Relying Party uses an HTTP response redirect (with status code set to 302) or an html page with an href button, containing the URL providing the same information as in the Cross-Device Flow. Below is a non-normative example:

HTTP/1.1 302 Found
Location: https://wallet-solution.digital-strategy.europa.eu?client_id=https%3A%2F%2Frelying-party.example.org%2Fcb&request_uri=https%3A%2F%2Frelying-party.example.org%2Frequest_uri&request_uri_method=post

Step 10: The Wallet Instance evaluates the trust with the Relying Party.

Steps 11-13 (Request URI Request): The Wallet Instance checks if the Relying Party has provided the request_uri_method within its signed Request Object.

  • If it is provided and is equal to post, the Wallet Instance SHOULD provide its metadata to the Relying Party. The Relying Party updates the Request Object according with the Wallet technical capabilities.

    The following is a non-normative example of an HTTP request made by the Wallet Instance to the Relying Party.

    POST /request HTTP/1.1
    Host: client.example.org
    Content-Type: application/x-www-form-urlencoded
    Accept: application/oauth-authz-req+jwt
    
    wallet_metadata=%7B%22authorization_endpoint%22%3A%20%22eudiw%3A%22%2C%20%22response_types_supported%22%3A%20%5B%22vp_token%22%5D%2C%20%22response_modes_supported%22%3A%20%5B%22form_post.jwt%22%5D%2C%20%22vp_formats_supported%22%3A%20%7B%22dc%2Bsd-jwt%22%3A%20%7B%22sd-jwt_alg_values%22%3A%20%5B%22ES256%22%2C%20%22ES384%22%5D%7D%7D%2C%20%22request_object_signing_alg_values_supported%22%3A%20%5B%22ES256%22%5D%7D%2C&wallet_nonce=%22qPmxiNFCR3QTm19POc8u%22
    

    Where the body of the request prior to being encoded in application/x-www-form-urlencoded by the Wallet corresponds to:

    {
      "wallet_metadata": {
        "authorization_endpoint": "https://wallet-solution.digital-strategy.europa.eu/authorization",
        "response_types_supported": [
          "vp_token"
        ],
        "response_modes_supported": [
          "form_post.jwt"
        ],
        "vp_formats_supported": {
          "dc+sd-jwt": {
              "sd-jwt_alg_values": [
                  "ES256",
                  "ES384"
              ]
          }
        },
        "request_object_signing_alg_values_supported": [
          "ES256"
        ],
        "client_id_schemes_supported": ["https"],
      },
      "wallet_nonce": "qPmxiNFCR3QTm19POc8u"
    }
    
  • When the Wallet Instance capabilities discovery is not supported by Relying Party, the Wallet Instance requests the signed Request Object using the HTTP method GET.

Step 14 (Request URI Response): The Relying Party issues the Request Object signing it using one of its cryptographic private keys, where their public parts have been published within its Entity Configuration (metadata.openid_credential_verifier.jwks). The Wallet Instance obtains the signed Request Object.

Below is a non-normative example of the Redirect URI Response:

HTTP/1.1 200 OK
Content-Type: application/oauth-authz-req+jwt

eyJhbGciOiJFUzI1NiIs...9t2LQ

A non-normative example of a Request Object in the form of decoded header and payload is shown below:

{
  "alg": "ES256",
  "typ": "oauth-authz-req+jwt",
  "kid": "9tjiCaivhWLVUJ3AxwGGz_9",
  "trust_chain": [
    "MIICajCCAdOgAwIBAgIC...awz",
    "MIICajCCAdOgAwIBAgIC...2w3",
    "MIICajCCAdOgAwIBAgIC...sf2"
  ]
}
{
  "client_id": "https://relying-party.example.org",
  "response_mode": "direct_post.jwt",
  "response_type": "vp_token",
  "dcql_query": {
    "credentials": [
      {
        "id": "personal id data",
        "format": "dc+sd-jwt",
        "meta": {
          "vct_values": [ "https://trust-registry.eid-wallet.example.it/credentials/v1.0/personidentificationdata" ]
        },
        "claims": [
            {"path": ["given_name"]},
            {"path": ["family_name"]},
            {"path": ["personal_administrative_number"]}
        ]
      },
      {
        "id": "wallet attestation",
        "format": "dc+sd-jwt",
        "meta": {
          "vct_values": ["https://itwallet.registry.example.it/WalletAttestation"]
        },
        "claims": [
            {"path": ["wallet_link"]},
            {"path": ["wallet_name"]}
        ]
      }
    ]
  },
  "response_uri": "https://relying-party.example.org/response_uri",
  "nonce": "2c128e4d-fc91-4cd3-86b8-18bdea0988cb",
  "wallet_nonce": "qPmxiNFCR3QTm19POc8u",
  "state": "3be39b69-6ac1-41aa-921b-3e6c07ddcb03",
  "iss": "https://relying-party.example.org",
  "iat": 1672418465,
  "exp": 1672422065,
  "request_uri_method": "post"
}

Steps 15-17 (WI Checks): The Wallet Instance verifies the Request Object, which is in the form of a signed JWT. It then processes the Relying Party metadata and applies the relevant policies to determine which Digital Credentials and User data the Relying Party is authorized to request.

Steps 18-19 (User Consent): The Wallet Instance requests the User's consent to disclose the requested Credentials by showing the Relying Party's identity and the requested attributes. The User authorizes and consents the presentation of the Credentials by selecting/deselecting the personal data to release.

Step 20 (Authorization Response): The Wallet Instance provides the Authorization Response to the Relying Party using an HTTP request with the method POST (response mode "direct_post.jwt").

Below is a non-normative example of the Authorization Response:

POST /response_uri HTTP/1.1
HOST: relying-party.example.org
Content-Type: application/x-www-form-urlencoded

response=eyJhbGciOiJFUzI1NiIs...9t2LQ

Below is a non-normative example of the decrypted payload of the JWT contained in the response, before base64url encoding. The vp_token parameter value corresponds to the format used when the DCQL query language is used in the presentation request.

{
  "state": "3be39b69-6ac1-41aa-921b-3e6c07ddcb03",
  "vp_token": {
      "personal id data": "eyJhbGciOiJFUzI1NiIs...PT0iXX0",
      "wallet attestation": "eyJhbGciOiJFUzI1NiIs...NTi0XG"
  }
}

Steps 21-25 (RP Checks): The Relying Party verifies the Authorization Response, extracts the Wallet Attestation to establish trust with the Wallet Solution. It then extracts the Digital Credentials and attests trust with the Credentials Issuer and the Wallet Instance's proof of possession of the presented Digital Credentials. Finally, the Relying Party verifies the revocation status of the presented Digital Credentials as described in Digital Credential Revocation and Suspension. If all previous verifications yelded positive result, the Relying Party updates the User session.

Steps 26-27 or 28 (Relying Party Response): The Relying Party provides to the Wallet Instance the response about the presentation, which informs the User.

Upon receiving and validating the Authorization Response at the Response Endpoint, the Relying Party returns to the Wallet Instance a HTTP 200 OK. In particular, in the Same Device Flow, the Relying Party SHOULD also pass the redirect_uri to the Wallet Instance. Upon receiving the redirect_uri, the Wallet Instance MUST perform a redirect to the URL specified by the redirect_uri. This redirect allows the Relying Party to seamlessly resume interaction with the User on the device which initiated the flow. When the response does not contain the redirect_uri parameter, the Wallet Instance is not required to perform any further step. The User should manually close the Wallet Instance and open the user-agent to continue the flow.

The following is a non-normative example of the response in the Same Device Flow.

HTTP/1.1 200 OK
Content-Type: application/json

{
  "redirect_uri": "https://relying-party.example.org/cb?response_code=091535f699ea575c7937fa5f0f454aee"
}

Steps 29-30: The JavaScript page is inspecting the status endpoint.

Below is a non-normative example of the HTTP Request to the status endpoint, where the parameter id contains an opaque and random value:

GET /session-state?id=3be39b69-6ac1-41aa-921b-3e6c07ddcb03 HTTP/1.1
HOST: relying-party.example.org

When the Wallet Instance has provided the presentation to the Relying Party's response_uri endpoint and the User authentication is successful. The Relying Party updates the session cookie allowing the user-agent to access to the protected resource. A redirect URL is provided carrying the location where the user-agent is intended to navigate. The following is a non-normative example of the response with the redirect_uri from the Relying Party to the user-agent.

HTTP/1.1 200 OK
Content-Type: application/json

{
  "redirect_uri": "https://relying-party.example.org/cb?response_code=091535f699ea575c7937fa5f0f454aee"
}

Steps 31-32: The user-agent is redirected to the redirect URI to continue the navigation with the protected resource made available to the User.

Authorization Request

The URL parameters contained in the Relying Party Authorization Request, which include the request_uri where the signed Request Object can be downloaded, are described in the table below.

Name

Description

client_id

REQUIRED. Unique identifier of the Relying Party.

request_uri

REQUIRED. The HTTP URL where the Relying Party provides the signed Request Object to the Wallet Instance.

state

RECOMMENDED. A unique identifier for the current transaction generated by the Relying Party. The value SHOULD be opaque to the Wallet Instance.

request_uri_method

OPTIONAL. The HTTP method MUST be set with get or post. The Wallet Instance should use this method to obtain the signed Request Object from the request_uri. If not provided or equal to get, the Wallet Instance SHOULD use the HTTP method get. Otherwise, the Wallet Instance SHOULD provide its metadata within the HTTP POST body encoded in application/x-www-form-urlencoded.

Warning

For security reasons and to prevent endpoint mix-up attacks, the value contained in the request_uri parameter MUST be one of those attested by a trusted third party, such as those provided in the openid_credential_verifier metadata within the request_uris parameter, obtained from the Trust Chain about the Relying Party.

Note

The state parameter in an OAuth request is optional, but it is highly recommended. It is primarily used to prevent Cross-Site Request Forgery (CSRF) attacks by including a unique and unpredictable value that the Relying Party can verify upon receiving the response. Additionally, it helps maintain the state between the request and response, such as session information or other data the Relying Party needs after the authorization process.

The value corresponding to the request_uri endpoint SHOULD be randomized, according to RFC 9101, The OAuth 2.0 Authorization Framework: JWT-Secured Authorization Request (JAR) Section 5.2.1.

Request URI Request

The Relying Party SHOULD provide the POST method with its request_uri endpoint allowing the Wallet Instance to inform the Relying Party about its technical capabilities.

This feature can be useful when, for example, the Wallet Instance supports a restricted set of features, supported algorithms or a specific url for its authorization_endpoint, and any other information that it deems necessary to provide to the Relying Party for interoperability.

Warning

The Wallet Instance, when providing its technical capabilities to the Relying Party, MUST NOT include any User information or other explicit information regarding the hardware used or usage preferences of its User.

If both the Relying Party and the Wallet Instance support the request_uri_method with HTTP POST, the Wallet Instance capabilities (metadata) MUST be provided using an HTTP request to the request_uri endpoint of the Relying Party, with the method POST and content type set to application/x-www-form-urlencoded. The request and its parameters are defined in Section number 5 (Authorization Request) of OpenID4VP. Below are the normative details and references about the parameters to be used by the Wallet Instance in the request.

Table 9 Request URI Endpoint Parameters

Parameter

Description

wallet_metadata

OPTIONAL. JSON object with metadata parameters. See OpenID4VP, Section 9.1 and the table below, "Wallet Metadata Parameters".

wallet_nonce

RECOMMENDED. String used by Wallet Instance to prevent replay of the Relying Party's responses. See OpenID4VP, Section 9.

Table 10 Wallet Metadata Parameters

Parameter

Description

vp_formats_supported

REQUIRED. Object with Credential format identifiers. See OpenID4VP Appendix B.

alg_values_supported

OPTIONAL. Array of cryptographic suites supported. See OpenID4VP Appendix B.

client_id_schemes_supported

RECOMMENDED. Array of Client Identifier schemes. Default is entity_id.

authorization_endpoint

URL of the authorization server's endpoint, see OAUTH2. Using an universal link is preferable for enhanced security and fallback support, custom url schemes can also be used if necessary.

response_types_supported

OPTIONAL. JSON array of OAuth 2.0 "response_type" values. If present it MUST be set to vp_token. Default is vp_token.

response_modes_supported

OPTIONAL. JSON array of OAuth 2.0 "response_mode" values. See JARM.

request_object_signing_alg_values_supported

OPTIONAL. See OpenID Connect Discovery.

Note

The wallet_nonce parameter is RECOMMENDED for Wallet Instances that want to prevent reply of their http requests to the Relying Parties. When present, the Relying Party MUST evaluate it.

Note

For the authorization_endpoint the use of universal links are preferred over custom url-schemes because, when properly configured using Assetlinks JSON for Android and Apple App Site Association for iOS, they provide enhanced security by reducing the risk of URL hijacking. Furthermore, universal links offer fallback mechanisms, allowing the flow to continue seamlessly in a browser even if the Wallet Instance is not installed, ensuring a smoother User experience. To ensure interoperability, support custom url-schemes is also RECOMMENDED according to OpenID4VC High Assurance Interoperability Profile (HAIP) OPENID4VC-HAIP, and in particular using the custom url haip://.

Request URI Response

The Relying Party issues the signed Request Object using the content type set to application/oauth-authz-req+jwt.

The JWT header parameters are described below:

Name

Description

alg

Algorithm used to sign the JWT, according to [RFC 7516#section-4.1.1]. It MUST be one of the supported algorithms in Section Cryptographic Algorithms and MUST NOT be set to none or to a symmetric algorithm (MAC) identifier.

typ

Media Type of the JWT, as defined in [RFC 7519] and [RFC 9101]. It SHOULD be set to the value oauth-authz-req+jwt.

kid

Key ID of the public key needed to verify the JWT signature, as defined in [RFC 7517]. REQUIRED when trust_chain is used.

trust_chain

Sequence of Entity Statements that composes the Trust Chain related to the Relying Party, as defined in OID-FED Section 4.3 Trust Chain Header Parameter.

The JWT payload parameters are described herein:

Name

Description

client_id

Unique Identifier of the Relying Party.

response_mode

It MUST be set to direct_post.jwt.

dcql_query

Object representing a request for a presentation of Credentials, according to the DCQL query language defined in Section 6 of OpenID4VP.

response_type

It MUST be set to vp_token.

wallet_nonce

String value used to mitigate replay attacks of the response, as defined in Section 5.11 (Request URI Method) of OpenID4VP. It MUST be present if previously provided by Wallet Instance.

response_uri

The Response URI to which the Wallet Instance MUST send the Authorization Response using an HTTP request using the method POST.

nonce

Fresh cryptographically random number with sufficient entropy, which length MUST be at least 32 digits.

state

Unique identifier of the Authorization Request.

iss

The entity that has issued the JWT. It will be populated with the Relying Party client id.

iat

Unix Timestamp, representing the time at which the JWT was issued.

exp

Unix Timestamp, representing the expiration time on or after which the JWT MUST NOT be valid anymore.

request_uri_method

String determining the HTTP method to be used with the request_uri endpoint to provide the Wallet Instance metadata to the Relying Party. The value is case-insensitive and can be set to: get or post. The GET method, as defined in [@RFC9101], involves the Wallet Instance sending a GET request to retrieve a Request Object. The POST method involves the Wallet Instance requesting the creation of a new Request Object by sending an HTTP POST request, with its metadata, to the request URI of the Relying Party.

Warning

For security reasons and to prevent endpoint mix-up attacks, the value contained in the response_uri parameter MUST be one of those attested by a trusted third party, such as those provided in the openid_credential_verifier metadata within the response_uris parameter, obtained from the Trust Chain about the Relying Party.

Note

The following parameters, even if defined in [OID4VP], are not mentioned in the previous non-normative example, since their usage is conditional and may change in future release of this documentation.

  • presentation_definition: JSON object according to Presentation Exchange. This parameter MUST not be present when presentation_definition_uri or scope are present.

  • presentation_definition_uri: Not supported. String containing an HTTPS URL pointing to a resource where a Presentation Definition JSON object can be retrieved. This parameter MUST be present when presentation_definition parameter or a scope value representing a Presentation Definition is not present.

  • client_metadata: A JSON object containing the Relying Party metadata values. If the client_metadata parameter is present, the Wallet Instance MUST ignore it and consider the client metadata obtained through the OpenID Federation Trust Chain.

Request URI Endpoint Errors

When the Relying Party encounters errors while issuing the Request Object from the request_uri endpoint, it MUST return an error response with application/json as the content type and MUST include the following parameters:

  • error: The error code.

  • error_description: Text in human-readable form providing further details to clarify the nature of the error encountered.

The following table lists the HTTP Status Codes and related error codes that MUST be supported for the error response:

Status Code

Error Code

Description

500 Internal Server Error

server_error

The request cannot be fulfilled because the Request URI Endpoint encountered an internal problem. (RFC 6749#section-4.1.2.1).

503 Service Unavailable

temporarily_unavailable

The request cannot be fulfilled because the Request URI Endpoint is temporarily unavailable (e.g., due to maintenance or overload). (RFC 6749#section-4.1.2.1).

The following is an example of an error response from request_uri endpoint:

HTTP/1.1 500 Internal Server Error
Content-Type: application/json

{
 "error": "server_error",
 "error_description": "The Request Object cannot be retrieved due to an internal server error."
}

Upon receiving an error response, the Wallet Instance SHOULD inform the User of the error condition in an appropriate manner. The Wallet Instance SHOULD log the error and MAY attempt to recover from certain errors if feasible. For example, if the error is server_error, the Wallet Instance SHOULD prompt the User to re-enter or scan a new QR code, if applicable.

Authorization Response

After obtaining the User authorization and consent for the presentation of the Digital Credentials, the Wallet Instance sends the Authorization Response to the Relying Party response_uri endpoint using an HTTP request with the method POST, the content SHOULD be encrypted according OpenID4VP Section 7.3, using the Relying Party public key.

Note

Why the response is encrypted?

The response sent from the Wallet Instance to the Relying Party is encrypted to prevent a malicious agent from gaining access to the plaintext information transmitted within the Relying Party's network. This is only possible if the network environment of the Relying Party employs TLS termination. Such technique employs a termination proxy that acts as an intermediary between the client and the webserver and handles all TLS-related operations. In this manner, the proxy deciphers the transmission's content and either forwards it in plaintext or by negotiates an internal TLS session with the actual webserver's intended target. In the first scenario, any malicious actor within the network segment could intercept the transmitted data and obtain sensitive information, such as an unencrypted response, by sniffing the transmitted data.

Where the following parameters are used:

Name

Description

vp_token

There MUST be at least two signed presentations in this Array:

  • The requested Digital Credential (one or more, in format of SD-JWT VC)

  • The Wallet Attestation (in SD-JWT VC format)

When presentation_definition is used, the vp_token value is a JSON Array containing the Verifiable Presentation(s) and the presentation_submission parameter MUST be also present within the response.

When the DCQL query language is used, the vp_token format is a JSON Object which keys corresponds to the requested credential ids in the dcql_query used in the request, and the values to each presented Digital Credential.

state

Unique identifier provided by the Relying Party within the Authorization Request.

SD-JWT defines how a Holder can present a Digital Credential to a Relying Party, proving the legitimate possession of the Digital Credential. To do this, the Holder MUST include the KB-JWT in the SD-JWT by appending the KB-JWT at the end of the SD-JWT, as represented in the example below

<Issuer-Signed-JWT>~<Disclosure 1>~<Disclosure 2>~...~<Disclosure N>~<KB-JWT>

To validate the signature on the Key Binding JWT, the Relying Party MUST use the key material included in the Issuer-Signed-JWT. The Key Binding JWT (KB-JWT) signature validation MUST use the public key included in the SD-JWT, using the cnf parameter contained in the Issuer-Signed-JWT.

When an SD-JWT is presented, its KB-JWT MUST contain the following parameters in the JWT header:

Claim

Description

typ

REQUIRED. MUST be kb+jwt, which explicitly types the Key Binding JWT as recommended in Section 3.11 of [RFC8725].

alg

REQUIRED. Signature Algorithm using one of the specified in the section Cryptographic Algorithms.

When an SD-JWT is presented, the KB-JWT signature MUST be verified by the same public key included in the SD-JWT within the cnf parameter. The KB-JWT MUST contain the following parameters in the JWT payload:

Claim

Description

iat

REQUIRED. The value of this claim MUST be the time at which the Key Binding JWT was issued, using the syntax defined in [RFC7519].

aud

REQUIRED. The intended receiver of the Key Binding JWT. The value of this parameter MUST match the Relying Party unique entity identifier.

nonce

REQUIRED. Ensures the freshness of the signature. The value type of this claim MUST be a string. The value MUST match with the one provided in the request object.

sd_hash

REQUIRED. The base64url-encoded hash digest over the Issuer-signed JWT and the selected disclosures.

Authorization Response Errors

There are cases where the Wallet Instance cannot validate the Request Object or the Request Object results invalid. This error occurs if the Request Object is successfully fetched from the url provided in the parameter request_uri but fails the validation checks. This could be due to incorrect signatures, malformed claims, or other validation failures, such as the revocation of the Relying Party.

If the Wallet Instance encounters any such errors during the evaluation of the Authorization Request, it MUST notify the Relying Party by sending an Authorization Error Response. The Wallet Instance sends the Authorization Error Response to the Relying Party response_uri endpoint using an HTTP POST request. The Authorization Error Response MUST be encoded in the request body using the format defined by the application/x-www-form-urlencoded content type.

Below is a non-normative example of an Authorization Error Response.

POST /response_uri HTTP/1.1
HOST: relying-party.example.org
Content-Type: application/x-www-form-urlencoded

state=3be39b69-6ac1-41aa-921b-3e6c07ddcb03&
error=invalid_request&
error_description=...

Warning

The current OpenID4VP specification outlines various error responses that a Wallet Instance may return to the Relying Party (Verifier) in case of faulty requests. For privacy enhancement, Wallet Instances SHOULD NOT notify the Relying Party of faulty requests in certain scenarios. This is to prevent any potential misuse of error responses that could lead to gather informations that could be exploited.

In the following table are listed error codes and descriptions that are supported for the Authorization Error Response:

Error Code

Description

invalid_request_object

The Request Object contains invalid parameters or is otherwise malformed. RFC 9101

invalid_request_uri

The request_uri in the authorization request returns an error, contains invalid data, or is otherwise malformed. RFC 9101

vp_formats_not_supported

The Wallet Instance does not support any of the vp formats required by the Relying Party. OpenID4VP

invalid_request

The Wallet Instance does not support any of the signing algorithms required by the Relying Party. OpenID4VP

access_denied

The Wallet did not have the requested credential, the User did not consent, or the Wallet failed to authenticate the User. OpenID4VP

invalid_client

The Relying Party cannot be authorized due to trust validation failures or is not a valid participant of the federation. OID-FED

Relying Party Response

As defined in Section 7.2. (Response Mode "direct_post") of the OpenID4VP specification, if the Response URI has successfully processed the Authorization Response or Authorization Error Response, it MUST respond with an HTTP status code of 200 with Content-Type of application/json and a JSON object in the response body.

In the Same Device Flow, the Relying Party SHOULD add the redirect_uri parameter to the JSON object in the response body. Upon receiving the redirect_uri, the the Wallet Instance MUST perform a redirect to the URL specified by the redirect_uri. This redirect allows the Relying Party to seamlessly resume interaction with the User on the device which initiated the flow, after the Wallet Instance has transmitted the Authorization Response to the designated response_uri.

The Relying Party MUST include a response code within the redirect_uri. The response code is a fresh, cryptographically random number used to ensure only the receiver of the redirect can fetch and process the Authorization Response. The number could be added as a path component, as a parameter or as a fragment to the URL. It is RECOMMENDED to use a cryptographic random value of 128 bits or more at the time of the writing of this specification. Even if an adversary manages to steal the random value used in the request to the status endpoint, their user-agent would be rejected due to the missing cookie in the request.

Warning

For security reasons and to prevent endpoint mix-up attacks, the value contained in the redirect_uri parameter MUST be one of those attested by a trusted third party, such as those provided in the openid_credential_verifier metadata within the redirect_uris parameter, obtained from the Trust Chain about the Relying Party.

Relying Party Response Errors

If any validation check, performed by the Relying Party on the Authorization Response from the Wallet Instance, fails; the Response URI endpoint MUST return an error response. The structure of this error response should be determined by the specific nature of the error encountered. The response MUST use application/json as the content type and MUST include the following parameters:

  • error: The error code.

  • error_description: Text in human-readable form providing further details to clarify the nature of the error encountered.

The following table lists the HTTP Status Codes and related error codes that MUST be supported for the error response:

Status Code

Error Code

Description

400 Bad Request

invalid_request

The response cannot be processed because it is missing required parameters, contains invalid parameters or is otherwise malformed.

400 Bad Request

invalid_request

The Credentials presented are malformed, invalid or revoked.

400 Bad Request

invalid_request

The credential presentation, contained in the vp_token object, is malformed, doesn't have the required parameters or is incorrectly formatted.

400 Bad Request

invalid_request

The "sd-jwt" returned is malformed, missing required parameters or incorrectly formatted.

403 Forbidden

invalid_request

The signature of the KB-JWT is invalid or does not match the associated public key (JWK) referenced in the Issuer signed SD-JWT.

403 Forbidden

invalid_request

The nonce value provided is incorrect or otherwise malformed.

403 Forbidden

invalid_request

The signature of the Wallet Attestation is not valid or trust cannot be established with its Issuer.

403 Forbidden

invalid_request

Trust could not be established with the Credential Issuer.

500 Internal Server Error

server_error

The request cannot be fulfilled because the Response URI Endpoint encountered an internal problem.

503 Service Unavailable

temporarily_unavailable

The request cannot be fulfilled because the Response URI Endpoint is temporarily unavailable (e.g., due to maintenance or overload).

Below there are two examples of HTTP responses using application/json that include both the error and error_description members:

HTTP/1.1 403 Forbidden
Content-Type: application/json

{
  "error": "invalid_request",
  "error_description": "Trust cannot be established with the issuer: https://issuer.example.com"
}
HTTP/1.1 400 Bad Request
Content-Type: application/json

{
  "error": "invalid_request",
  "error_description": "The vp_token is malformed, missing required parameters or incorrectly formatted"
}

Status Endpoint

This specification introduces the Relying Party Status Endpoint for implementations that choose to use it. This endpoint is an internal security feature of the implementation and is not required for interoperability.

Whether the flow is Same Device or Cross Device, the user-agent needs to check the session status at the endpoint made available by the Relying Party (status endpoint). This check MAY be implemented in the form of JavaScript code, within the page that shows the QRCode or the href button pointing to the request URL. The JavaScript code makes the user-agent check the status endpoint using either a polling strategy (in seconds) or a push strategy (e.g., WebSocket).

Since the HTML page and the status endpoint are implemented by the Relying Party, the implementation details of this solution are the responsibility of the Relying Party, as this is related to the Relying Party's internal API. However, the text below describes an example implementation.

The Relying Party binds the request of the user-agent, with a session cookie marked as Secure and HttpOnly, with the issued request. The request url SHOULD include a parameter with a random value. The HTTP response returned by this status endpoint MAY contain the HTTP status codes listed below:

  • 201 Created. The signed Request Object was issued by the Relying Party that waits to be downloaded by the Wallet Instance at the request_uri endpoint.

  • 202 Accepted. This response is given when the signed Request Object was obtained by the Wallet Instance.

  • 200 OK. The Wallet Instance has provided the presentation to the Relying Party's response_uri endpoint and the User authentication is successful. The Relying Party updates the session cookie allowing the user-agent to access to the protected resource. A redirect URL is provided carrying the location where the user-agent is intended to navigate.

Status Endpoint Errors

If instead any validation check performed by the Relying Party fails, the QRCode page SHOULD be updated with an error message. Moreover, the status endpoint MUST return an error response, whose structure depends on the nature of the error. The response MUST use application/json as the content type and MUST include the following parameters:

  • error: The error code.

  • error_description: Text in human-readable form providing further details to clarify the nature of the error encountered.

The following table lists the HTTP Status Codes and related error codes that MUST be supported for the error response:

Status Code

Error Code

Description

401 Unauthorized

authentication_failed

The Wallet Instance or its User have rejected the request, the request is expired, or other errors prevented the authentication.

403 Forbidden

invalid_session

Either the session id provided in the request is invalid.

Redirect URI

The redirect_uri value MUST be used with an HTTP method GET by the user-agent to redirect the User to a specific Relying Party's endpoint in order to complete the process.

Redirect URI Errors

When the user-agent is redirected to the Redirect URI provided by the Relying Party, several errors may occur that prevent the successful completion of the process. These errors are critical as they directly impact the User experience by hindering the seamless flow of information between the Wallet Instance and the Relying Party. Handling these errors requires clear communication to the User within the returned navigation web page. Relying Party MUST implement the error handling and validation mechanisms for Redirect URIs defined in this specification. Below are potential errors related to the Redirect URI, the error response MUST use application/json as the content type and MUST include the following parameters:

  • error: The error code.

  • error_description: Text in human-readable form providing further details to clarify the nature of the error encountered.

The following table lists the HTTP Status Codes and related error codes that MUST be supported for the error response:

Status Code

Error Code

Description

403 Forbidden

invalid_request

The Redirect URI provided by the Relying Party does not match any of the URIs linked with the User session. (RFC 6749#section-4.1.2.1)

403 Forbidden

invalid_request

The User session is invalid or expired.

500 Internal Server Error

server_error

The request cannot be fulfilled due to an intenal server error. (RFC 6749#section-4.1.2.1).

503 Service Unavailable

temporarily_unavailable

The request cannot be fulfilled because the service is temporarily unavailable (e.g., due to maintenance or overload). (RFC 6749#section-4.1.2.1).

Proximity Flow

This section describes how a Relying Party Instance requests the presentation of an mdoc-CBOR Credential to a Wallet Instance according to the ISO 18013-5 Specification.

The high-level presentation phase is structured into three broad sub-phases as depicted in the following figure:

_images/high-level-presentation-proximity.svg

Fig. 18 High-Level Presentation Flow in proximity

The sub-phases are described below:

1. Device Engagement: This subphase begins when the User is prompted to disclose certain attributes from the mdoc(s). The objective of this subphase is to establish a secure communication channel between the Wallet Instance and the Relying Party Instance, so that the mdoc requests and responses can be exchanged during the communication subphase. The messages exchanged in this subphase are transmitted through short-range technologies to limit the possibility of interception and eavesdropping.

2. Session establishment: During the session establishment phase, the Relying Party Instance sets up a secure connection. All data transmitted over this connection is encrypted using a session key, which is known to both the Wallet Instance and the Relying Party Instance at this stage. The established session MAY be terminated based on the conditions as detailed in [ISO18013-5 #9.1.1.4].

3. Communication - Device Retrieval: The Relying Party Instance encrypts the mdoc request with the appropriate session key and sends it to the Wallet Instance together with its public key in a session establishment message. The mdoc uses the data from the session establishment message to derive the session key and decrypt the mdoc request. During the communication subphase, the Relying Party Instance has the option to request information from the Wallet Instance using mdoc requests and responses. The primary mode of communication is the secure channel established during the session setup. The Wallet Instance encrypts the mdoc response using the session key and transmits it to the mobile Relying Party via a session data message.

Relying Party and Wallet Instances registered in the IT-Wallet ecosystem MUST support at least:

  • Supervised Device Retrieval flow where a human Relying Party is overseeing the verification process in person, in contrast with unsupervised flow where verification might happen through automated systems without human oversight.

  • Device Engagement based on QR Code.

  • RP Instance Authentication following the mechanisms defined in the ISO18013-5 for the reader authentication.

  • Device Retrieval mechanism based on Bluetooth Low Energy (BLE) for the communication sub-phase. Server Retrieval mechanism MUST NOT be supported.

  • Domestic Document Type and Namespaces defined in this technical specification in addition to those already defined in the ISO18013-5 for the mDL (see mdoc-CBOR Credential Format for more details).

  • Wallet Instance validation through the Wallet Attestation.

The following figure illustrates the low-level flow compliant with ISO 18013-5 for proximity flow.

_images/High-Level-Flow-ITWallet-Presentation-ISO-updated.svg

Fig. 19 High-Level Proximity Flow

Step 1: The User opens the Wallet Instance initiating the process.

Step 2: The User authenticates itself to the Wallet Instance. This can be done by the Wallet Instance or a Wallet Secure Cryptographic Application (WSCA). It is a prerequisite for accessing sensitive data and presenting attributes.

Step 3: The User selects the proximity presentation functionality.

Step 4: [Optional] If the initial authentication in Step 2 was not done through WSCA, a separate authentication via WSCA MAY be required.

Step 5: The Wallet Instance generates a new ephemeral Elliptic Curve key pair for secure communication. The public key (EDeviceKey.Pub) will be used for session encryption. This is part of the device engagement process.

Step 6: The Wallet Instance presents a QR Code to the Relying Party Instance. This QR code contains the DeviceEngagement data, which includes the EDeviceKey.Pub and information about supported cipher suites.

Below is a non-normative example using the diagnostic notation of a CBOR-encoded DeviceEngagement that utilizes QR for device engagement and Bluetooth Low Energy (BLE) for data retrieval.

{
  0: "1.1", % Version (Updated to 1.1 because Capabilities and OriginInfos are present)
  1: % Security
  [
    1, % defines the cipher suite , which contains only EC curves
    24(<< % embedded CBOR data item
    {
      1: 2, % kty:EC2 (Elliptic curves with x and y coordinate pairs)
      -1: 1, % crv:p256
      -2:h'5A88D182BCE5F42EFA59943F33359D2E8A968FF289D93E5FA444B624343167FE', % x-coordinate
      -3:h'B16E8CF858DDC7690407BA61D4C338237A8CFCF3DE6AA672FC60A557AA32FC67' % y-coordinate
    }
    >>)
  ],
  2: % DeviceRetrievalMethods (Device engagement using QR code with BLE for retrieval)
  [
    [
      2, % BLE
      1, % Version
      { % BLE options
        0: false, % no support for mdoc peripheral server mode
        1: true,  % support for mdoc central client mode
        11: h'45EFEF742B2C4837A9A3B0E1D05A6917' % UUID of mdoc client central mode
      }
    ]
  ],
  5: % OriginInfos (Required because Capabilities is present)
  [],
  6: % Capabilities (Defines supported features)
  {
    2: false, % HandoverSessionEstablishmentSupport (Supports negotiated handover)
    3: true % ReaderAuthAllSupport (Supports reader authentication)
  }
}

Step 7: The verifier uses its Relying Party Instance to scan the QR code and retrieve the DeviceEngagement data from the mdoc.

Step 8: The Relying Party Instance generates its ephemeral key pair (EReaderKey.Priv, EReaderKey.Pub). The private key (EReaderKey.Priv) MUST be kept secret, and the public key (EReaderKey.Pub) MUST be used in establishing the session.

Step 9: The Wallet Instance and Relying Party Instance independently MUST derive the session keys using their private ephemeral key and the other party's public ephemeral key through a key agreement protocol. This ensures session encryption. In this particular step, the Relying Party Instance MUST compute its session key.

Step 10: The RP Instance MUST prepare a SessionEstablishment message. This message MUST be signed by the Relying Party Instance (mdoc reader authentication as specified in [ISO18013-5 #9.1.4]) and encrypted using the session keys derived in the previous step. The SessionEstablishment message MUST include the EReaderKey.Pub and a request for specific attribute(s).

Below is a non-normative example using the diagnostic notation of a CBOR-encoded SessionEstablishment that contains the mdoc request of a Wallet Attestation along with an mDL Digital Credential.

{
  "version": "1.0",  % Version
  "docRequests": 
  [
    {
    "itemsRequest": 
    24(<<  % Embedded CBOR data item
      {
        "docType": "org.iso.18013.5.1.mDL",
        "nameSpaces": 
        {
          "org.iso.18013.5.1": 
          {
            "family_name": true,
            "document_number": true,
            "driving_privileges": true,
            "issue_date": true,
            "expiry_date": true,
            "portrait": false
          }
        }
      }
    >>)
    },
    {
    "itemsRequest": 
    24(<<  % Embedded CBOR data item
      {
        "docType": "org.iso.18013.5.1.IT.WalletAttestation",
        "nameSpaces": {
          "org.iso.18013.5.1.IT": 
          {
            "wallet_name": true,
            "wallet_link": true,
            "sub": true,
            "aal": true
          }
        }
      }
    >>)
    }
  ],
  "readerAuthAll": 
  [
    h'a10126', % COSE_Sign1 authentication header
    {
      33: h'308201253081cda00302010202012a300a06082a8648ce3d0403023020311e301c06035504030c15536f6d652052656164657220417574686f72697479301e170d3233313132343130323832325a170d3238313132323130323832325a301a3118301606035504030c0f536f6d6520526561646572204b65793059301306072a8648ce3d020106082a8648ce3d03010703420004aa1092fb59e26ddd182cfdbc85f1aa8217a4f0fae6a6a5536b57c5ef7be2fb6d0dfd319839e6c24d087cd26499ec4f87c8c766200ba4c6218c74de50cd1243b'
    },
    null, % No additional reader authentication
    h'58a0d421a7e53b7db0412a196fea50ca6d4c8a530a47dd84d88588ab145374bd0ab2a724cf2ed2facf32c7184591c5969efd53f5aba63194105440bc1904e1b9'  % Reader authentication signature
  ]
}

Step 11: The Relying Party Instance MUST transmit the encrypted and signed SessionEstablishment message to the Wallet Instance over a secure BLE connection that was established based on the device engagement information.

Step 12: The Wallet Instance MUST compute the session key, as described in Step 9.

Step 13: Upon receiving the SessionEstablishment message, the Wallet Instance MUST decrypt it using the shared session key and MUST verify the Relying Party Instance's signature (mdoc reader authentication as specified in [ISO18013-5 #9.1.1.4]) to ensure its authenticity.

Step 14: The Wallet Instance MUST decrypt the attribute request and MUST prompt the User for their consent to release the requested attributes. It MUST also display the contents of the Relying Party's registration certificate to ensure transparency about the requested data and its registered purpose.

Step 15: The User reviews the request and the Relying Party's registration information and then approves the presentation of the requested attributes.

Step 16: After receiving User approval, the Wallet Instance MUST retrieve the requested mdoc Digital Credentials. It then MUST prepare a SessionData message containing these Digital Credentials, and it MUST sign the required authentication data (as part of the mdoc authentication process, as specified in [ISO18013-5 #9.1.3]). It MUST encrypt it using the established session keys before transmitting it to the Relying Party Instance over the secure BLE channel. The signing ensures device binding and data integrity. The mdoc response MUST be encoded in CBOR, with its structure outlined in [ISO18013-5 #8.3.2.1.2.2].

Below is a non-normative example using the diagnostic notation of a CBOR-encoded SessionData that contains the mdoc response of a Wallet Attestation and an mDL.

{
    "version": "1.0",
    "documents": 
    [
      {
        "docType": "org.iso.18013.5.1.mDL",
        "issuerSigned": 
        {
          "nameSpaces": 
          {
            "org.iso.18013.5.1": 
            [
              24(<<
                {
                    "digestID": 0,
                    "random": h'790401ed5d0822d1aced942e4b0c41f754eee67b89c5ee3b8fd2c97491a96406',
                    "elementIdentifier": "family_name",
                    "elementValue": "Rossi"
                }
              >>),
              24(<<
                {
                    "digestID": 3,
                    "random": h'0c8f68d1ec3aa445ef68aa10b7a5875fa18ca222a821e23890a227cdc7d25e8f',
                    "elementIdentifier": "issue_date",
                    "elementValue": 1004(2025-03-27)
                }
              >>),
              24(<<
                {
                    "digestID": 4,
                    "random": h'0a9ed0d4937673152e52fb3fac0722baf4252e0d0c9869919e3339670203178e',
                    "elementIdentifier": "expiry_date",
                    "elementValue": 1004(2030-03-27)
                }
              >>),
              24(<<
                {
                    "digestID": 8,
                    "random": h'88e94c0365c611b523518d9a1b179ae52e242383576249f4965c40c6c97cf214',
                    "elementIdentifier": "document_number",
                    "elementValue": "XX1234567"
                }
              >>),
              24(<<
                {
                    "digestID": 9,
                    "random": h'944758b43602b01ad68911b062349845492c04c6a78129bcf8cb5fb1396af2fc',
                    "elementIdentifier": "portrait",
                    "elementValue": h'ffd8ffe000104a46494600010101009000900000ffdb004300130d0e110e0c
                    13110f11151413171d301f1d1a1a1d3a2a2c2330453d4947443d43414c566d5d4c51685241435f82
                    606871757b7c7b4a5c869085778f6d787b76ffdb0043011415151d191d381f1f38764f434f767676
                    76767676767676767676767676767676767676767676767676767676767676767676767676767676
                    76767676767676ffc00011080018006403012200021101031101ffc4001b00000301000301000000
                    000000000000000005060401020307ffc40032100001030303020502030900000000000001020304
                    0005110612211331141551617122410781a1163542527391b2c1f1ffc40015010101000000000000
                    00000000000000000001ffc4001a110101010003010000000000000000000000014111213161ffda
                    000c03010002110311003f00a5bbde22da2329c7d692bc7d0d03f52cfb0ff75e7a7ef3e7709723a1
                    d0dae146ddfbb3c039ce07ad2bd47a7e32dbb8dd1d52d6ef4b284f64a480067dfb51f87ffb95ff00
                    eb9ff14d215de66af089ce44b7dbde9cb6890a2838eddf18078f7add62d411ef4db9b10a65d6b95a
                    147381ea0d495b933275fe6bba75c114104a8ba410413e983dff004f5af5d34b4b4cde632d0bf1fd
                    1592bdd91c6411f3934c2fa6af6b54975d106dcf4a65ae56e856001ebc03c7ce29dd9eef1ef10fc4
                    47dc9da76ad2aee93537a1ba7e4f70dd8eff0057c6dffb5e1a19854a83758e54528750946ec67048
                    50cd037bceb08b6d7d2cc76d3317fc7b5cc04fb6707269c5c6e0c5b60ae549242123b0e493f602a0
                    75559e359970d98db89525456b51c951c8afa13ea8e98e3c596836783d5c63f5a61a99fdb7290875
                    db4be88ab384bbbbbfc7183fdeaa633e8951db7da396dc48524fb1a8bd611a5aa2a2432f30ab420a
                    7a6d3240c718cf031fa9ef4c9ad550205aa02951df4a1d6c8421b015b769db8c9229837ea2be8b1b
                    0d39d0eba9c51484efdb8c0efd8d258daf3c449699f2edbd4584e7af9c64e3f96b9beb28d4ac4093
                    1e6478c8e76a24a825449501d867d2b1dcdebae99b9c752ae4ecd6dde4a179c1c1e460938f9149ef
                    655e515c03919a289cb3dca278fb7bf177f4faa829dd8ce3f2ac9a7ecde490971fafd7dce15eed9b
                    71c018c64fa514514b24e8e4f8c5c9b75c1e82579dc1233dfec08238f6add62d391acc1c5256a79e
                    706d52d431c7a0145140b9fd149eb3a60dc5e88cbbc2da092411e9dc71f39a7766b447b344e847dc
                    ac9dcb5abba8d145061d43a6fcf1e65cf15d0e90231d3dd9cfe62995c6dcc5ca12a2c904a15f71dd
                    27d451453e09d1a21450961cbb3ea8a956433b781f1ce33dfed54f0e2b50a2b71d84ed6db18028a2
                    8175f74fc6bda105c529a791c25c4f3c7a11f71586268f4a66b726e33de9ea6f1b52b181c760724e
                    47b514520a5a28a283ffd9'  
                }
              >>),
              24(<<
                {
                    "digestID": 10,
                    "random": h'577e4822125f55fe923117aba01fdaefcc67d4aea80018fc22efa8d48e17982f',
                    "elementIdentifier": "driving_privileges",
                    "elementValue": [
                      {
                        "vehicle_category_code": "A",
                        "issue_date": 1004("2020-09-17"),
                        "expiry_date": 1004("2031-06-10")
                        }
                      ]
                }
              >>)
            ]
          },
          "issuerAuth": 
          [
            << {1: -7} >>,
            {
              33: h'30820208308201afa00302010202142eb39c647c81836bcf79fa9cd0b201ec0bf52307300a0
              6082a8648ce3d0403023064310b30090603550406130255533113301106035504080c0a43616c6966
              6f726e69613116301406035504070c0d53616e204672616e636973636f31133011060355040a0c0a4
              d7920436f6d70616e793113301106035504030c0a6d79736974652e636f6d301e170d323530333237
              3135353532305a170d3235303430363135353532305a3064310b30090603550406130255533113301
              106035504080c0a43616c69666f726e69613116301406035504070c0d53616e204672616e63697363
              6f31133011060355040a0c0a4d7920436f6d70616e793113301106035504030c0a6d79736974652e6
              36f6d3059301306072a8648ce3d020106082a8648ce3d03010703420004f33da72d0dd0009b62221b
              0e839099b12dab5e01021124ebf9060422e648f3c3ec6614a86da1e91e552b2ae35e04d3058ae82b5
              c65a7f1f26800cb4499652a09a33f303d303b0603551d1104343032863068747470733a2f2f637265
              64656e7469616c2d6973737565722e6f6964632d66656465726174696f6e2e6f6e6c696e65300a060
              82a8648ce3d040302034700304402204d1f0819971652b79ebe4825547de3d5554d2f41410225e6b1
              3dab949cda125e022079ba71b823619e49719dce5daa565bf745d3d97e2b87c7f7d6a626f981e653ed'
            },
            <<
              24(<<
                {
                  "version": "1.0",
                  "digestAlgorithm": "SHA-256",
                  "docType": "org.iso.18013.5.1.mDL",
                  "valueDigests": {
                    "org.iso.18013.5.1": 
                    {
                        0: h'f46b65d5060ad060ab9be62ff22ea8633437619ebdc7fa81f2d151159e92bffe',
                        1: h'e506545f6a6fd5d982670b4d62fc2b0688dc8f26754e7b0c574d63f5d72a85ac',
                        2: h'cfcf96fa12d100eeed5f00183d3b6a0888baa47eae85b5b95037eca7bbc0d07e',
                        3: h'8b0772252b0e06b611676b6b3402eb33bf866eb145e49f4d5f23215e6a047772',
                        4: h'14135c96693e2ab08d956876ee491357d906a6dd125557196dfb9811ba54aa8d',
                        5: h'86dcbd99233fbb84a9a2dce3a864a425e6e809300067a4475e3ea2a4d233dc74',
                        6: h'2e9512d35ea225e69e7b2180ecc1678dcc3e77a16e36427e64b4f0e2861b4d3a',
                        7: h'4efe55c36f6249d23c473a125afc5181aa30633936494781554971b72ff13700',
                        8: h'cc44a4f9983c5b0b1efc0e82e2867c8d5bbdf89c34bff16a1953c923bb4e4b3e',
                        9: h'775eb2af0aa55f2071d62662b35c99698ae3bc0e2c4af5724ff88476cddd152f',
                       10: h'915d0ad53dd23dace34968c263d307c04701a9bb9dc9865af91dc409786fd833',
                       11: h'47d89ff4fb513044e6f2394236755ac0abf3e4f4a46f40454a458a59f8b7a6fb'
                    },
                    "org.iso.18013.5.1.IT": {
                       12: h'16d2098702e896b4614dff1859bd3b42105cac2e62ce7f87dcacc249a656db32',
                       13: h'755fd7c0f9272a8589c4a661a8aa80dc916018e500884eba316899d653fcb8d1'
                      }
                  },
                  "deviceKeyInfo": {
                    "deviceKey": {
                        1: 2,
                       -1: 1,
                       -2: h'f96b29873b61f05403e2963a7ecbc799c9aab28d8a6629e5848cfdef85442866',
                       -3: h'a9fef033a900c63e3894d8deb805a2a1fb55ef0d2b88e3c0d3336408186485ef'
                    }
                  },
                  "validityInfo": {
                    "signed": 0("2025-03-27T00:00:00Z"),
                    "validFrom": 0("2025-03-27T00:00:00Z"),
                    "validUntil": 0("2026-03-27T00:00:00Z")
                  },
                  "status": {
                    "status_list": {
                      "idx": 1340,
                      "uri": "https://statusprovider.example.org/statuslists/1"                           
                    }
                  }
                }
              >>)
            >>,
            h'd09f9acdf7a6be5e4aeb405bfb3b297b1b8003bcf52558a2f39fc6e5cffed40f18f49d2cc0e72a2a5645
            8d8aade591dee8d6540e639bca637f94bd9fa56f345c'
          ]
        },
        "deviceSigned": 
        {
          "nameSpaces": 24(<< {} >>),
          "deviceAuth": 
          {
            "deviceSignature": 
            [
              << {1: -7} >>,
              {},
              null,
              h'E99521A85AD75943BF5AEAE68943BF5AE249943BF5AE943BF5AE43BF5AEDE99521A85AD75943BF5AEAE
              68943BF5AE249943BF5AE943BF5AE43BF5AED'

            ]
          }
        }
      },
      {
        "docType": "org.iso.18013.5.1.IT.WalletAttestation",
        "issuerSigned": 
        {
          "nameSpaces": 
          {
            "org.iso.18013.5.1.IT": 
            [
              24(<<
                {
                  "digestID": 0,
                  "random": h'691a4e9c599982a009e6e0e4d64784e53dd8b1ebca79e7d6eb2146b16c7def7a',
                  "elementIdentifier": "wallet_name",
                  "elementValue": "Wallet_Hobbiton_v1"
                }
              >>),
              24(<<
                {
                  "digestID": 1,
                  "random": h'6659db56b91fd967107742dc45dff9e692f03bb9298e8b90b0cefbe6f7475f25',
                  "elementIdentifier": "wallet_link",
                  "elementValue": "https://example.com/wallet/detail_info.html"
                }
              >>),
              24(<<
                {
                  "digestID": 2,
                  "random": h'147cb4f9a4a8b71cb13a963e73dfa01ec59953831dda0a818e9b8c457ff91b31',
                  "elementIdentifier": "sub",
                  "elementValue": "3B4hK2m7fA9TdVzqLrGp6W8XyJ1sNtQc"
                }
              >>),
              24(<<
                {
                  "digestID": 3,
                  "random": h'c1e2ded83eb15143e16f3e4bcda9a7804f467263a59b0f4f3269ccdc240ce453',
                  "elementIdentifier": "aal",
                  "elementValue": "https://trust-list.eu/aal/high"
                }
              >>)
            ]
          },
          "issuerAuth": 
          [
            << {1: -7} >>,
            {
              33: h'207581c0bc387bf3d7e7c7a3991395ed28069806e5ed21fdeb19aaa6f33bd9da98c88e44fc32
              cb19578e472a2cf4ed2c9182864265754dc19941a4b408d056a657a649bc67a9aa0e22ff76460680e7
              4b26197dd542a41ac6d99dc6a94bbfc668844705cd4dd6b56f521339174deda55676088b531901c992
              a65e97213037215057cb4d8519b2ea8c03b376b048b9c60f75586b067456ae78aac9e472b1fa6ce0cf
              65345c463ae0c94e59bb034597533a14a84f4b99d19b72207607c2f692e6956822cb19736de6b38477
              d726ac07983cfe9cd1e27b59f3cabae28653eac2bbf884fca22122df8c78da110c411f310abd6fae86
              2e7766044e1af78525dabf5412ebcf57532ee25b959fa1d591f950adb46da1cec14c0a6c08383a95de
              5fad9673fdf72130029b81350d048568fa1b962ba2118af48a8c4aaf074e5265f367d134055a4c9f99
              21a8f03050e062a5b91bb053bcbd69bc59e37ac0c3a6358461893fae6f87021c6492638864ae38afb6
              aa444406c1c296300be1a152b27fbcdd543d73888199f2daf3bc007bdcbacf2f6a8d498c4d6f42f59f
              0cc8967db15016faf81c3fbd4585e5eb657c13c86d4149d17a10417d3a65342d206fdbd3ba139b8d9a
              175b27a4578f37703b20cd2179c6e9ce49c26391e46753c86b80ea0837bc71c57893cacf4e76f1bbe1
              ce2292914d5d247cecb579d36271ae0b7d0988ef42105c90fda654a7a41908a8680b38896689f3e511
              663bcf667d7a2787e1bb8effa3b9910064d59609f58f98e3e9edd35aa4f170da7521db1c6ab6b3a6fb
              e585778fccf2426417d509c5f2e7d5b726148a46373f0b43bf6749b4c8af592b0a032a3971cb0ea453
              9c2493314b4429b7d88b8abd160342e9d8e790dd61c0def2e84df2db0d7f8603814ca49a49c76513b0
              94c283ca5bf60710ee5fd7511d0307184b8b3349f5ac6cc29d2d5429b0e9cdb6ba72a53159833f45d3
              72c1b191f20434e7a9120f528d1c9463d5b58380e1087f288c444cc55c182663ee3a4a70ae21784093
              5276a1c8424a8a893175dd080704daeceffee9c8e453adcadd3f0ba383bbed6f0d3cada8055d08008d
              b244da9e59f9972641c036fcac047d2d067bca02bca7f752'
            },
            <<
              24(<<
                {
                  "version": "1.0",
                  "digestAlgorithm": "SHA-256",
                  "docType": "org.iso.18013.5.1.it.WalletAttestation",
                  "valueDigests": {
                  "org.iso.18013.5.1.IT": {
                      0: h'0f1571a988fcdf29290d4a509d25b24c7b182d8c3f5db27c761f6b7ec9b0c830',
                      1: h'0cdfe0774a2b596c90b147ae3a61fd55f06cb7490aab76d3a49105dc3c5a987b',
                      2: h'e238214925589843954da4f60772ce3054fd8f0a0c1f5a4b6f2a791b7ec1993f',
                      3: h'bbc77e6cce544edf864f2cf60d9f1eb13998a99126584b3615a6437f822ea820'
                    }
                  },
                  "deviceKeyInfo": {
                    "deviceKey": {
                      1: 2,
                     -1: 1,
                     -2: h'b820963964e5483cb929a3e8bb79da5a7137f50f859f6a173d3d642cefa8f419',
                     -3: h'0a6da0af437ebf9672351dcac420f1a37924bde1076c4cf09f4cb05ad3dba8b0'
                    }
                  },
                  "validityInfo": {
                    "signed": 0("2025-03-03T10:00:00Z"),
                    "validFrom": 0("2025-03-03T10:00:00Z"),
                    "validUntil": 0("2026-03-03T10:00:00Z")
                  }
                }
              >>)
            >>,
            h'98F1D2C47EB3AA09F5F3CCF2839D7E6A12B37E5A4C9E42E7B0D5D299AB5CE87F7A0DFF12B6A5CC
            9D9B329A8165F8B163D479DEA9A2E4B0C30FD6C83FADB5E244'
          ]
        },
        "deviceSigned": 
        {
          "nameSpaces": 24(<< {} >>),
          "deviceAuth": 
          {
            "deviceSignature": 
            [
              << {1: -7} >>,
              {},
              null,
              h'E99521A85AD75943BF5AEAE68943BF5AE249943BF5AE943BF5AE43BF5AEDE99521A85AD75943
              BF5AEAE68943BF5AE249943BF5AE943BF5AE43BF5AED'
            ]
          }
        }
      }
    ],
    "status": 0
}

Step 17: The Relying Party Instance receives the SessionData, then it MUST decrypt it, and it MUST verify the Wallet Instance's signature to ensure the data's integrity and that it originates from the expected device (device binding). It also MUST check the validity of the mdoc, including its Issuer's signature. In case of long-lived Digital Credentials, it SHOULD also check the revocation status using TOKEN-STATUS-LIST.

Step 18: Once the data exchange is complete, either party can terminate the session. If BLE is used, this can involve sending a status code for session termination or the “End” command. In this scenario, the GATT Client (Relying Party Instance) MUST unsubscribe from characteristics and disconnect from the GATT server (Wallet Instance).

Final Consideration: The presentation flow focused on the technical data exchange in proximity settings. It is crucial to recognise that supervised proximity flows involving a human verifier play a vital role in many use cases (e.g., age verification at a store, identity check by law enforcement). The human element adds a layer of identity verification through visual inspection and comparison, contributing to User Binding and overall authentication assurance aspects not fully captured in a purely technical presentation flow.

Note

During proximity presentation the Wallet Instance might not be able to fetch a fresh Wallet Attestation, in this case, the Wallet Instance SHOULD send the latest version of the Wallet Attestation. It is left up to the Relying Party to determine whether a presentation with a valid but expired Wallet Attestation is valid or not.

Device Engagement

The Device Engagement structure MUST be CBOR encoded and have at least the following components:

Component

Description

Version

(tstr). Version of the device engagement structure.

Security

(array). Contains two mandatory values:

  • (int). Cipher suite identifier. See Table 22 of ISO18013-5.

  • (bstr). Public ephemeral key generated by the Wallet Instance, used by the Relying Party Instance to derive the Session Key. The key MUST be of a type allowed by the selected cipher suite.

BleOptions

(map). Provides options for the BLE connection, such as Peripheral Server or Central Client mode, and the device UUID.

Only Central Client Mode MUST be supported by this implementation profile.

Capabilities

(map). Declares optional capabilities supported by the mdoc, that are:

  • HandoverSessionEstablishmentSupport (bool). If present, it MUST be set to true. Indicates support for receiving the SessionEstablishment message during Negotiated Handover, as defined in [ISO18013-5 #8.2.2.4].

  • ReaderAuthAllSupport (bool). If present, it MUST be set to true. Indicates support for receiving the ReaderAuthAll structure in the mdoc request, as defined in [ISO18013-5 #8.3.2.1.2.1].

OriginInfos

(array). Describes the interface used to receive and deliver the engagement structure.

When used in flows defined in [ISO18013-5 #6.3.2.1], OriginInfos MAY be an empty array.

mdoc Request

The messages in the mdoc Request MUST be encoded using CBOR. The resulting CBOR byte string for the mdoc Request MUST be encrypted with the Session Key obtained after the Device Engagement phase and MUST be transmitted using the BLE protocol. Each mdoc Request MUST be compliant with the following structure, and MUST include the following components, unless otherwise specified:

Component

Description

version

(tstr). Version of the mdoc Request structure. Enables compatibility management across different versions or implementation profiles.

docRequests

(array). Each entry is a DocRequest containing:

  • itemsRequest. CBOR-encoded ItemsRequest structure, formatted as:

    • docType (tstr). The type of document requested. See mdoc-CBOR Credential Format.

    • nameSpaces (map). A map of namespace identifiers to requested DataElements.

      Each entry in DataElements includes:

      • DataElementIdentifier (tstr). The identifier of the requested data element.

      • IntentToRetain (bool). Indicates whether the Relying Party intends to retain the value of the data element.

  • readerAuth (COSE_Sign1, CONDITIONAL). Used to authenticate the the Relying Party Instance for each DocRequest. The signature is computed over ReaderAuthentication data, as defined in [ISO18013-5 #9.1.4].

    This component MUST be present only if readerAuthAll is not used.

readerAuthAll

(COSE_Sign1, CONDITIONAL). Used to authenticate the Relying Party once for all DocRequest`s. The signature is computed over `ReaderAuthenticationAll data, as defined in [ISO18013-5 #9.1.4].

This component MUST be present only if ReaderAuthAllSupport is set to true in the DeviceEngagement structure, and individual readerAuth fields are not used.

mdoc Response

The messages in the mdoc Response MUST be encoded using CBOR and MUST be encrypted with the Session Key obtained after the Device Engagement phase. Each mdoc Response MUST be compliant with the following structure, and MUST include the following components, unless otherwise specified:

Component

Description

version

(tstr). Version of the mdoc Response structure. Enables tracking changes and maintaining compatibility across versions of the standard or implementation profiles.

documents

(array of Documents, OPTIONAL). CBOR-encoded collection of documents returned in response to the request. Each document includes issuerSigned and deviceSigned components, and follows the structure defined in the below table.

documentErrors

(map, OPTIONAL). A map of error codes for unreturned documents, as defined in [ISO18013-5 #8.3.2.1.2.3]. Each key is a docType, and each value is an ErrorCode (int) indicating the reason why the document was not returned.

status

(uint). Status code indicating the outcome of the request. For example, "status": 0 means successful processing. For details, see Table 8 (ResponseStatus) of [ISO18013-5 #8.3.2.1.2].

Each document in documents MUST be compliant with the following structure, and it MUST include the following components, unless otherwise specified:

Component

Description

docType

(tstr). Document type identifier. For example, for an mDL, the value MUST be org.iso.18013.5.1.mDL.

issuerSigned

(bstr). Contains the IssuerNameSpaces structure, which includes data elements signed by the Issuer, and the issuerAuth structure, which ensures their authenticity and integrity using the Mobile Security Object (MSO). See mdoc-CBOR Credential Format.

deviceSigned

(bstr). Contains the DeviceNameSpaces structure (data elements signed by the Wallet Instance), and the deviceAuth structure, which includes the authentication data signed by the Wallet Instance. See the table below for details.

errors

(map, OPTIONAL). A map of error codes for each unreturned data element grouped by namespace. Each key represents a namespace, and each value is a map of data element identifiers to corresponding error codes. See [ISO18013-5 #8.3.2.1.2.3] for details on the errors structure.

A deviceSigned data structure MUST be compliant with the following structure, and MUST include the following components:

Component

Description

nameSpaces

(bstr). Contains the DeviceNameSpaces structure. It MAY be an empty structure. DeviceNameSpaces maps namespace identifiers to a set of data elements signed by the Wallet Instance.

Each namespace contains one or more DeviceSignedItem, where each item includes:

  • DataItemName (tstr). The identifier of the data element.

  • DataItemValue (any). The value of the data element.

deviceAuth

(COSE_Sign1). Contains the DeviceAuth structure, which MUST include the deviceSignature for the Wallet Instance authentication. The signature is computed over the DeviceAuthentication data, which binds the returned elements to the session and the request. See [ISO18013-5 #9.1.3] for details on the authentication structure.

Session Termination

The session MUST be terminated if at least one of the following conditions occur:

  • after a time-out of no activity of receiving or sending session establishment or session data messages occurs. The time-out for no activity implemented by the Wallet Instance and the Relying Party Instance SHOULD be no less than 300 seconds;

  • when the Wallet Instance does not accept any more requests;

  • when the Relying Party Instance does not send any further requests.

If the Wallet Instance and the Relying Party Instance does not send or receive any further requests, the session termination MUST be initiated as follows:

  • send the status code for session termination, or

  • dispatch the "End" command as outlined in [ISO18013-5 #8.3.3.1.1.5].

When a session is terminated, the Wallet Instance and the Relying Party Instance MUST perform at least the following actions:

  • destruction of session keys and related ephemeral key material;

  • closure of the communication channel used for data retrieval.

Note

See mdoc-CBOR Credential Format for the meaning of CBOR type acronyms.