openid / OpenID4VCI

68 stars 20 forks source link

The Value of Having JWKS in the Credential Issuer Matadata #385

Open peppelinux opened 2 months ago

peppelinux commented 2 months ago

As promised during the previous DCP WG call, here I create the issue to introduce the value of having the parameters jwks within the openid4vci metadata, as proposed also in the federation wallet draft, here: https://github.com/peppelinux/federation-wallet/issues/13#issue-2471668319

Each entity within wallet ecosystems may need to sign requests, responses, and more stringently, credentials, assertions, attestations, etc. Currently, OpenID4VCI does not include public keys for signature verification within the metadata, which ideally should be available in other types of metadata (e.g., SD-JWT VC). This omission creates confusion among implementers and in particular a gap for implementers that needs to issue other credential data formats, not sd-jwt vc.

jogu commented 2 months ago

Thanks Giuseppe! For clarify this issue is titled 'issuer metadata' so I will only address that aspect:

Credential issuers do not make signed responses, nor can they receive signed requests. They don't generate assertions or attestations, at least as far as I remember in the VCI specification.

The only thing I can see they have do that might require a jwks is sign credentials. SD-JWT VC already has a different solution proposed here https://github.com/oauth-wg/oauth-sd-jwt-vc/blob/main/draft-ietf-oauth-sd-jwt-vc.md?plain=1#L381 - namely /.well-known/jwt-vc-issuer - note that this location is specific to sd-jwt-vc's. An earlier version of the spec proposed a more generic .well-known/jwt-issuer which the OAuth WG was very unhappy with as it could result in keys for very different purposes ending up in the same jwks, and I believe the same concern may apply to a jwks entry in credential issuer metadata - i.e. keys should be stored in more specific locations that clearly separate what they are to be used for.

There is a competing proposal here for mdoc: https://github.com/openid/OpenID4VCI/issues/62 (which hasn't progressed as there are unanswered questions on the issue).

peppelinux commented 2 months ago

I would argue that it would be more consistent to include public cryptographic material within the openid4vci metadata for the following reasons:

  1. It would generally be advantageous to make openid4vci independent of other metadata resources for credential issuance purposes.
  2. It would ensure that the issuance of any credentials is consistent in their configuration within the openid4vci metadata.
  3. It would prevent the dispersion or fragmentation of configurations related to individual credentials across multiple .well-known resources.
  4. It would consolidate the role of VCI in a context where the distribution of a single metadata is possible and adequate. This way, if a trusted third party needs to distribute the VCI metadata, they can use a single signed artifact containing all necessary information. Currently, we already have a distinction between the authorization server and openid4vci, requiring two different metadata (mitigated with OpenID Federation Entity Configuration). Continuing to encourage this fragmentation would be concerning for implementers.
  5. It would make openid4vci self-consistent and generalist for any type of credential that might be introduced in the future, so that a new credential data format does not necessarily require a new .well-known for key distribution.

To avoid introducing breaking changes, I propose resolving this issue by introducing the jwks and jwks_uri parameters within the openid4vci metadata as OPTIONAL, containing all public keys controlled by openid4vci.

alenhorvat commented 2 months ago

I agree with @jogu that purpose of the keys must be well or at least better defined. Note that proposal #62 mentioned above falls in the same category.

JWK RFC (https://datatracker.ietf.org/doc/html/rfc7517#section-4.2) supports public key metadata, such as:

So in theory, jwks/jwks_uri could host public keys used for different purposes and also keys for the IACA since an x509 certificate can embedded with/referenced with a JWK.

However, for this to work, it should be well defined how to publish the keys and how to use the different properties correctly. IMO, key_use is currently too limited, and (if this is the path to take) to be extended similar to how x509 v3 allows to extend the key usage.

Note that signature formats define how to resolve the public keys needed to verify a signature (e.g., via x5c, x5u (not used), trust_chain of OIDFed, jwk/kid header params, etc). Each mechanism defines how the public key is bound to the issuer (x509 -> explicit, OIDC/OAuth via URL matching, OIDFed via signed metadata, ...) Hence, in all signed VCs that are using established signature frameworks, it is already defined how to resolve the signing keys.

Open question: when a wallet receives a VC from an issuer using OID4VCI, how to link the URL of the issuer and the public key used to sign the VC? For this purpose, there should be a link between the VC signing keys and the issuer URL.

Note that this does not solve the problem of distributing the root keys/certificates. Those need to be a) delivered out of band (e.g., TLS root directory) b) fetched via a trusted resource (e.g., EUTL, OIDC/OAuth, ...) where trusted resources (URLs) are delivered out of band

TakahikoKawasaki commented 2 months ago

