Coder Social home page Coder Social logo

microsoft / verifiablecredentials-verification-sdk-typescript Goto Github PK

View Code? Open in Web Editor NEW
54.0 18.0 14.0 1.27 MB

An SDK to help Relying Parties manages their Decentralized Identities and Verifiable Credentials.

License: MIT License

TypeScript 99.86% JavaScript 0.13% Batchfile 0.01%

verifiablecredentials-verification-sdk-typescript's Introduction

From October 31, 2021 certain Microsoft Azure AD Verifiable Credential SDK functionality will stop working in Microsoft Authenticator. Applications and services that currently use the Microsoft Azure AD Verifiable Credential SDK should migrate to the Microsoft Request Service REST API.


GitHub package.json version GitHub commit activity

GitHub Verification SDK

Repo

https://github.com/microsoft/VerifiableCredentials-Verification-SDK-Typescript

Goals

Goal – Validate complex Self-Issued OpenID Connect (SIOP) requests

SIOPs can contain multiple id tokens such as verifiable credentials and presentations. The SDK defines easy methods to validate these complex payloads.

We can pass in expected values and these values are checked by the SDK during the validation process.

Goal – Help services to create OpenID Connect requests

Support for creating signed OpenID Connect requests. The signing can be done on nodejs or on Key Vault.

Goal – Service can decide to use Key Vault for key storage and crypto operations

Provide flexibility to services to use more secure environments such as Key Vault for critical cryptographic operations. The service can use configuration to switch between Key Vault or nodejs.

Concepts

Builder pattern

The top-level API is based on the Builder pattern. The Builder pattern allows for different representation of complex classes. This is great to deal with a lot of different options. Our SDK must deal with a lot of options, hence the choice for the Builder pattern.

Practically each base class has a builder class. We use the following convention:

for the base class.

Builder for the builder class.

The builder class use verbs to add options (e.g. useState, useNonce). The builder class’s purpose is managing the options and not to do actions. By calling the build() method, an instance of the base class is created.

The action methods are defined in the base class. The base class has access to the builder class for access to all properties.

The constructor of the builder class will use arguments which are fixed for the object so the constructor can be instantiated beforehand, in some initializer class.

CryptoBuilder/Crypto

The Crypto class is necessary for the Requestor class. The Requestor needs to sign the request payload and requires cryptographic capabilities.

The creation of the Crypto base class is faily simple.

    const crypto = new CryptoBuilder(did, signingKeyReference)
    .useDid(did)
    .useSigningKeyReference(signingKeyReference)
    .build();

did

The DID of the service

signingKeyReference

The reference that is used to publish the public key of the signing key in the DID document.

Services require flexibility where their security critical, cryptographic operations happen. The default is no secure environment.

The Crypto object supports Key Vault as a secure environment for the cryptographic operations.

  const crypto = new CryptoBuilder()
    .useKeyVault(credential, vaultUrl)
    .useDid(did)
    .useSigningKeyReference(signingKeyReference)
    .build();

useKeyVault

The useKeyVault method informs the Crypto class that cryptographic operations need to happen on Key Vault.

‘credential’ allows to pass in different credential used to access Key Vault. One can pass in a client id and client secret but also an X.509 certificate.

‘vaultUrl’ specifies the bases url of the Key Vault environment to use.

RequestorBuilder/Requestor

Services authenticate users by means of DIDs. The DID community created a protocol based on the Self Issued OpenID Connect provider protocol called DID Auth based on a simple request/response transaction. The service needs to produce a signed request on which the user’s agent will respond with a response containing claims about the subject/user.

The Requestor class is designed to create DID Auth Requests and make the process of allowing users to authenticate by means of DIDs simpler.

  const requestor = new RequestorBuilder(request, crypto)
    .useNonce(nonce)
    .useState(state)  
    .build();

The constructor takes a JSON object which contains information about the service. There are three important areas in the request:

  1. The Crypto object needed to allow the Requestor to sign the request.
  2. Properties about the service such as its name, logo, etc.
  3. An attestation sections which allows the service to state which claims are expected in the response.

In the example we also pass in the state and nonce properties intended to protect the transaction. In case one wants to instantiate the builder class beforehand, in some service initializer class, nonce and state can also be passed into the requestor create method.

The actual OpenID Connect request can be created by means of a simple call.

const requestResult = await requestor.create();

ValidatorBuilder/Validator

The Validator class validates id tokens. Tokens in the DID space can be very complex and the Validator class helps services to making the process of validating these tokens much simpler.

The Validator class validates five kind of tokens.

Self-Issued token

A self-issued token is just a set of claims provided by the user in a JSON object. There is no validation done on the self-issued token.

