Skip to content

a library to create DID configuration resources and domain linkage credentials

License

Notifications You must be signed in to change notification settings

Sphereon-Opensource/wellknown-did-client

Repository files navigation


Sphereon
Well Known DID client

CI codecov NPM Version

Wellknown-dids client

The wellknown-dids-client is a library to create DID configuration resources and domain linkage credentials and to be able to verify these conforming to the DIF spec for well-known DID Configurations It is written in Typescript and can be compiled to any target JavaScript version.

Supported actions

  • Creating a DID configuration resource.
  • Creating a domain linkage credential.
  • Verifying domain linkage based on a DID document.
  • Verifying an endpoint descriptor.
  • Verifying a DID configuration resource (option for remote possible).
  • Verifying a domain linkage credential (JWT or JSONLD).

Requirements

Well-Known DID issuer

For the well-known DID issuer, an issue callback is required that does the actual issuing of the credential. This can be supplied by using a config to the issuer or as a parameter to the functions.

Well-Known DID verifier

For the well-known DIr verifier, a verification callback is required that does the signature verification of the credential. This can be supplied by using a config to the issuer or as a parameter to the functions.

Examples

NOTE: VC-JS is being used as an example. Any issuer should be able to be used.

DID configuration resource creation
import { WellKnownDidIssuer } from '@sphereon/wellknown-dids-client';
import vc from '@digitalbazaar/vc';
import { Ed25519VerificationKey2020 } from '@digitalcredentials/ed25519-verification-key-2020';
import { Ed25519Signature2020 } from '@digitalcredentials/ed25519-signature-2020';

const issueCallback = async (args: IIssueCallbackArgs): Promise<any> => {
 const keyPair = await Ed25519VerificationKey2020.generate();
 const suite = new Ed25519Signature2020({key: keyPair});
 suite.verificationMethod = args.credential.credentialSubject.id
 const { defaultDocumentLoader } = vc;

 return await vc.issue({ credential: args.credential, suite, documentLoader: defaultDocumentLoader });
};

const issuer: WellKnownDidIssuer = new WellKnownDidIssuer({
 issueCallback: (args: IIssueCallbackArgs) => issueCallback(args),
});

const args = {
 issuances: [
   {
     did: 'did:key:z6MkoTHsgNNrby8JzCNQ1iRLyW5QQ6R8Xuu6AA8igGrMVPUM',
     origin: 'https://example.com',
     issuanceDate: new Date().toDateString(),
     expirationDate: new Date(new Date().getFullYear() + 10, new Date().getMonth(), new Date().getDay()).toISOString(),
     options: { proofFormat: ProofFormatTypesEnum.JSON_LD },
   },
 ],
};

issuer.issueDidConfigurationResource(args) 
 .then(result => 'success')
 .catch(error => 'failed');
Domain linkage credential creation
import { WellKnownDidIssuer } from '@sphereon/wellknown-dids-client';
import vc from '@digitalbazaar/vc';
import { Ed25519VerificationKey2020 } from '@digitalcredentials/ed25519-verification-key-2020';
import { Ed25519Signature2020 } from '@digitalcredentials/ed25519-signature-2020';

const issueCallback = async (args: IIssueCallbackArgs): Promise<any> => {
 const keyPair = await Ed25519VerificationKey2020.generate();
 const suite = new Ed25519Signature2020({key: keyPair});
 suite.verificationMethod = args.credential.credentialSubject.id
 const { defaultDocumentLoader } = vc;

 return await vc.issue({ credential: args.credential, suite, documentLoader: defaultDocumentLoader });
};

const issuer: WellKnownDidIssuer = new WellKnownDidIssuer();

const args = {
 issuances: [
   {
     did: 'did:key:z6MkoTHsgNNrby8JzCNQ1iRLyW5QQ6R8Xuu6AA8igGrMVPUM',
     origin: 'https://example.com',
     issuanceDate: new Date().toDateString(),
     expirationDate: new Date(new Date().getFullYear() + 10, new Date().getMonth(), new Date().getDay()).toISOString(),
     options: { proofFormat: ProofFormatTypesEnum.JSON_WEB_TOKEN },
     issueCallback: (args: IIssueCallbackArgs) => issueCallback(args)
   },
 ],
};

issuer.issueDomainLinkageCredential(args)
 .then(result => 'success')
 .catch(error => 'failed');
Domain linkage verification
import { WellKnownDidIssuer } from '@sphereon/wellknown-dids-client';
import vc from '@digitalbazaar/vc';
import { Ed25519VerificationKey2020 } from '@digitalcredentials/ed25519-verification-key-2020';
import { Ed25519Signature2020 } from '@digitalcredentials/ed25519-signature-2020';

const verifySignatureCallback = async (args: IVerifyCallbackArgs): Promise<IVerifyCredentialResult> => {
 const keyPair = await getKeyPair();
 const suite = new Ed25519Signature2020({key: keyPair});
 const { defaultDocumentLoader } = vc;
 
 return await vc.verifyCredential({ credential: args.credential, suite, documentLoader: defaultDocumentLoader });
}

const verifier: WellKnownDidVerifier = new WellKnownDidVerifier({
 verifySignatureCallback: (args: IVerifyCallbackArgs) => verifySignatureCallback(args),
});

const didDoccument = {
 ...
};

verifier.verifyDomainLinkage({ didDoccument, onlyVerifyServiceDid: false })
 .then(result => 'success')
 .catch(error => 'failed');
DID configuration resource verification
import { WellKnownDidIssuer } from '@sphereon/wellknown-dids-client';
import vc from '@digitalbazaar/vc';
import { Ed25519VerificationKey2020 } from '@digitalcredentials/ed25519-verification-key-2020';
import { Ed25519Signature2020 } from '@digitalcredentials/ed25519-signature-2020';

