Skip to content

Verify Module

Abstract

This document defines how an Authorizing Party receives, verifies, and authorizes a PaSO transaction. It specifies the proof package structure forwarded by the Relying Party, the verification procedure, and a standard endpoint for ingesting transactions.

1 Introduction

1.1 Overview

After the Wallet produces a presentation response, the Relying Party forwards the proof package to the Authorizing Party. This module defines what the proof package contains, how the Authorizing Party verifies it, and a standard HTTP endpoint for receiving it.

How the Relying Party obtains the Authorizing Party's public key and endpoint URI is out of scope of this document.

1.2 Requirements Notation

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in [RFC2119] and [RFC8174] when, and only when, they are written in all capital letters.

2 Proof Package

The Relying Party SHALL forward the following to the Authorizing Party:

  1. The signed [OID4VP] Authorization Request ([JAR] Request Object) as sent to the Wallet, in its compact-serialised JWT form.
  2. The full vp_token as received from the Wallet.

The Relying Party SHALL NOT modify either artefact. Section 4 defines a standard endpoint for forwarding; the applicable Transaction Data Type Rulebook MAY define alternative forwarding mechanisms.

3 Verification Procedure

Upon receiving the proof package, the Authorizing Party SHALL perform the following checks:

  1. Request verification: Verify the signed Authorization Request JWT signature. Verify the Relying Party's identity from the request.

  2. Credential verification: Verify the PaSO Credential in the vp_token:

  3. Validate the credential signature.
  4. Verify the credential has not expired.
  5. Verify the credential has not been revoked.

  6. Holder binding proof verification: Verify the holder binding proof (KB-JWT for [SD-JWT-VC], DeviceAuthentication for [mdoc]).

  7. SCA response claims verification per [PaSO Core] Section 6.1:

  8. transaction_data_hash: recompute the hash from the transaction_data entry in the Authorization Request and verify it matches.
  9. transaction_data_hash_alg: verify the algorithm is acceptable.
  10. request_integrity: recompute the [W3C.SRI] integrity value of the signed Authorization Request JWT and verify it matches.
  11. metadata_integrity: if present, verify it matches the [W3C.SRI] integrity value of the Attestation Provider's current signed credential metadata JWT for this credential.
  12. display_locale: verify that the locale matches a locale for which the credential metadata provides complete display entries.
  13. jti: verify uniqueness (the Authorizing Party SHOULD maintain a replay cache).

  14. Payload verification: Verify that the transaction_data entry's payload conforms to the applicable Transaction Data Type Rulebook. The specific checks are defined by the rulebook.

  15. Risk-signals verification per [PaSO Risk Signals] Section 6:

  16. Resolve the effective signal set for the matched transaction data type per [PaSO Risk Signals] Section 4.1: the union of every referenced risk signal profile, then tightened by any metadata or rulebook enumeration. Signal types are defined by [PaSO Risk Signal Registry].
  17. Verify that every signal resolved as required is present in the risk_signals claim, with any status. The absence of a signal that did not resolve as required SHALL NOT be treated as a failure.
  18. Verify each envelope is well-formed and that its collected_at is no older than the max_age resolved for that signal, measured from the time the proof package was received and allowing for reasonable clock skew and forwarding delay. Where no max_age was resolved, the acceptable window is a matter of Transaction Data Type Rulebook or Authorizing Party policy.
  19. When urn:paso:risk:global:amr:1 is present, verify that the authentication methods it reports meet the requirements of the applicable Transaction Data Type Rulebook.
  20. When urn:paso:risk:global:response_mode:1 is present, verify that its value matches the response_mode of the received Authorization Request.
  21. Interpreting signal values to reach a risk decision is out of scope and left to Authorizing Party policy.
  22. When encryption is required for the transaction data type, verify that the risk_signals value is an encrypted structure and reject a plaintext value; the presence, well-formedness, freshness, and signal-specific checks above are performed by the holder of the issuer decryption key after decryption, as defined in [PaSO Risk Signals] Section 6.1. An Authorizing Party that is not the issuer therefore cannot perform the amr check — see [PaSO Risk Signals] Section 7.8.

If any check fails, the Authorizing Party SHALL reject the transaction.

4 Transaction Ingestion Endpoint

The Authorizing Party MAY expose an HTTP endpoint for receiving proof packages.

4.1 Request

The Relying Party SHALL send an HTTP POST request to the endpoint with:

  • Content-Type: application/jose when encrypted per Section 4.3, or application/json otherwise.
  • Body: The proof package as defined below.

When the body is application/json, it SHALL have the following structure:

{
  "signed_request": "<compact-serialised Authorization Request JWT>",
  "vp_token": "<vp_token as received from the Wallet>"
}
  • signed_request: REQUIRED. The signed [OID4VP] Authorization Request in compact JWT serialisation.
  • vp_token: REQUIRED. The vp_token as received from the Wallet.

4.2 Response

The endpoint SHALL respond with:

  • 200 OK — the transaction was accepted.
  • 400 Bad Request — the proof package is malformed or a verification check failed. The response body SHOULD be a JSON object with an error field describing the failure.
  • 401 Unauthorized — the Relying Party could not be authenticated.
  • 409 Conflict — the jti has already been processed (replay).

4.3 Encryption

The Relying Party SHOULD encrypt the proof package as a [JWE] compact serialisation. The JWE SHALL be:

  • signed by the Relying Party using its trust chain,
  • encrypted to the Authorizing Party's public key, so that only the Authorizing Party can decrypt it.

The JWE payload is the JSON proof package defined in Section 4.1. The JOSE header SHALL include the Relying Party's certificate chain in the x5c parameter.

How the Relying Party obtains the Authorizing Party's public key is out of scope of this document.

5 References

Reference Description
[PaSO Core] PaSO Core
[PaSO Proof Metadata] PaSO Proof: Metadata Module
[PaSO Risk Signals] PaSO Proof: Risk Signals Module
[PaSO Risk Signal Registry] PaSO Proof: Risk Signal Registry
[OID4VP] OpenID for Verifiable Presentations 1.0
[JAR] RFC 9101 — JWT-Secured Authorization Request
[JWE] RFC 7516 — JSON Web Encryption
[SD-JWT-VC] SD-JWT-based Verifiable Credentials
[mdoc] ISO/IEC 18013-5:2021 — Mobile driving licence application
[RFC2119] RFC 2119 — Key words for use in RFCs
[RFC8174] RFC 8174 — Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words
[W3C.SRI] Subresource Integrity