OpenID4VP icon indicating copy to clipboard operation
OpenID4VP copied to clipboard

Client identifier prefix overload and binding to trust frameworks

Open Razumain opened this issue 8 months ago • 11 comments

The concept of client identifier prefix is creating a major implementation problem for realization with EUDI wallet.

The current approach solidifies the current state of play, without having considered the effects of a dynamic development in this area.

In EU there is a battle of how trust frameworks shall och can be provided to services across EU. At the moment the Trusted Lists approach has the lead, but that does not rule out the use of OpenID federation. We have outlined a detailed plan for how to make trusted data about services available through multiple trust frameworks. In reality, a Swedish service can access trusted metadata from our local OpenID federation, both for services in Sweden and for services outside of Sweden.

At the same time services from EU can access trusted information about Swedish services from the Truted Lists concept using certificates such as Relying party registration certificates.

To make this work, it MUST be the choice of the consuming peer entity by what resources they choose to obtain a version of the opponents metadata and rights. It simply cannot be determined and announced by the client identifier.

The client identifier should be just an identifier and should not encode decisions on how to trust this entity. That must be a choice made by the peer entity.

I was told that we should solve this by defining a new prefix. Unfortunately that does not work. We can't control what prefix services across EU will choose to use.

Razumain avatar Apr 25 '25 11:04 Razumain

