Git Product home page Git Product logo

did-resolver's Introduction

npm npm codecov

Typescript DID Resolver

This library is intended as a simple common interface for javascript applications to resolve DID documents from Decentralized Identifiers (DIDs).

This is intended to support the proposed Decentralized Identifiers spec from the W3C Credentials Community Group.

The library does not implement any specific DID method, but allows DID method implementors to release npm packages that applications can add.

Configure Resolver object

You are now required to preconfigure a resolver during instantiation. The Resolver constructor expects a registry of methods mapped to a resolver function. For example:

{
  ethr: resolve,
  web: resolve
}

Each method resolver should expose a function called getResolver which will return an object containing one of these key/value pairs. Then you can flatten them into one object to pass into the Resolver constructor.

import { Resolver } from 'did-resolver'
import ethr from 'ethr-did-resolver'
import web from 'web-did-resolver'
import sov from 'sov-did-resolver'

//returns an object of { methodName: resolveFunction}
ethrResolver = ethr.getResolver()
webResolver = web.getResolver()

//If you are using multiple methods you need to flatten them into one object
const resolver = new Resolver({
  ...ethrResolver,
  ...webResolver,
})

//If you are using one method you can simply pass the result of getResolver( into the constructor
const resolver = new Resolver(ethrResolver)

Using legacy DID Method resolvers

DID Method resolvers created before version 3.0.0 of this library can be used as legacy resolvers.

import { Resolver } from 'did-resolver'
import web from 'web-did-resolver'
import sov from 'sov-did-resolver'

//returns an object of { methodName: resolveFunction}
webResolver = web.getResolver()
sovResolver = sov.getResolver()

//If you are using multiple methods you need to flatten them into one object
const resolver = new Resolver({}, {
  legacyResolvers: {
    ...webResolver,
    ...sovResolver,
  }
})

//If you are using one method you can simply pass the result of getResolver( into the constructor
const resolver = new Resolver(ethrResolver)

Resolving a DID document

The resolver presents a simple resolve() function that returns a ES6 Promise returning the DID document.

resolver.resolve('did:ethr:0xF3beAC30C498D9E26865F34fCAa57dBB935b0D74/some/path#fragment=123').then(doc => console.log)

// You can also use ES7 async/await syntax
const doc = await resolver.resolve('did:ethr:0xF3beAC30C498D9E26865F34fCAa57dBB935b0D74/some/path#fragment=123')

Caching

Resolving DID Documents can be expensive. It is in most cases best to cache DID documents. Caching has to be specifically enabled using the cache parameter

The built-in cache uses a Map, but does not have an automatic TTL, so entries don't expire. This is fine in most web, mobile and serverless contexts. If you run a long-running process you may want to use an existing configurable caching system.

The built-in Cache can be enabled by passing in a true value to the constructor:

const resolver = new DIDResolver({
  ethr,
  web
}, {
  cache: true
})

Here is an example using js-cache which has not been tested.

var cache = require('js-cache')
const customCache : DIDCache = (parsed, resolve) => {
  // DID spec requires to not cache if no-cache param is set
  if (parsed.params && parsed.params['no-cache'] === 'true') return await resolve()
  const cached = cache.get(parsed.didUrl)
  if (cached !== undefined) return cached
  const doc = await resolve()
  cache.set(parsed, doc, 60000)
  return doc
}

const resolver = new DIDResolver({
  ethr,
  web
}, {
  cache: customCache
})

Implementing a DID method

Each DID method will have its own methods for looking up an identifier on its respective blockchain or other decentralized storage mechanism.

To avoid misconfiguration, method implementers should export a getResolver() function which returns an object mapping the method name to a resolve(did: string, parsed: ParsedDID, didResolver: DIDResolver, options: DIDResolutionOptions) function. e.g. { ethr: resolve }.

The resolve function should accept a did string, and an object of type ParsedDID

export function getResolver() {
  async function resolve(
    did: string,
    parsed: ParsedDID,
    didResolver: Resolver,
    options: DIDResolutionOptions
  ): Promise<DIDDocument> {
    console.log(parsed)
    // {method: 'mymethod', id: 'abcdefg', did: 'did:mymethod:abcdefg/some/path#fragment=123', path: '/some/path', fragment: 'fragment=123'}
    const didDoc = ...// lookup doc
    // If you need to lookup another did as part of resolving this did document, the primary DIDResolver object is passed in as well
    const parentDID = await didResolver.resolve(...)
    // Return the DIDResolutionResult object
    return {
      didResolutionMetadata: { contentType: 'application/did+ld+json' },
      didDocument: didDoc
      didDocumentMetadata: { ... }
    }
  }

  return { myMethod: resolve }
}