The jwks and jwks_uri parameters in the credential issuer metadata (/.well-known/openid-credential-issuer) can coexist with the jwks and jwks_uri parameters in the JWT VC issuer metadata (/.well-known/jwt-vc-issuer).

The former could serve as the default or fallback location for retrieving keys, while the latter could be used for keys specific to (SD-)JWT-based VCs.

It could be said that the former serves as a key distribution mechanism from the issuer's perspective, while the latter serves as one from the verifiable credential's perspective, despite the latter's path, /.well-known/jwt-vc-issuer, containing issuer.

It is clear that the former approach is highly compatible with OpenID Federation, which is based on trust between federation entities. In OpenID Federation, a credential issuer is considered a type of federation entity.

Looking back, the reason the discussions around the latter approach became so contentious and confusing is that, despite being a key distribution mechanism specific to the verifiable credential format, the well-known path contained the term "issuer", as in /.well-known/jwt-issuer or /.well-known/jwt-vc-issuer. Had it used a different name, such as /.well-known/verifiable-credential/sd-jwt-vc, it likely wouldn’t have caused such confusion.

As a developer who has actually implemented OpenID Federation and understands its complexity, I support including jwks and jwks_uri in the credential issuer metadata. I believe the OID4VCI specification should allow ecosystems to use jwks and jwks_uri within the credential issuer metadata at their discretion.

jogu commented 2 months ago

I think I remain concerned that 'jwks' is a very generic name and it looks too much like it would be a sensible place to publish keys if the issuer in the future does need to sign something other than a credential, and we seem to have agreement that mixing keys for different uses in one location is a bad idea.

I think we always need more details on the proposal - for example:

  1. I'm not clear what is being proposed for sd-jwt vc - is that out of scope of jwks, do the keys need to be published in both places, or is it proposed to remove the sd-jwt-vc-issuer? (the latter not being something this WG can decide on, but it would still be useful to know the intent)
  2. what exactly does the JWK for mdl, mdoc, w3c vc, and sd-jwt vc look like? We should at least have examples to go in the spec, but I'm not clear what normative text we might need.
  3. I think for at least mdoc we need a description of how the verifier would get the credential issuer entity id from the credential (the wallet obviously knows where it got from the credential from, but once we're one step further down the chain at the verifier I'm struggling to see how it works)
peppelinux commented 2 months ago

@jogu my reaction to your concern is that, according to the agreed-upon best practice of specializing cryptographic keys for specific purposes, nothing prevents us from using the parameter jwks in each credential configuration instead of having it at the top level.

In OIDC Core we didn't have specialized keys for AT (if JWT), ID Token, UserInfo (with or without nested JWT) and so on, but the granularity obtained within the openid credential issuer metadata allows this advancement, therefore I tend to support this to remove any kind of blocking concern.

  1. I'd suggest to work on a self-consistent and general purpose standard: openid4vci. Other specification might work without any conflict with openid4vci. Using openid4vci and having all the credential configurations within the openid credential issuer it makes sense to have also the jwks for the signature validation.

  2. JWK supports at least X.509, there might be space also for DID, using namespaces within the kid parameter. At the end a cryptographic key is a sequence of bytes, while x.509, jwk, base16 or whatever are only different representations of that sequence, with, sometimes, additional metadata. For the scope of signature validation we only need the cryptographic key.

  3. It would be CN and or SAN URL for that

selfissued commented 2 months ago

Replying to @alenhorvat's comment:

purpose of the keys must be well or at least better defined

A standard clause when using JWK Sets (in this case, quoted from OpenID Connect Discovery) is:

When both signing and encryption keys are made available, a use (public key use) parameter value is REQUIRED for all keys in the referenced JWK Set to indicate each key's intended usage.

Defined usages are signing and encryption.

We should include JWK Sets and qualify them as above.

alenhorvat commented 2 months ago

Thank you @selfissued. I fully agree with this and this part is clear. I also support having jwks/jwks_uri in the credential metadata.

What I had in mind, but didn't express well, is what @TakahikoKawasaki explained - confusion that appears due to /.well-known/jwt-issuer or /.well-known/jwt-vc-issuer;

If someone reads the specs, they will end up with

I guess federation server (if running along with an AS) is using same keys to sign entity statements and ID tokens, but probably the 2 keys could be different? - Please correct me here.

However, we have 2 or 3 keys used for different "signing purpose" (not the best term)

So would it make sense to clarify that:

OIDC configuration -> jwks/jwks_uri -> id token/userinfo signing keys VCI configuration -> jwks/jwks_uri -> VC signing keys Entity configuration -> jwks/jwks_uri -> entity statement signing keys?

None of these should be affected by the VC format discovery, etc.

selfissued commented 2 months ago

Exactly @alenhorvat:

