JSPM

  • Created
  • Published
  • Downloads 14
  • Score
    100M100P100Q42514F
  • License ISC

SDK core monorepo for affinity DID solution

Package Exports

  • @affinityproject/wallet-core-sdk
  • @affinityproject/wallet-core-sdk/dist/services/CognitoService
  • @affinityproject/wallet-core-sdk/dist/services/WalletStorageService

This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (@affinityproject/wallet-core-sdk) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.

Readme

Affinity Core SDK - Affinity network DID solution

Table of contents

Workflows

DID anchoring

schema

Share VC Flow

schema

Offer VC Flow

schema

Wallet Storage

schema

How to install

npm i --save @affinityprojecthub/wallet-core-sdk

Using SDK on client

Deploying minified bundle version

  1. Generate minified bundle file (/build/affinity.min.js.br):

    npm run buildClient

    To generate unminified bundle file:

    npm run buildClient:dev

    Unminified bundle file is compiled in /build/affinity.js

  2. Bundle files are deployed to CDN as a part of pipeline (via GitHub actions)

  3. Using lib on the client

    The entry point of the library is affinityNetworkMember.

    <script src='https://cdn.affinity-project.org/affinity.min.js.br'></script>
    ...
    const { CommonNetworkMember } = affinityNetworkMember

Initialize

If you want to specify issuer's URL, pass it in the options.

You can also specify the stack environment to be used in env variable. env - (optional) is enum which can be dev | staging | prod (staging is used by default).

const options = {
  issuerUrl: 'https://affinity-issuer.staging.affinity-project.org'
}

const commonNetworkMember = new CommonNetworkMember(password, encryptedSeed, options)

options - (optional) if not defined, values posted above will be used.

Issuer / Holder / Verifier interface examples

Initialize from seed

const options = {
  issuerUrl: 'https://affinity-issuer.staging.affinity-project.org'
}

CommonNetworkMember.fromSeed(seedHex, options, password)

options - (optional) if not defined, values posted above will be used.

password - (optional) if not defined, it will be generated.

Sign DID document

const signedDidDocument = await commonNetworkMember.signDidDocument(didDocument)

Interface

const { CommonNetworkMember } = require('@affinityprojecthub/wallet-core-sdk')

Generate seed

Generates random seed from which keys could be derived.

const seed = await CommonNetworkMember.generateSeed(didMethod)

didMethod - (optional) enum (elem | jolo), if not defined, elem DID method will be used.

Create DID

const options = { issuerUrl: 'https://affinity-issuer.staging.affinity-project.org' }

const { did, encryptedSeed } = await CommonNetworkMember.register(password, options)

URL mentioned above will be used, if options was not provided.

Creation of DID flow is the same for each member. E.g. creation of DID for Verifier works the same:

const { did, encryptedSeed } = await CommonNetworkMember.register(password)

Intiate SDK

const options = {
  issuerUrl:   'https://affinity-issuer.staging.affinity-project.org',
}

const networkMember = new Wallet(password, encryptedSeed, options)

options - (optional) if not defined, values posted above will be used.

Get DID

const networkMember = new CommonNetworkMember(password, encryptedSeed, options)

const did = networkMember.did

did - user's DID

Passwordless sign in or sign up if user does not exist + DID creation

NOTE: This passwordless method was designed for a specific usecase, and its
simple user interface achieved by making extra calls to AWS Cognito.
If this method is chosen for authentication you may see failed requests
to Cognito in the browser's console - that is expected behaviour,
exceptions are caught and handled properly.
const options = { env: 'staging' }

const token = await CommonNetworkMember.signIn(username, options)

username - email or phoneNumber, of existing Cognito user or if it does not exist, a new one will be created.

options - (optional) used to specify environment stack dev | staging | prod.

Confirm sign in

const { isNew, commonNetworkMember } = await CommonNetworkMember.confirmSignIn(token, confirmationCode, options)

token - from previous step.

confirmationCode - 6 digits code, generated and sent by AWS Cognito/SES.

options - (optional) if not defined defaults will be used.

Returns isNew flag, identifying whether new account was created, and initialized instance of SDK - commonNetworkMember.

Sign up

const token = await CommonNetworkMember.signUp(username, password, options)

password - (optional)(if not passed - user will be able login only throw passwordlessLogin).

