Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DCQL: express desired credential issuers #393

Open
wants to merge 11 commits into
base: main
Choose a base branch
from
145 changes: 144 additions & 1 deletion openid-4-verifiable-presentations-1_0.md
Original file line number Diff line number Diff line change
Expand Up @@ -693,6 +693,16 @@ this object are defined per Credential Format. Examples of those are in (#sd_jwt
no specific constraints are placed on the metadata or validity of the requested
Credential.

`accepted_issuers`:
: OPTIONAL. A non-empty array of objects as defined in (#dcql_accepted_issuers) that
specifies expected issuers or trust frameworks that an issuer belongs to, that the
Verifier will accept. Every Credential returned by the Wallet SHOULD match at least
one of the conditions present in the corresponding `accepted_issuers` array if present.

Note that Relying Parties must verify that the issuer of a received presentation is
trusted on their own and this feature mainly aims to help data minimization by not
revealing information that would likely be rejected.

Comment on lines +696 to +705
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
`accepted_issuers`:
: OPTIONAL. A non-empty array of objects as defined in (#dcql_accepted_issuers) that
specifies expected issuers or trust frameworks that an issuer belongs to, that the
Verifier will accept. Every Credential returned by the Wallet SHOULD match at least
one of the conditions present in the corresponding `accepted_issuers` array if present.
Note that Relying Parties must verify that the issuer of a received presentation is
trusted on their own and this feature mainly aims to help data minimization by not
revealing information that would likely be rejected.
`accepted_issuers`:
: OPTIONAL. A non-empty array of objects as defined in (#dcql_accepted_issuers) that
specifies expected Credential Issuers that the
Verifier accepts. Every Credential returned by the Wallet SHOULD match at least
one of the conditions present in the corresponding `accepted_issuers` array if present.
Relying Parties using this parameter MUST ensure that the Credential Issuers specified are both active and trusted at the time of the query.

I would not mix trust frameworks identifiers with credential identifiers in the same parameter

`claims`:
: OPTIONAL. A non-empty array of objects as defined in (#claims_query) that specifies
claims in the requested Credential. Verifiers MUST NOT point to the same claim more than
Expand All @@ -705,6 +715,128 @@ The rules for selecting claims to send are defined in (#selecting_claims).

Note that multiple Credential Queries in a request MAY request a presentation of the same Credential.

### Accepted Issuer Query {#dcql_accepted_issuers}

An Accepted Issuer Query is an object representing information that helps to identify an issuer
or the trust framework that an issuer is belonging to. A Credential is identified as a match
to an Accepted Issuer Query if it to matches with one of the provided values in one of the provided
types. How exactly the matching works is defined for the different types below

Note that explicit issuer matching can also be achieved using claim value matching for certain
Credential formats (e.g., value matching the `iss` claim in an SD-JWT). The methods provided in
accepted_issuers are more tailored towards matching trust frameworks and those that require more
complex matching logic (e.g., certificate thumbprints).

Each entry in `accepted_issuers` MUST be an object with the following properties:

`type`:
: REQUIRED. A string uniquely identifying the type of information about the issuer trust framework.
Types defined by this specification are listed below.

`values`:
: REQUIRED. An array of strings, where each string (value) contains information specific to the
used Accepted Issuer Query type that allows to identify an issuer, trust framework, or a federation that an
issuer belongs to.

Below are descriptions for the different Type Identifiers (string), the description on how to interpret
and perform the matching logic for each provided value.
Comment on lines +720 to +742
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
An Accepted Issuer Query is an object representing information that helps to identify an issuer
or the trust framework that an issuer is belonging to. A Credential is identified as a match
to an Accepted Issuer Query if it to matches with one of the provided values in one of the provided
types. How exactly the matching works is defined for the different types below
Note that explicit issuer matching can also be achieved using claim value matching for certain
Credential formats (e.g., value matching the `iss` claim in an SD-JWT). The methods provided in
accepted_issuers are more tailored towards matching trust frameworks and those that require more
complex matching logic (e.g., certificate thumbprints).
Each entry in `accepted_issuers` MUST be an object with the following properties:
`type`:
: REQUIRED. A string uniquely identifying the type of information about the issuer trust framework.
Types defined by this specification are listed below.
`values`:
: REQUIRED. An array of strings, where each string (value) contains information specific to the
used Accepted Issuer Query type that allows to identify an issuer, trust framework, or a federation that an
issuer belongs to.
Below are descriptions for the different Type Identifiers (string), the description on how to interpret
and perform the matching logic for each provided value.
An Accepted Issuer Query is an object representing information that identify one or more Credential Issuers.
A Credential matches an Accepted Issuer Query if it aligns at least its Credential Issuer and the Credential Issuer configures the Credential as supported (eg: `iss` and `vct` for SD-JWT). Different Credential Types may use different matching approaches.
Each `accepted_issuers` object MUST have the following members:
`credential_issuer`:
: REQUIRED. A string uniquely identifying the Credential Issuer.
`trust_evaluations_supported`:
: REQUIRED. An array of strings, uniquely identifying the type of information about the trust evaluation mechanism the Credential Issuer MUST support.
`trust_frameworks_supported`:
: OPTIONAL. An array of strings, where each string (value) contains information specific to the
supported trust framework the Credential Issuer MUST belong to, to be considered a valid Credential Issuer.
Below are descriptions for the different Type Identifiers (string), the description on how to interpret
and perform the matching logic for each provided value.

Copy link
Member Author

@c2bo c2bo Feb 11, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think your proposal would work with the current scope of the PR:

  • Part of the problem initially discussed in the issue was that not every issuer is easily identified by a string (see the Authority Key Identifier discussion)
  • The discussion in the issue basically spanned 2 problems:
    • Direct issuer matching -> This will be done by value matching (out of scope here) unless impossible (AKI)
    • Expressing requirements about the trust chain/path -> Instead of directly identifying the issuer, expressing some expected properties/entities in the trust chain

This PR mainly covers the second part - describing some requirements that the trust chain/path of a credential has to fulfil. I think some of the confusion stems from the rather unfitting name "accepted_issuers"?


#### X.509 Thumbprint
Copy link
Collaborator

@Sakurann Sakurann Jan 28, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reasoning to introduce this was for the CA that do not have AKIs. CAB forum mandates AKIs, but not all CAs are web certificates, so those might not have AKIs - not sure how many of those certs don't have AKIs..?


Type:
: `"x5t#S256"`

Value:
: The base64url encoded SHA-256 digest (a.k.a. thumbprint, fingerprint) of the DER encoding of an X.509
certificate as defined in Section 4.1.8 of [@!RFC7515]. This thumbprint MUST match with the thumbprint
of an X.509 certificate in the trust chain of the Credential.

Below is a non-normative example of such an entry of type `x5t#S256`:
```json
{
"type": "x5t#S256",
"values": ["455943cf819425761d1f950263ebf54755d8d684c25535943976f488bc79d23b"]
}
```

Comment on lines +744 to +761
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd suggest removing X.509 thumbprint because it is less useful than aki and doesn't have any benefit over aki. It has actually a couple of downsides like having issues with re-issued certificates.

Suggested change
#### X.509 Thumbprint
Type:
: `"x5t#S256"`
Value:
: The base64url encoded SHA-256 digest (a.k.a. thumbprint, fingerprint) of the DER encoding of an X.509
certificate as defined in Section 4.1.8 of [@!RFC7515]. This thumbprint MUST match with the thumbprint
of an X.509 certificate in the trust chain of the Credential.
Below is a non-normative example of such an entry of type `x5t#S256`:
```json
{
"type": "x5t#S256",
"values": ["455943cf819425761d1f950263ebf54755d8d684c25535943976f488bc79d23b"]
}
```

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The 2 biggest reasons why I chose to include it in the initial proposal was

  • x5t is somewhat commonly used in the oauth world -> keep the choices consistent
  • AuthoriyKeyIdentifier is an extension and I was not sure if every ecosystem that would want to use AKI.

That said, I am happy to remove it if everyone can use / is happy with AKI. Less choices is always a good thing. It would also be easy to re-introduce x5t later on.

#### Authority Key Identifier
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ISO feedback. less options the better. AKI alone is probably sufficient. AKI meets ISO requirement.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Then we should consider dropping VICAL.


Type:
: `"aki"`

Value:
: The base64url encoded Authority Key Identifier element as defined in Section 4.2.1.1 of [@!RFC5280].
The raw byte representation of this element MUST match with the AuthorityKeyIdentifier element of an X.509
certificate in the trust chain of a matching Credential.

Below is a non-normative example of such an entry of type `aki`:
```json
{
"type": "aki",
"values": ["s9tIpPmhxdiuNkHMEWNpYim8S8Y"]
}
```

#### Verified Issuer Certificate Authority List (VICAL)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DCP WG discussion. leaning to keep it in OpenID4VP because value is not defined as a URL, but an identifier that does not have to be resovled


Type:
: `"vical"`

Value:
: The identifier (can also be a URL) of a Verified Issuer Certificate Authority List (VICAL) as specified in
[@ISO.18013-5]. The VICAL contains a list of Issuing Authority Certificate Authorities (IACA), that provide
DER encoded X.509 Certificates and corresponding allowed document types (an array of DocType identifiers).
This Type MUST only be used in combination with Credentials of the Credential Format mdoc. The trust chain
of a matching Credential MUST contain at last one X.509 Certificate entry in the IACAs and the allowed
DocTypes of the corresponding IACA entry MUST match with the doctype of the Credential.

Below is a non-normative example of such an entry of type `vical`:
```json
{
"type": "vical",
"values": ["https://vical.example.com"]
}
```

#### ETSI Trusted List

Type:
: `"etsi_tl"`

Value:
: The identifier (can also be a URL) of a Trusted List as specified in ETSI TS 119 612 [@ETSI.TL].An ETSI
Trusted List contains references to other Trusted Lists, creating a list of trusted lists, or entries
for Trust Service Providers with corresponding service description and X.509 Certificates. The trust chain
of a matching Credential MUST contain at least one X.509 Certificate that matches one of the entries of the
Trusted List or its cascading Trusted Lists.

Below is a non-normative example of such an entry of type `etsi_tl`:
```json
{
"type": "etsi_tl",
"values": ["https://lotl.example.com"]
}
```

#### OpenID Federation

Type:
: `"openid_fed"`

Value:
: The `Entity Identifier` as defined in Section 1 of [@!OpenID.Federation] that is bound to
an entity in an OpenID Federation System. While this Entity Identifier could be any entity in

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could change OpenID Federation System to a federation or an ecosystem or something along these lines.

that ecosystem, this entity would usually have the Entity Configuration of a Trust Anchor.
The trust chain of a matching credential MUST contain the given Entity Identifier.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
The trust chain of a matching credential MUST contain the given Entity Identifier.
The trust chain of a matching credential MUST contain the Entity Configuration issued by the Entity identified by the given Entity Identifier.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is no direct use case for that but logically we should also consider including option to use intermediary ids. Any thoughts?

Copy link
Member Author

@c2bo c2bo Jan 23, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds reasonable to me with my limited knowledge of OIDF, @selfissued, @peppelinux ?

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With the disclaimer that I'm no expert in OIDF, I believe there is no such thing as "the trust chain" for a given credential. There could be multiple trust roots that a credential could chain up to (especially assuming that roots will cross-certify each other as trusted peers, e.g. in the EU). So I would recommend something like "A valid trust path, terminating at the given Entity Identifier, must be constructible from a matching credential".

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed that trust chain doesn't seem to be the best wording here. I am a bit hesitant with the word "terminating" as it sounds like we want to allow intermediate entities and terminating could be interpreted as reaching a Trust Anchor?

Would this work for you @lj-raidiam , @balfanz

Suggested change
The trust chain of a matching credential MUST contain the given Entity Identifier.
A valid trust path, reaching the given Entity Identifier, must be constructible from a matching credential.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm curious how the processing of this would work. Knowing if you can build a chain including the requested entity id often involves a (complicated) resolving process. As @balfanz pointed out, multiple paths could exist, so you'd either have to:

  • store (a subset of) the possible trust chains with the credential, so you can perform this offline
  • resolve the trust chain dynamically to match (this doesn't seem like a good approach, credential matching should be performed locally IMO).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reaching would still suggest an end, maybe including works?

Suggested change
The trust chain of a matching credential MUST contain the given Entity Identifier.
A valid trust path, including the given Entity Identifier, must be constructible from a matching credential.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm curious how the processing of this would work. Knowing if you can build a chain including the requested entity id often involves a (complicated) resolving process. As @balfanz pointed out, multiple paths could exist, so you'd either have to:

  • store (a subset of) the possible trust chains with the credential, so you can perform this offline
  • resolve the trust chain dynamically to match (this doesn't seem like a good approach, credential matching should be performed locally IMO).

Yes, wallets will have to store it for all credentials to do the filtering. Perhaps in more complex case (like two paths) this filtering will not be ideal. Verifiers will have a harder work to do as they will have to resolve it dynamically in most cases.


Below is a non-normative example of such an entry of type `openid_fed`:
```json
{
"type": "openid_fed",
"values": ["https://trustanchor.example.com"]
}
```

## Credential Set Query {#credential_set_query}

A Credential Set Query is an object representing a request for one or more credentials to satisfy
Expand Down Expand Up @@ -1850,6 +1982,16 @@ In the event that another component is invoked instead of the Wallet, the End-Us
</front>
</reference>

<reference anchor="ETSI.TL" target="https://www.etsi.org/deliver/etsi_ts/119600_119699/119612/02.01.01_60/ts_119612v020101p.pdf">
<front>
<title>ETSI TS 119 612 V2.1.1 Electronic Signatures and Infrastructures (ESI); Trusted Lists </title>
<author>
<organization>European Telecommunications Standards Institute (ETSI)</organization>
</author>
<date year="2015"/>
</front>
</reference>

<reference anchor="BCP195" target="https://www.rfc-editor.org/info/bcp195">
<front>
<title>BCP195</title>
Expand Down Expand Up @@ -2806,7 +2948,8 @@ The technology described in this specification was made available from contribut
[[ To be removed from the final specification ]]

-25


* add `accepted_issuers` to DCQL
* add language on client ID and nonce binding for ISO mdocs and W3C VCs
* clarify the behavior is not to sign when authorization_signed_response_alg is omitted

Expand Down