The MyMethod getResolver() result could then be passed into the DIDResolver constructor. Note that it should be flattened if used with other methods as well.

import { DIDResolver } from 'did-resolver'
import MyMethod from 'mymethod-did-resolver'

const myResolver = MyMethod.getResolver()
const resolver = new DIDResolver(myResolver)

did-resolver's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

did-resolver's Issues

[proposal] Add cosmosAddress Property in verificationMethod like a ethereumAddress

[proposal] jwt validation using cosmosAddress #204

Since Cosmos uses prefixes for addresses, it is an advantageous address system to use as did. So, after decomposing the address into prefix and remainder, we want to use it as a DID. And, like Ethereum, Cosmos would like to add the address of Cosmos to the property so that it can be verified by extracting the public key from the signature.

dsrv1zp78zmtj4a7qvs4p2s08ngjn9rcwpaf5k9d0la (cosmos address)
did:dsrv:1zp78zmtj4a7qvs4p2s08ngjn9rcwpaf5k9d0la (did)

interface VerificationMethod {
  id: string
  type: string
  controller: string
  publicKeyBase58?: string
  publicKeyBase64?: string
  publicKeyJwk?: JsonWebKey
  publicKeyHex?: string
  publicKeyMultibase?: string
  blockchainAccountId?: string
  ethereumAddress?: string
  cosmosAddress?: string
}

Action Required: Fix Renovate Configuration

There is an error with this repository's Renovate configuration that needs to be fixed. As a precaution, Renovate will stop PRs until it is resolved.

Error type: Cannot find preset's package (github>whitesource/merge-confidence:beta)

Add support for didResolutionMetadata and didDocumentMetadata

According to did-core a resolver function should have the following abstract form:

resolve(did, resolutionOptions) →
   « didResolutionMetadata, didDocument, didDocumentMetadata »

Currently the function signature for this library looks like this:

resolve(did: string): Promise<DIDDocument>

We should introduce a breaking change that adds support for returning didResolutionMetadata and didDocumentMetadata.
It should be possible to implement this in a way in which all resolvers won't break with the new version of this package, but won't provide additional metadata until they implement the new interface.

The new function signature would look something like this:

interface ResolutionResult {
  didDocument: DIDDocument
  didResolutionMetadata: DIDResolutionMetadata
  didDocumentMetadata: DIDDocumentMetadata
}

resolve(did: string, resolutionOptions: ResolutionOptions): Promise<ResolutionResult>

Why owner instead of controller?

Is there a specific reason why you call 'controller' property 'owner' in pubkey?
To follow w3c DID spec, I think we should change it to 'controller'

Authentication interface: publicKey in DidDoc an Array but string in type

We are using the hosted v1 uniresolver, and ethr did-method, a did we are resolving for example here.

We were aiming to use the types direct from this project but noticed that Authentication.publicKey is defined here as just a single string but the uniresolver is returning an array of publicKey strings:

  "authentication" : [ {
    "type" : "Secp256k1SignatureAuthentication2018",
    "publicKey" : [ "did:ethr:0xCC59d32d61A1E469818e8E489D3559dda4Fac32d#owner" ]
  } ],

Can we update Authentication.publicKey to string[] ?

[BUG] Incorrect did matcher regex

Current Behavior