Hi Stefan, can you explain at which point this worked in VP, and what the client passed in the request in the case it worked? (I am pretty certain the problem didn't start with the introduction of the client identifier prefix.)

We can't control what prefix services across EU will choose to use.

Why not? (Genuine question. I think there is a general assumption right now that verifiers that want to obtain data from a particular wallet would need to ensure they authenticate in a way that wallet accepts, e.g. if you want to be able to access both EU & USA credentials you would need to be able to authenticate to both EU wallets and USA wallets, and I'm not sure why that assumption isn't true here.)

jogu avatar Apr 25 '25 12:04 jogu

I think the problem actually started at the point we added the client_id_scheme parameter in early 2023.

To make this work, it MUST be the choice of the consuming peer entity by what resources they choose to obtain a version of the opponents metadata and rights

I'm not sure if this is generally true - it seems like it needs to be a combination - the verifier announcing the ways it knows it can be authenticated (for this particular request), and the wallet then picking one of those ways and indicating back to the verifier which one was used.

This is actually possible due to the changes in https://github.com/openid/OpenID4VP/pull/308 but this currently only works for the DC API.

Would a similar solution for the custom url scheme based flows solve your issue?

jogu avatar May 01 '25 18:05 jogu

We just finished a workshop in OpenID fed in Stockholm with implementers from all over the world. We discussed this in detail and there was a general consensus among those developing solutions that trust frameworks need to be able to function even when they are decoupled from the protocols using the metadata. This for 2 reasons mainly:

  1. In order to successfully build federations from 0 participation to 100% participation, we need to allow the entity implementations to be unaltered and just add availability of their metadata. They should not even need to be aware that their metadata can be validated through multiple sources and protocols. In order to make it attractive to obtain metadata through the trust framework, we need to have good coverage of available metadata. Then we can get more and more to use it as a trusted source.
  2. In a transition phase, like will be the case of EUDI wallets, where we likely will start with Trusted List, but want to gradually transition to OpenID federation, It will be absolutely necessary to be available through several trust frameworks at the same time. If not, then transition will be impossible.

Binding the identifier to a single trust framework is devastating to these ambitions. At least as far as me and many others can see.

The main process to select a suitable trust framework in a future secure fashion (in my world) is the following:

  1. The client pass a request to the wallet entity, specifying its identifier and optionally its metadata.
  2. The wallet entity decides what trust framework to use to obtain and/or validate metadata and verifies that this is the trusted metadata for the requesting client identity. What framework to use is decided by the verifying party based on its capability and trust preferences.

The identifier should just be an identifier of the client, nothing more and nothing less.

I'm my self guilty of overloading the semantics of identifier. I wrote ETSI EN 319 412-1 where we prefixed the content of "serialNumber". Seemed like a great idea at the time. And we were very wrong. The right thing to do had been to specify context in a separate attribute. I believe the same is true here.

Razumain avatar May 01 '25 22:05 Razumain

Hi Stefan, can you explain at which point this worked in VP, and what the client passed in the request in the case it worked? (I am pretty certain the problem didn't start with the introduction of the client identifier prefix.)

We can't control what prefix services across EU will choose to use.

Why not? (Genuine question. I think there is a general assumption right now that verifiers that want to obtain data from a particular wallet would need to ensure they authenticate in a way that wallet accepts, e.g. if you want to be able to access both EU & USA credentials you would need to be able to authenticate to both EU wallets and USA wallets, and I'm not sure why that assumption isn't true here.)

Hi,

I wish I could answer the first question, but I'm not sure.

However why custom prefix does not work is easier. If I develop a Relying Party (the client) and present a custom prefix, I would not expect wallets across EU to accept it.

If I develop a wallet and receive a client identifier with a prefix, I would have to honor that prefix, or violate the standard. I think this is quite clearly stated in 5.9. Consequently, if a RP use the openid_federation prefix, then OpenID federation processing rules MUST be used. Since many wallets will not support that option, it means that no RP wanting to interact with all wallets can use this prefix. That means we will be stuck with whatever is selected forever.

Please let me know if I misread the standard.

Razumain avatar May 01 '25 22:05 Razumain

I think the problem actually started at the point we added the client_id_scheme parameter in early 2023.

To make this work, it MUST be the choice of the consuming peer entity by what resources they choose to obtain a version of the opponents metadata and rights

I'm not sure if this is generally true - it seems like it needs to be a combination - the verifier announcing the ways it knows it can be authenticated (for this particular request), and the wallet then picking one of those ways and indicating back to the verifier which one was used.

This is actually possible due to the changes in #308 but this currently only works for the DC API.

Would a similar solution for the custom url scheme based flows solve your issue?

I'm trying to follow, but I'm not entirely sure I get this right.

The verifier (in this case the wallet) is not known to the client (RP) at the time the request is sent with the client identifier prefix (Looking at the flows in section 3). I read this as the client need to lock to its prefix before it knows any of the wallets capabilities, depriving the wallet from choosing what it deems to be the suitable trust framework for this interaction.

If such negotiation is available, then I'm wrong about this.

The pull you cite is interesting, and seems to reinforce that the wallet should be able to choose what trust framework to choose, but I fail to see how it solves this issue. Can you offer an explanation how?

Razumain avatar May 01 '25 22:05 Razumain

The verifier (in this case the wallet) is not known to the client (RP) at the time the request is sent with the client identifier prefix (Looking at the flows in section 3). I read this as the client need to lock to its prefix before it knows any of the wallets capabilities, depriving the wallet from choosing what it deems to be the suitable trust framework for this interaction.

If such negotiation is available, then I'm wrong about this.

The pull you cite is interesting, and seems to reinforce that the wallet should be able to choose what trust framework to choose, but I fail to see how it solves this issue. Can you offer an explanation how?

The current mental model is that it is unlikely for any kind of negotiation to happen beforehand, but the request itself should carry everything necessary and allow optionality where necessary. #308 allows for a Verifier to support different trust ecosystems (identified by different prefixes) and send a request bundling all of them. The Wallet then evaluates its options and chooses the one it supports.

So if you have a Verifier that supports both, OpenID Federation, and X.509 (e.g., facilitated via Trusted Lists), they would construct the request with both options as described in 308 (currently only works with DC API but that could be extended to work with "vanilla" flows), the wallet chooses (e.g., selects OpenID Federation), validates the request and constructs the response accordingly.

c2bo avatar May 02 '25 07:05 c2bo

If I develop a wallet and receive a client identifier with a prefix, I would have to honor that prefix, or violate the standard. I think this is quite clearly stated in 5.9. Consequently, if a RP use the openid_federation prefix, then OpenID federation processing rules MUST be used. Since many wallets will not support that option, it means that no RP wanting to interact with all wallets can use this prefix. That means we will be stuck with whatever is selected forever.

Right. But how it that different to the 'before client id prefixes' world where in OID4VP the client would pass:

client_id_scheme=x509_sans_dns&client_id=verifier.example.com

? (as it was at the time expected that all verifiers in the EU would be required to do)

In that case, the specification required the client id to be interpreted by the wallet as an x509 identifier, and interpreting it as anything else would be a violation of the specification (and there was an explicit clause in the specification that metadata must only be obtained within the signed request, so obtaining it from openid federation instead (for example) would be a violation of the spec.

Removing the prefixes and switching back to the previous way doesn't seem to resolve your problem (and would reintroduce the problems as described in https://github.com/openid/OpenID4VP/issues/124 where plenty of alternative solutions were also considered.)

I think we should concentrate on how your problem can be solved.

jogu avatar May 02 '25 13:05 jogu

The current mental model is that it is unlikely for any kind of negotiation to happen beforehand, but the request itself should carry everything necessary and allow optionality where necessary. #308 allows for a Verifier to support different trust ecosystems (identified by different prefixes) and send a request bundling all of them.

Thank you. I finally got to the bottom of how this is thought to work. However this solution does not solve the issue. Here is why.

This solution makes perfect sense from the perspective of the RP. That is. The RP concerned about the wallet having choices can control which choices it can offer the wallet.

I'm looking at this from the wallets perspective. The wallet has no control and no freedom. If the RP does not send a suitable client_id with a suitable prefix, the wallet lost its freedom to select the trust framework it actually trust.

Removing the prefixes and switching back to the previous way doesn't seem to resolve your problem (and would reintroduce the problems as described in https://github.com/openid/OpenID4VP/issues/124 where plenty of alternative solutions were also considered.)

No. Issue 124 use backwards logic to highlight a problem that does not exist.

Yes there will always be a risk that clients choose a colliding ID. But:

  1. It is NOT the client that should decide what source the wallet should use to determine what this ID means.
  2. If the trust framework used by the wallet returns the metadata and keys for another RP (due to ID collisions) That RP is unable to impersonate the requesting RP, and the Requesting RP is unable to impersonate the located RP due to key mismatch.

The problem of ID collision is solved by imposing requirements on IDs in the larger ecosystem (Rules for EUDI wallet RPs) set by the EU commission. Only if the wallet chosen trust framework returns the keys and metadata for the actual requester, will the request be accepted.

Razumain avatar May 07 '25 14:05 Razumain

Just a stupid question from one that still stuggles to understand all bits of this document.

Reading #248 I notice the following solution:

"header": {
               "client_id": "https://rp.federation.eu",
               "client_id_scheme": "entity_id"
             },

This makes a lot more sense to me (separate parameters) rather than a prefixed ID. Why the different approaches? Why not having a client_id_scheme also as a request parameter instead of prefix? Why not making it multivalued (array) and define it as a hint (not imposing mandatory requirements on what trust framework the wallet must use)?

Razumain avatar May 07 '25 14:05 Razumain

Just a stupid question from one that still stuggles to understand all bits of this document.

Reading #248 I notice the following solution:

"header": {
               "client_id": "https://rp.federation.eu",
               "client_id_scheme": "entity_id"
             },

This makes a lot more sense to me (separate parameters) rather than a prefixed ID. Why the different approaches? Why not having a client_id_scheme also as a request parameter instead of prefix? Why not making it multivalued (array) and define it as a hint (not imposing mandatory requirements on what trust framework the wallet must use)?

There is more information on why we abandoned client_id_scheme here: https://github.com/openid/OpenID4VP/issues/124

awoie avatar May 20 '25 15:05 awoie

Given the voting announcement has now gone out for 1.0, I don't think there's any chance this will change now, especially given we don't have a concrete proposal on the table - will close in a week or so unless anyone objects.

jogu avatar Jun 11 '25 20:06 jogu