So would it make sense to clarify that: OIDC configuration -> jwks/jwks_uri -> id token/userinfo signing keys VCI configuration -> jwks/jwks_uri -> VC signing keys Entity configuration -> jwks/jwks_uri -> entity statement signing keys?

OpenID Federation employs this kind of key segregation. The JWK Sets for:

are all distinct. Likewise, the JWK Sets for the different Wallet entity types would all be distinct in the same way.

peppelinux commented 2 months ago

I guess federation server (if running along with an AS) is using same keys to sign entity statements and ID tokens, but probably the 2 keys could be different? - Please correct me here.

@alenhorvat OpenID Federation uses different keys for different purposes, such as those related to trust evaluation at the top level of the Entity Statement, which are distinct from the keys contained in each metadata type within the same Entity Statement.

immagine

jogu commented 2 months ago

As a clarifying question, if the VCI issuer and the authorization server use the same issuer url - i.e the authorization_server parameter in the Credential Issuer Metadata is omitted, how does that work in federation? Can you have two entity statements with the same url but different entity types?

peppelinux commented 2 months ago

@jogu

A single Entity Configuration or Subordinate Statements (technically both Entity Statements) can include the authz server along with the vci metadata (any other at the same time like openid_credential_verifier, openid_relying_party and so on).

an example is here:

https://italia.github.io/eudi-wallet-it-docs/versione-corrente/en/pid-eaa-entity-configuration.html

Can you have two entity statements with the same url but different entity types?

No. The same url correspond to the same entity. Different entities might use different webpaths, like https://entity.example.org/as and https://entity.example.org/vci representing two different entities within the same domain.

jogu commented 1 month ago

Talking to @peppelinux about above part that this is defining a mechanism that overlaps with https://github.com/oauth-wg/oauth-sd-jwt-vc/blob/main/draft-ietf-oauth-sd-jwt-vc.md?plain=1#L381 - namely /.well-known/jwt-vc-issuer (and similar things for other credential formats).

