quartzjer / did-jwk

DID JWK Method Spec
Creative Commons Zero v1.0 Universal
6 stars 6 forks source link

JWK `kid` and `verificationMethod.id` #6

Closed OR13 closed 2 years ago

OR13 commented 2 years ago

https://www.w3.org/TR/did-core/#dfn-publickeyjwk

The publicKeyJwk property is OPTIONAL. If present, the value MUST be a map representing a JSON Web Key that conforms to [RFC7517]. The map MUST NOT contain "d", or any other members of the private information class as described in Registration Template.

It is RECOMMENDED that verification methods that use JWKs [RFC7517] to represent their public keys use the value of kid as their fragment identifier. It is RECOMMENDED that JWK kid values are set to the public key fingerprint [RFC7638]. See the first key in Example 13 for an example of a public key with a compound key identifier.

Many folks who use JWK will already have an identifier for the JWK, more examples (possibly pulled from Amazon, Google, Azure KMS JWKs) would help provide better interop.

quartzjer commented 2 years ago

Given that source JWK is part of the DID itself, I don't believe the RECOMMENDED use of the kid/fragment makes sense here as there's nothing to potentially disambiguate.

I also don't believe that this simplified usage will conflict with any existing systems that may use publicKeyJwk+kid (that I'm aware of at least).

OR13 commented 2 years ago

@quartzjer

Many JWT implementers who use other methods use the following convention to identify keys:

JWT.header.kid = did:example:123#key-0 <- note the fragment

When dereferencing with any of these other did methods, first, the document is resolved... then the key is obtained from the document... the key is not the document, it is a sub resource of the document.

There is a similar process in HTML which you are probably used to called anchor tags.

https://example.com/page/2#header-5... the server returns https://example.com/page/2, the web browser scrolls to #header-5 when text/html; charset=UTF-8 is returned.

You are correct that the resolver does not care about the fragment... but a dereferencer does.

the current method spec does not define unique identifiers for "sub resources" and therefore does not support interoperable dereferencing.... I can't use the result with our existing libraries without "hacking " it.

The problem is solvable though, because you already have to write code to transform the JWK into the DID Document, you have a few options:

0. don't support fragments

This is what you have today. This means your methods won't be a drop in replacement for methods that use fragments... which is pretty much every method I have ever seen.... but that doesn't mean you need interop with them.

1. compute verificationMethod.id from kid

If JWK contained kid, then didDocument.verificaitonMethod[0].id = did + '#' + kid

if kid is absent, just leave the DID URL with a dangling fragment... so its unique.

leave kid in JWK .

note that you cannot have the kid include the did... since the did is computed from the kid... this is similar to the issues with content addressing and IPFS.

1. hard code verificationMethod.id

Just add a #0 or whatever to the did, so that the verification method has a unique id.

Summary

Your use of a DID for verificationMethod.id might be rare / against convention / not interoperable... but it is legal:

Screen Shot 2022-04-11 at 8 54 00 AM

A DID is just a DID URL without a path, query or fragment....

However, since every other did method will likely include DID URLs that are NOT DIDs as id values for verification methods... it seems unwise to not at least conform to that convention in 1 of the suggested ways above.

its also worth nothing that your method does not support relative did URLs like ION, because you have no fragment.

so all relative ids would be the empty string... which is not a valid DID URL when considering the base identifier to be a DID.... specifically this legal version of your did document:

"id": "did:example:123",
"verificationMethod": [{
  "id": "",
  "controller": "did:example:123",
quartzjer commented 2 years ago

Thank you so much for the detailed explanation, I completely get it now.

I'll consider the options and add some language to the spec.

OR13 commented 2 years ago

Some things to keep in mind while you consider:

Using relative DID URLs, your did document can look a lot smaller, while having the same semantics.... but then your client libraries will be reconstructing absolute DID URLs from relative ones all over the place... I prefer absolute DID URLs after years of bugs working with relative ones, but both are legal.