Did matcher regex used in the parse function (https://github.com/decentralized-identity/did-resolver/blob/master/src/resolver.ts#L166) uses an incorrect regex according to the specification (https://www.w3.org/TR/did-core/#did-syntax). Specifically:

  • method should not include capitals which it currently does
  • method_id should allow for sequential colons (ex. did:method::id)
  • % can only be followed by two hex digits (ex. did:method:%1p is invalid while did:method:%1f is valid)

Expected Behavior

The matcher regex should conform to the did specification.

Failure Information

parse('did:CAPITALS:id')

{
  did: 'did:CAPITALS:id',
  method: 'CAPITALS',
  id: 'id',
  didUrl: 'did:CAPITALS:id'
}

Steps to Reproduce

  1. Invoke parse with a did that follows the specification and parse will return null OR with an invalid did and parse will return a ParsedDid

Environment Details

  • node/browser version: v16.11.1
  • OS Version: Big Sur v11.6
  • Device details:

Failure Logs/Screenshots

None

Alternatives you considered

None

The automated release is failing 🚨

🚨 The automated release from the master branch failed. 🚨

I recommend you give this issue a high priority, so other packages depending on you could benefit from your bug fixes and new features.

You can find below the list of errors reported by semantic-release. Each one of them has to be resolved in order to automatically publish your package. I’m sure you can resolve this 💪.

Errors are usually caused by a misconfiguration or an authentication problem. With each error reported below you will find explanation and guidance to help you to resolve it.

Once all the errors are resolved, semantic-release will release your package the next time you push a commit to the master branch. You can also manually restart the failed CI job that runs semantic-release.

If you are not sure how to resolve this, here is some links that can help you:

If those don’t help, or if this issue is reporting something you think isn’t right, you can always ask the humans behind semantic-release.


Invalid npm token.

The npm token configured in the NPM_TOKEN environment variable must be a valid token allowing to publish to the registry https://registry.npmjs.org/.

If you are using Two-Factor Authentication, make configure the auth-only level is supported. semantic-release cannot publish with the default auth-and-writes level.

Please make sure to set the NPM_TOKEN environment variable in your CI with the exact value of the npm token.


Good luck with your project ✨

Your semantic-release bot 📦🚀

Add dereference function

DID Core distinguishes between resolving a DID and dereferencing a DID URL. Resolving a DID is already covered but it would be good have support for dereferencing a DID URL as well as defined in the DID Core spec here.

Interface looks as follows:

dereference(didUrl, dereferenceOptions) →
   « dereferencingMetadata, contentStream, contentMetadata »

[proposal] Allow query of a key fragment as a document

Is your feature request related to a problem? Please describe.
I'm currently using the web-did-resolver in a custom document loader and it works very well, but i still have to query key fragments separately like so:

  const [did, keyFragment] = url.split('#')

  // fetch document
  const didDocument: any = (await getResolver().resolve(url)).didDocument

  // if a keyFragment of the DID document is queried
  if (keyFragment && didDocument) {
      
      // TODO allow query of other fields than verification method as well
      const keyFragmentDoc: any | undefined = didDocument.verificationMethod.filter(function(method: any) {
                                                                      return method.id === url || method.id === verificationMethod;
                                                                  })[0];

      if (!keyFragmentDoc)
          throw new jsonldSignatures.VerificationError(
                      new Error(`${verificationMethod} is an unknown key fragment for ${did}`)
                      );

      return {
          contextUrl: null,
          documentUrl: url,
          // deliver keyFragment with the DID doc context
          document: Object.assign(verificationMethodDoc, {'@context': didDocument['@context']}),
      };

  }

  return {
      contextUrl: null,
      documentUrl: url,
      document: didDocument,
  };

Describe the solution you'd like
If the key fragment is specified the resolver should not return the DID document, but the key fragment document. (See code above)

Describe alternatives you've considered
See code above

Moved here from decentralized-identity/web-did-resolver#121

JsonWebKey Interface only for a public key? Missing private key parameter.

Question
Why doesn't the JsonWebKey interface define the "d" parameter for a private key?

See: JSON Web Key Parameters in :
https://www.iana.org/assignments/jose/jose.xhtml

See the interface definition in:
https://github.com/decentralized-identity/did-resolver/blob/master/src/resolver.ts#L74-L86

Context:
Current Fix
For context, I was hacking around the break up the test file https://github.com/bshambaugh/did-jwt/blob/master/src/__tests__/JWT/CommonSignerTest/CommonSignerTest.ts#L20-L22

so I could import creation of the DID document as a fuction; https://github.com/bshambaugh/did-jwt/blob/master/src/__tests__/JWT/JWT.ES256Signer.test.ts#L50-L54 and https://github.com/bshambaugh/did-jwt/blob/master/src/__tests__/JWT/JWT.ES256KSigner.test.ts#L43-L47
(other changes [unrelated to this issue] were so I could avoid use of the any type)

Originally it was: https://github.com/decentralized-identity/did-jwt/blob/master/src/__tests__/JWT.test.ts#L36-L91

further parameter for resolving

Hello everone,

I'd would like to see that i could add further parameter to the resolve function.
e.g. didResolver.resolve(did, {some: "extra", stuff }

What do you think?
I could create a pull request for that.

kind regards,
Frank

[BUG] ServiceEndpoint interface does not match DID Spec

Current Behavior

ServiceEndpoint interface (which is intended to define the service DIDDocument property) is defined in this package here: https://github.com/decentralized-identity/did-resolver/blob/master/src/resolver.ts#L67

The Service properties are defined in the spec here: https://www.w3.org/TR/did-core/#service-properties

The ServiceEndpoint interface contains a field serviceEndpoint with type string. However, the spec states that the serviceEndpoint property can be a string OR a map OR a set of strings/maps.

Expected Behavior

The ServiceEndpoint interface should be refactored (possibly renamed to Service to avoid confusion) and the serviceEndpoint field type should be modified to string | ServiceEndpoint | ServiceEndpont[], where the new ServiceEndpoint interface defines the possible fields of that object (e.g. uri (string), routingKeys(string[]), accept(string[]))

Alternatives you considered

The possible fields of the ServiceEndpoint object are not well defined, as far as I can tell. I see it defined in the DIDComm spec (https://identity.foundation/didcomm-messaging/spec/#reference) but it's not clear if this specification applies to all ServiceEndpoint objects. Perhaps instead of defining this interface the serviceEndpoint field should simply be typed string | object | object[]?

Dependency Dashboard

This issue lists Renovate updates and detected dependencies. Read the Dependency Dashboard docs to learn more.

Open

These updates have all been created already. Click a checkbox below to force a retry/rebase of any.

Detected dependencies

github-actions
.github/workflows/release.yml
  • actions/checkout v4
  • actions/setup-node v4
  • ubuntu 22.04
.github/workflows/test.yml
  • actions/checkout v4
  • actions/setup-node v4
  • codecov/codecov-action v3
  • ubuntu 22.04
npm
package.json
  • @babel/core 7.24.3
  • @babel/preset-env 7.24.3
  • @babel/preset-typescript 7.24.1
  • @semantic-release/changelog 6.0.3
  • @semantic-release/git 10.0.1
  • @types/jest 29.5.12
  • @typescript-eslint/eslint-plugin 5.62.0
  • @typescript-eslint/parser 5.62.0
  • babel-jest 29.7.0
  • eslint 8.57.0
  • eslint-config-prettier 8.10.0
  • eslint-plugin-jest 27.9.0
  • eslint-plugin-prettier 4.2.1
  • jest 29.7.0
  • microbundle 0.15.1
  • prettier 2.8.8
  • semantic-release 19.0.5
  • typescript 4.9.5

  • Check this box to trigger a request for Renovate to run again on this repository

[proposal] Add list of known implemented methods with reference

Is your feature request related to a problem? Please describe.
It's hard to find out if a method is already implemented and where to find it. I'm currently searching for a did:key 'resolver' which would be easily implemented by myself, but why if it already exists.

Describe the solution you'd like
Maintain (Self/PR) a list of proposed method implementations in this repository with a reference.

Describe alternatives you've considered

Additional context

How to verify DID Document returned from Resolver?

Not sure if I might be missing something here, but is there a way to verify the signature of a DID Document returned by the resolver?

The type in the library is "DIDDocument", which only has (excluding deprecated fields):

id
publicKey
authentication
service
keyAgreement

Does the concept of the resolver rely on trusting the result from the resolver?

I'm currently implementing an did-resolver and being able to verify the signature is something I want to support, so I'm considering adding some parameters to the getResolver method allowing retrieval of the original JWT.

Can also be handled in the resolve method and throw error, since my DID Method API returns the JWT.

Looking at some of the examples here, I see that maybe Document Metadata could be used for the signature?

https://dev.uniresolver.io/

Is it OK to extend the result returned, I see some DID Methods are using the deprecated "proof" section, yet I'd rather conform to the latest specification.

[bug] private member `registry` leads to typescript compiler errors

In a project with complex dependency tree it can happen that there are 2 or more versions of did-resolver in use.
The class Resolver has a private registry member, which leads to broken builds when it is imported from different versions of the library.

Argument of type '{ [x: string]: DIDResolver | DIDResolver; }' is not assignable to parameter of type 'ResolverRegistry'.
'string' index signatures are incompatible.
  Type 'DIDResolver | DIDResolver' is not assignable to type 'DIDResolver'.
    Type 'import("..../node_modules/did-resolver/lib/resolver").DIDResolver' is not assignable to type 'import("..../node_modules/did-resolver/lib/resolver").DIDResolver'.
      Types of parameters 'resolver' and 'resolver' are incompatible.
        Type 'import("..../node_modules/did-resolver/lib/resolver").Resolver' is not assignable to type 'import("..../node_modules/did-resolver/lib/resolver").Resolver'.
          Types have separate declarations of a private property 'registry'.

I believe this could be fixed by avoiding the use of class Resolver as a type in other definitions.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.