const verifySignatureCallback = async (args: IVerifyCallbackArgs): Promise<IVerifyCredentialResult> => {
 const keyPair = await getKeyPair();
 const suite = new Ed25519Signature2020({key: keyPair});
 const { defaultDocumentLoader } = vc;

 return await vc.verifyCredential({ credential: args.credential, suite, documentLoader: defaultDocumentLoader });
}

const verifier: WellKnownDidVerifier = new WellKnownDidVerifier();

const didConfigurationResource = {
 '@context': 'https://identity.foundation/.well-known/did-configuration/v1',
 linked_dids: [
   {
     '@context': [
       'https://www.w3.org/2018/credentials/v1',
       'https://identity.foundation/.well-known/did-configuration/v1'
     ],
     'issuer': 'did:key:z6MkoTHsgNNrby8JzCNQ1iRLyW5QQ6R8Xuu6AA8igGrMVPUM',
     'issuanceDate': '2020-12-04T14:08:28-06:00',
     'expirationDate': '2025-12-04T14:08:28-06:00',
     'type': [
       'VerifiableCredential',
       'DomainLinkageCredential'
     ],
     'credentialSubject': {
       'id': 'did:key:z6MkoTHsgNNrby8JzCNQ1iRLyW5QQ6R8Xuu6AA8igGrMVPUM',
       'origin': 'https://identity.foundation'
     },
     'proof': {
       'type': 'Ed25519Signature2018',
       'created': '2020-12-04T20:08:28.540Z',
       'jws': 'eyJhbGciOiJFZERTQSIsImI2NCI6ZmFsc2UsImNyaXQiOlsiYjY0Il19..D0eDhglCMEjxDV9f_SNxsuU-r3ZB9GR4vaM9TYbyV7yzs1WfdUyYO8rFZdedHbwQafYy8YOpJ1iJlkSmB4JaDQ',
       'proofPurpose': 'assertionMethod',
       'verificationMethod': 'did:key:z6MkoTHsgNNrby8JzCNQ1iRLyW5QQ6R8Xuu6AA8igGrMVPUM#z6MkoTHsgNNrby8JzCNQ1iRLyW5QQ6R8Xuu6AA8igGrMVPUM'
     },
     'eyJhbGciOiJSUzI1NiIsImtpZCI6ImRpZDprZXk6ejZNa29USHNnTk5yYnk4SnpDTlExaVJMeVc1UVE2UjhYdXU2QUE4aWdHck1WUFVNI3o2TWtvVEhzZ05OcmJ5OEp6Q05RMWlSTHlXNVFRNlI4WHV1NkFBOGlnR3JNVlBVTSJ9.eyJleHAiOjE3NjQ4NzkxMzksImlzcyI6ImRpZDprZXk6b3RoZXIiLCJuYmYiOjE2MDcxMTI3MzksInN1YiI6ImRpZDprZXk6b3RoZXIiLCJ2YyI6eyJAY29udGV4dCI6WyJodHRwczovL3d3dy53My5vcmcvMjAxOC9jcmVkZW50aWFscy92MSIsImh0dHBzOi8vaWRlbnRpdHkuZm91bmRhdGlvbi8ud2VsbC1rbm93bi9kaWQtY29uZmlndXJhdGlvbi92MSJdLCJjcmVkZW50aWFsU3ViamVjdCI6eyJpZCI6ImRpZDprZXk6b3RoZXIiLCJvcmlnaW4iOiJodHRwczovL2lkZW50aXR5LmZvdW5kYXRpb24ifSwiZXhwaXJhdGlvbkRhdGUiOiIyMDI1LTEyLTA0VDE0OjEyOjE5LTA2OjAwIiwiaXNzdWFuY2VEYXRlIjoiMjAyMC0xMi0wNFQxNDoxMjoxOS0wNjowMCIsImlzc3VlciI6ImRpZDprZXk6b3RoZXIiLCJ0eXBlIjpbIlZlcmlmaWFibGVDcmVkZW50aWFsIiwiRG9tYWluTGlua2FnZUNyZWRlbnRpYWwiXX19.rRuc-ojuEgyq8p_tBYK7BayuiNTBeXNyAnC14Rnjs-jsnhae4_E1Q12W99K2NGCGBi5KjNsBcZmdNJPxejiKPrjjcB99poFCgTY8tuRzDjVo0lIeBwfx9qqjKHTRTUR8FGM_imlOpVfBF4AHYxjkHvZn6c9lYvatYcDpB2UfH4BNXkdSVrUXy_kYjpMpAdRtyCAnD_isN1YpEHBqBmnfuVUbYcQK5kk6eiokRFDtWruL1OEeJMYPqjuBSd2m-H54tSM84Oic_pg2zXDjjBlXNelat6MPNT2QxmkwJg7oyewQWX2Ot2yyhSp9WyAQWMlQIe2x84R0lADUmZ1TPQchNw'
   ],
 };

 verifier.verifyResource({ 
   configuration: didConfigurationResource,
   did: 'did:key:z6MkoTHsgNNrby8JzCNQ1iRLyW5QQ6R8Xuu6AA8igGrMVPUM',
   verifySignatureCallback: (args: IVerifyCallbackArgs) => verifySignatureCallback(args),
 })
 .then(result => 'success')
 .catch(error => 'failed');

Build

yarn build

Test

The test command runs:

  • eslint
  • prettier
  • unit
  • coverage

You can also run only a single section of these tests, using for example yarn test:unit.

yarn test

Utility scripts

There are several other utility scripts that help with development.

  • yarn fix - runs eslint --fix as well as prettier to fix code style.
  • yarn cov - generates code coverage report.