OpenID Connect id token

An OpenID Connect id token is issued by an OpenID Connect provider. This provider is represented by a configuration URI usually referred to as the well-known URI. The configuration URIs of the trusted OpenID Connect providers need to be provided to the Validator to allow the Validator to validate the corresponding id token.

Verifiable credentials and their corresponding presentations

Verifiable credentials are standardized by W3C.

Verifiable credentials are issued to the user by some trusted issuer.

Verifiable presentations present a verifiable credential to some peer. A presentation can contain one or more verifiable credentials. A presentation is also a token.

Self-Issued OpenID Connect (SIOP)

The SIOP is the actual response signed by the DID of the client that is returned when the service does a SIOP request. The SIOP can contain any of the above tokens.

       const validator = new ValidatorBuilder(this.crypto)
        .useTrustedIssuerConfigurationsForIdTokens(rules.attestations.idTokens.map((idTokenRule: any) => idTokenRule.configuration))
        .useAudienceUrl('https://test-relyingparty.azurewebsites.net/verify')
        .build();

      const validationResult = await validator.validate(siop);
      if (!validationResult.result) {
          console.error(`Validation failed: ${validationResult.detailedError}`);
          return validationResult;
      }

      return validationResult;

The example creates a Validator object by passing in two options.

useTrustedIssuerConfigurationsForIdTokens provides an array of trusted well-know configuration URIs, needed by the validator to check id tokens.

useAudienceUrl provides the URL of the service’s validation endpoint. This is used to check whether the SIOP was presented to the right endpoint.

The validate(siop) method does the actual validation.

Getting started

Install

To add the sdk to your package.json:

npm i verifiablecredentials-verification-sdk-typescript

Cloning

Git clone verifiablecredentials-verification-sdk-typescript.git

Update all packages

npm install

Build

npm run build

Test

npm run test

Publishing the package to npmjs

Only authorized publishers are allowed to publish the package.

Test all unit tests

 npm run build
 npm run test

Make sure all tests pass. Make sure no new uncovered lines are introduced.

Update version

Make sure package.json shows the new version to publish. Also CHANGE_LOG.md shows the changes done to the new version.

publish

It is most common to publish a preview version.

npm publish --tag preview

Skip the --tag to do a new release of the package. Remove '-preview.' from the version number. The release package is the same as the last preview package.

Contributing

This project welcomes contributions and suggestions. Most contributions require you to agree to a Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us the rights to use your contribution. For details, visit https://cla.opensource.microsoft.com.

When you submit a pull request, a CLA bot will automatically determine whether you need to provide a CLA and decorate the PR appropriately (e.g., status check, comment). Simply follow the instructions provided by the bot. You will only need to do this once across all repos using our CLA.

This project has adopted the Microsoft Open Source Code of Conduct. For more information see the Code of Conduct FAQ or contact [email protected] with any additional questions or comments.

verifiablecredentials-verification-sdk-typescript's People

Contributors

beejones avatar codeglobally avatar gpproano avatar gproanomsft avatar jcruiz avatar jorgeibarra13 avatar mauesrog avatar microsoft-github-operations[bot] avatar microsoftopensource avatar nithyaganeshng avatar symorton avatar

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

Watchers

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

verifiablecredentials-verification-sdk-typescript's Issues

Change that requires the update key is failing with "key: Is not extractable"

I saw that you recently changed that we need to include an update key.

I implemented it like you suggested:

let crypto: Crypto;
(async () => {
  try {
    crypto = await createIssuerCrypto();
    crypto = await crypto.generateKey(KeyUse.Signature, "signing");
    crypto = await crypto.generateKey(KeyUse.Signature, "recovery");
    crypto = await crypto.generateKey(KeyUse.Signature, "update");    
    const did = await new LongFormDid(crypto).serialize();
    crypto.builder.useUpdateKeyReference(crypto.builder.updateKeyReference);
    crypto.builder.useDid(did);
  } catch (error) {
    console.log(error);
  }
})();

Though the line where I generate the update key fails with the following message:
(node:52954) UnhandledPromiseRejectionWarning: Error: key: Is not extractable at EcdsaProvider.checkExportKey

Are you aware of this or am I missing something? Would also be cool if you could update the demo App that shows the right approach.

TypeError: Key is not of type 'CryptoKey' at SubtleCryptoKeyVault.checkCryptoKey

I opened already a ticket on the demo page, but I think the issue might be more related to the SDK here.

It seems like the SDK doesn't recognize the signing keys?

The error appears once I try to build a request with e.g.

req.session.issueRequest = await requestBuilder.build().create();

Error log:

(node:62578) UnhandledPromiseRejectionWarning: TypeError: Key is not of type 'CryptoKey'
    at SubtleCryptoKeyVault.checkCryptoKey (/Users/mathiasklenk/passbase-dev/credential-issuer/node_modules/webcrypto-core/build/webcrypto-core.js:893:19)
    at SubtleCryptoKeyVault.sign (/Users/mathiasklenk/passbase-dev/credential-issuer/node_modules/webcrypto-core/build/webcrypto-core.js:762:14)
    at SubtleCryptoExtension.signByKeyStore (/Users/mathiasklenk/passbase-dev/credential-issuer/node_modules/verifiablecredentials-crypto-sdk-typescript-plugin/dist/lib/SubtleCryptoExtension.js:53:40)
    at JwsToken.sign (/Users/mathiasklenk/passbase-dev/credential-issuer/node_modules/verifiablecredentials-crypto-sdk-typescript-protocol-jose/dist/lib/jws/JwsToken.js:382:40)
    at processTicksAndRejections (internal/process/task_queues.js:93:5)
    at async Jose.sign (/Users/mathiasklenk/passbase-dev/credential-issuer/node_modules/verifiablecredentials-crypto-sdk-typescript/dist/lib/Jose.js:52:23)
    at async Requestor.create (/Users/mathiasklenk/passbase-dev/credential-issuer/node_modules/verifiablecredentials-verification-sdk-typescript/dist/lib/api_oidc_request/Requestor.js:70:27)
    at async exports.issueRequest (/Users/mathiasklenk/passbase-dev/credential-issuer/src/controller/credentialIssuerController.js:76:30)
(Use `node --trace-warnings ...` to show where the warning was created)
(node:62578) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 2)
(node:62578) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
(node:62578) UnhandledPromiseRejectionWarning: TypeError: Key is not of type 'CryptoKey'
    at SubtleCryptoKeyVault.checkCryptoKey (/Users/mathiasklenk/passbase-dev/credential-issuer/node_modules/webcrypto-core/build/webcrypto-core.js:893:19)
    at SubtleCryptoKeyVault.sign (/Users/mathiasklenk/passbase-dev/credential-issuer/node_modules/webcrypto-core/build/webcrypto-core.js:762:14)
    at SubtleCryptoExtension.signByKeyStore (/Users/mathiasklenk/passbase-dev/credential-issuer/node_modules/verifiablecredentials-crypto-sdk-typescript-plugin/dist/lib/SubtleCryptoExtension.js:53:40)
    at JwsToken.sign (/Users/mathiasklenk/passbase-dev/credential-issuer/node_modules/verifiablecredentials-crypto-sdk-typescript-protocol-jose/dist/lib/jws/JwsToken.js:382:40)
    at processTicksAndRejections (internal/process/task_queues.js:93:5)
    at async Jose.sign (/Users/mathiasklenk/passbase-dev/credential-issuer/node_modules/verifiablecredentials-crypto-sdk-typescript/dist/lib/Jose.js:52:23)
    at async Requestor.create (/Users/mathiasklenk/passbase-dev/credential-issuer/node_modules/verifiablecredentials-verification-sdk-typescript/dist/lib/api_oidc_request/Requestor.js:70:27)
    at async exports.issueRequest (/Users/mathiasklenk/passbase-dev/credential-issuer/src/controller/credentialIssuerController.js:76:30)
@mathiasklenk


Keys for commit/reveal should be EC secp256k1 keys

When provisioning keys for a commit/reveal pair...

const secretKey = await this.crypto.builder.subtle.generateKey(<AesKeyGenParams>{ name: "AES-GCM", length: 256 }, true, ["encrypt", "decrypt"]);

  1. I believe the sidetree implementation expects these to be secp256k1 public keys, which wouldn't be compatible with a private AES-GCM key

  2. It'll be important to return the associated private key (or maybe following the keyStore pattern, write these keys to a relevant store)

Ambiguity of the format of universalResolverUrl for the ManagedHttpResolver ctor

Hi, I'm following the documentation here. In the sample the current url passed to the ManagedHttpResolver constructor is: "https://beta.discover.did.microsoft.com/1.0/identifiers"
However I think this is not working because the ctor appends the "/1.0/identifiers/" segments again resulting in a wrong url.

this.resolverUrl = `${universalResolverUrl}${slash}1.0/identifiers/`;

I apologies if the issue is only in the sample/documentation side that needs to use a different url, just "https://beta.discover.did.microsoft.com/"
Actually there's a bug note in the sample repo but I wasn't sure: https://github.com/Azure-Samples/active-directory-verifiable-credentials/blob/fb093ccabce6f2cdd2228622c66d397c2c5e9a3e/verifier/app.js#L172

Thanks.

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.