userName - username

options - (optional) used to specify environment stack (dev | staging | prod).

SMS/email with verification code will be sent to appropriate login method.

To re-send sign up confirmation code:

await CommonNetworkMember.resendSignUpConfirmationCode(username, options)

options - (optional) used to specify environment stack (dev | staging | prod).

To confirm email/phoneNumber and finish registration:

const commonNetworkMember = await CommonNetworkMember.confirmSignUp(token, confirmationCode, options)

token - token from the previous step.

options - (optional) used to specify environment stack (dev | staging | prod).

To store keys on Affinity Guardian Wallet:

await commonNetworkMember.storeEncryptedSeed(username, password, options)

options - (optional) used to specify environment stack (dev | staging | prod).

Get Signup Credential

const signedCredential = await CommonNetworkMember.getSignupCredentials(accessToken, idToken, options)

accessToken - Access JWT from AWS cognito

idToken - ID JWT from AWS cognito

options - (optional) used to specify environment stack (dev | staging | prod).

Credential offer is sent from wallet backend back to client if idToken contains verified email or phone number. Client automatically accepts and requests a signed credential. Signed credential is sent back. Signed credential is saved in the user vault.

Initiate instance of SDK with login and pasword

To initiate instance of networkMember using just login and password (when user already signed up at Affinity, and if stored his keys at Affinity Guardian Wallet).

const networkMember = await CommonNetworkMember.fromLoginAndPassword(username, password, options)

options - (optional) used to specify environment stack (dev | staging | prod).

Passwordless login

Login to the network by username, registered in AWS Cognito.

const token = await CommonNetworkMember.passwordlessLogin(username, options)

username - email or phone number, at which confirmation code will be sent.

options - (optional) used to specify environment stack (dev | staging | prod).

Complete login challenge and initiate instance of SDK:

await CommonNetworkMember.completeLoginChallenge(token, confirmationCode, options)

token - token from the previous step.

confirmationCode - 6 digits code, generated and sent by AWS Cognito/SES.

options - (optional) if not defined defaults will be used.

Password recovery

await CommonNetworkMember.forgotPassword(username, options)

username - email or phone number, at which confirmation code will be sent.

options - (optional) used to specify environment stack (dev | staging | prod).

Complete change password challenge:

await CommonNetworkMember.forgotPasswordSubmit(username, confirmationCode, newPassword, options)

username - username in Cognito.

confirmationCode - 6 digits code, generated and sent by AWS Cognito/SES.

newPassword - new password for Cognito user.

options - (optional) used to specify environment stack (dev | staging | prod).

Change username

const commonNetworkMember = new CommonNetworkMember(password, encryptedSeed, options)

await commonNetworkMember.changeUsername(newUsername)

newUsername - email or phone number that will be a new username in Cognito.

Complete change username challenge:

const commonNetworkMember = new CommonNetworkMember(password, encryptedSeed, options)

await commonNetworkMember.confirmChangeUsername(newUsername, confirmationCode, options)

newUsername - username from the previous step.

confirmationCode - 6 digits code, generated and sent by AWS Cognito/SES.

Sign Out

Signs out current Cognito user.

await CommonNetworkMember.signOut(options)

options - (optional) used to specify environment stack (dev | staging | prod).

Issuer

Initiate credential offer request

const credentialOfferToken = await issuer.generateCredentialOfferRequestToken(offeredCredentials, options)

const { audienceDid, expiresAt, nonce, callbackUrl } = options

audienceDid (string) - audience of genreated token.

expiresAt (isoString) - expires of genreated token.

nonce (string) - nonce/jti of genreated token.

callbackUrl (string)

Initiate DID auth

const authDidRequestToken = await issuer.generateDidAuthRequest(options)
const { audienceDid, expiresAt, nonce, callbackUrl } = options

audienceDid (string) - audience of genreated token.

expiresAt (isoString) - expires of genreated token.

nonce (string) - nonce/jti of genreated token.

callbackUrl (string)

const offeredCredentials = [{
  type: 'IssuerCustomCredential',
  renderInfo
}]

renderInfo (optional) where issuer can define how that VC can be represented/shown.

Example:

const renderInfo = {
  logo: {
    url: 'https://miro.medium.com/fit/c/240/240/1*jbb5WdcAvaY1uVdCjX1XVg.png'
  },
  background: {
    url: 'https://i.imgur.com/0Mrldei.png',
  },
  text: {
    color: '#05050d'
  }
}

credentialOfferToken can be passed to the wallet side, and let Wallet/Holder option to response to this offer if usser want take offered credentials.

Validate Holder Response on Offer Request

const { isValid, did, nonce, selectedCredentials } = await issuer.verifyCredentialOfferResponseToken(credentialOfferResponseToken, credentialOfferRequestToken)

credentialOfferRequestToken (optional) - using when need check response against request (nonce, audience).

Validates response token and verify signature, if verification not passed response { isValid: false } if response is valid returns also { issuer, nonce, selectedCredentials }.

did - it's DID which signed that response.

Sign multiple credentials

const credentialParams = {
  type:              'ProofOfAgeOverCredential',
  context:           [{ 'id': '@id', 'type': '@type', 'schema': 'http://schema.org/' }],
  credentialSubject: { 'ageOver': 18 },
  expiresAt:         '2021-01-16T07:06:35.337Z',
}

const credentials = await signCredentials(credentialOfferResponseToken, credentialParams)

credentialOfferResponseToken - credential offer response JWT.

credentialParams - array of params for credentials, where expiresAt is optional.

Generate signed credential

const credential = await issuer.signCredential(claim, credentialMetadata, { credentialOfferResponseToken, requesterDid }, expiresAt)

claim - data which should be present in VC according to VC schema, for example: const claim = { ageOver: 18 }.

credentialMetadata - schema of credential (should be defined and Issuer and Verifier use the same, so verifier will be able to understand what kind of credential was created by Issuer).

Example:

const customMetadata = {
  context: [{
    ageOver: 'https://ontology.example.com/v1#ageOver',
    ProofOfAgeOverCredential: 'https://ontology.example.com/v1#ProofOfAgeOverCredential'
  }],
  name: 'Age Over',
  type: ['Credential', 'ProofOfAgeOverCredential'],
  claimInterface: {
    ageOver: 0
  }
}

Verifier

Initiate credential share request

const credentialShareRequestToken = await verifier.generateCredentialShareRequestToken(credentialRequirements, issuerDid, jwtOptions)

const { audienceDid, expiresAt, nonce, callbackUrl } = jwtOptions

audienceDid (string) - audience of genreated token.

expiresAt (isoString) - expires of genreated token.

nonce (number) - nonce/jti of genreated token.

callbackUrl (string)

Generates JWT with info of which VC credentialRequirements to be provided from Wallet/Holder.

const credentialRequirements = [{ type: ['Credential', 'ProofOfNameCredential'] }]

callbackUrl - (optional) Holder/Wallet will be able send response on this request to this URL.

issuerDid - (optional) its contrain, that define required isser of VC.

credentialShareRequestToken can be send to Wallet/Holder to anwser on this with response with requested VC inside.

Validate Holder Response on Share Request

const { isValid, did, nonce, suppliedCredentials } = await verifier.verifyCredentialShareResponseToken(credentialShareResponseToken, credentialShareRequestToken, isHolderMustBeSubject)

credentialShareResponseToken - (optional) using when need check response against request (when request have constrains).

isHolderMustBeSubject - (optional) can be passed as true, when need to verify that holder is a subject of VC.

Its validate response token and verify signature on provided VC inside, if verification not passed response { isValid: false }. If response is valid it returns also { did, nonce, suppliedCredentials }.

Validate Holder Response on Did auth Request

const { isValid, did, nonce } = await verifier.verifyDidAuthResponse(authDidResponseToken, authDidRequestToken)

Its validate response token, if verification not passed response { isValid: false } if response is valid returns also { did, nonce }

Wallet

Create Response on credential share request

const responseToken = await wallet.createCredentialShareResponseToken(credentialShareRequestToken, suppliedCredentials, callbackURL)

suppliedCredentials - credentials which Holder providing for Verifier.

callbackURL - (optional)

Create Response on credential offer request

const responseToken = await wallet.createCredentialOfferResponseToken(credentialOfferRequestToken)

Agree to recieve proposed credentials by the Issuer.

Create Response on DID auth request

const authDidResponseToken = await wallet.createDidAuthResponse(authDidRequestToken)