Adding jwks to VCI metadata potentially creates 3 places the keys could found from (from /.well-known/jwt-vc-issuer, from the VCI issuer metadata, or from the federation entity id's VCI issuer metadata).

If we instead add a federation entity type for sd-jwt-vc-issuer, we're only creating one more place for a total of 2 (from /.well-known/jwt-vc-issuer, or from the federation entity id's sd jwt vc issuer's metadata), which seems like a better proposal. This also keeps the flexibility that SD JWT VC can be used with federation without OID4VCI - or at least removes the need for the verifier to be aware of whether the wallet obtained the credential using OID4VCI or not, which seems useful.

awoie commented 4 weeks ago

OIDC configuration -> jwks/jwks_uri -> id token/userinfo signing keys VCI configuration -> jwks/jwks_uri -> VC signing keys Entity configuration -> jwks/jwks_uri -> entity statement signing keys? None of these should be affected by the VC format discovery, etc.

@alenhorvat IMO, the VC signing keys are affected by the VC format a little bit. For ISO mdocs, the key to verify the issuer signature of the mdoc is included in the mdoc itself (x5chain COSE header). For this reason, jwks/jwks_uri are not really useful for mdocs for discovering the credential verification key of the corresponding issuer. I know that for SD-JWT VC there is unfortunately more flexibility. Further, for mdocs they would have to be encoded as X.509 certificates and they even might be different for each credential configuration if individual root certificates are used per credential type.

Furthermore, I fully agree that the keys exposed by an AS have a different purpose than the keys exposed by an issuer.

I think it is useful to list cryptographic credential verification material in the issuer metadata. But I believe this cannot be limited to JWKS, it has to support at least X.509 as well.

IMO, it might even make sense to have credential configuration-specific cryptographic credential verification material for the reason provided above although there might be other architectural options to support this without having it per credential configuration.

I propose to add a new parameter cryptopraphic_credential_verification_material to the be added to the issuer metadata, or to a specific credential configuration in the issuer metadata:

 "cryptopraphic_credential_verification_material": [
    "certificates": [ "...", "..." ],
    "jwks": {
       "keys": [ ... ]
    }
 ]
alenhorvat commented 4 weeks ago

I agree.

What you're describing is usually called "signature profile" (e.g., JAdES is a JWS profile that has 4 signature types) and is bound to the signature format (and not the payload format, if the credentials are designed well). ISO, IMO, defines a CWS? profile.

Maybe it's a good opportunity to define better elements we're discussing about and set down the terminology the WG would agree upon.

jogu commented 4 weeks ago

@awoie

IMO, the VC signing keys are affected by the VC format a little bit. For ISO mdocs, the key to verify the issuer signature of the mdoc is included in the mdoc itself (x5chain COSE header). For this reason, jwks/jwks_uri are not really useful for mdocs for discovering the credential verification key of the corresponding issuer. I know that for SD-JWT VC there is unfortunately more flexibility. Further, for mdocs they would have to be encoded as X.509 certificates and they even might be different for each credential configuration if individual root certificates are used per credential type.

Just for clarify, x.509 certificates can be published in a JWK/JWKS: https://datatracker.ietf.org/doc/html/rfc7517#section-4.7

alenhorvat commented 4 weeks ago

@jogu, yes, but is anyone doing it this way? If you verify the x509 (which you should) you get the public key from the cert.

awoie commented 4 weeks ago

@awoie

IMO, the VC signing keys are affected by the VC format a little bit. For ISO mdocs, the key to verify the issuer signature of the mdoc is included in the mdoc itself (x5chain COSE header). For this reason, jwks/jwks_uri are not really useful for mdocs for discovering the credential verification key of the corresponding issuer. I know that for SD-JWT VC there is unfortunately more flexibility. Further, for mdocs they would have to be encoded as X.509 certificates and they even might be different for each credential configuration if individual root certificates are used per credential type.

Just for clarify, x.509 certificates can be published in a JWK/JWKS: https://datatracker.ietf.org/doc/html/rfc7517#section-4.7

@jogu are you in general supportive of including this in the issuer metadata, and just want to minimize possible encoding options, i.e., X.509 vs JWK? It is just a cleaner approach to define a dedicated issuer metadata for cryptographic credential verification material.

jogu commented 4 weeks ago

@jogu are you in general supportive of including this in the issuer metadata, and just want to minimize possible encoding options, i.e., X.509 vs JWK? It is just a cleaner approach to define a dedicated issuer metadata for cryptographic credential verification material.

I think there are still two fundamental questions:

  1. How much does this create duplicate and confusion, e.g. with the .well-known for keys specified in SD-JWT VC.
  2. Is VCI the right place to have it, because if a verifier needs to verify a credential it can't assume the credential was issued with OID4VCI?
awoie commented 4 weeks ago

@jogu are you in general supportive of including this in the issuer metadata, and just want to minimize possible encoding options, i.e., X.509 vs JWK? It is just a cleaner approach to define a dedicated issuer metadata for cryptographic credential verification material.

I think there are still two fundamental questions:

  1. How much does this create duplicate and confusion, e.g. with the .well-known for keys specified in SD-JWT VC.

.well-known for SD-JWT VC is SD-JWT VC-specific and even within SD-JWT VC it is a choice an issuer needs to make which also comes with certain tradeoffs compared to other options. It creates some redundancy for SD-JWT VC issuers that chose to use .well-known but it would allow other credential formats and profiles to have access to such a mechanism. IMO, the level of confusion is manageable since these SD-JWT VC issuers can choose to not support this cryptographic credential verification material in their issuer metadata if it becomes an optional metadata.

  1. Is VCI the right place to have it, because if a verifier needs to verify a credential it can't assume the credential was issued with OID4VCI?

IMO, it can be the right place. Credential profiles can define a dedicated entry point for OID4VCI well-known to fetch this information, so it becomes available to verifiers as well.

jogu commented 4 weeks ago

3. Is VCI the right place to have it, because if a verifier needs to verify a credential it can't assume the credential was issued with OID4VCI?

IMO, it can be the right place. Credential profiles can define a dedicated entry point for OID4VCI well-known to fetch this information, so it becomes available to verifiers as well.

But how would the verifier know if the credential came from VCI? And in the case of mdoc where would the verifier get the issuer url to lookup the data?

alenhorvat commented 4 weeks ago

In mDL, everything is covered with the x509 certs (either embedded or referenced); root (VICAL) must be maintained.

For JWK, 2 schemas are possible (but both have their downsides): a) OIDC-approach: iss -> well-known; b) jku header

VCI can define where the keys can be resolved, but how the information is resolved, what are the identifier schemes, etc is something that falls under a "trust framework", which requires a bit more than key resolution.

awoie commented 4 weeks ago
  1. Is VCI the right place to have it, because if a verifier needs to verify a credential it can't assume the credential was issued with OID4VCI?

IMO, it can be the right place. Credential profiles can define a dedicated entry point for OID4VCI well-known to fetch this information, so it becomes available to verifiers as well.

But how would the verifier know if the credential came from VCI? And in the case of mdoc where would the verifier get the issuer url to lookup the data?

Credential profiles could define a mechanism where to embed the credential issuer identifier to perform .well-known.

alenhorvat commented 4 weeks ago

Credential profiles could define a mechanism where to embed the credential issuer identifier to perform .well-known.

Signature profile. For key resolution there's the 'jku' claim.