What Can You Do With Affinidi’s Tech Stack?

Affinidi Pte. Ltd.
6 min readFeb 9, 2022

Affinidi’s APIs and SDKs provide the building blocks for decentralized identity creation, verifiable credential issuance, and verification.

This documentation will talk in detail about Affinidi’s SDK and what you can do with it. Also, browse through this blog post or watch this video to see how you can build a driver’s license use-case with these SDKs.

An Introduction to Affinidi’s SDK

Affinidi’s SDK enables you to issue Verifiable Credentials (VCs), register accounts, collect and validate information, verify VCs, and more.

This SDK consists of six packages, and they are:

  • Core
  • Browser
  • Expo
  • Issuer-kit
  • React-native
  • VC-data

Let’s now look through each of these packages and what they do.

sdk/core

The core folder contains the @affinidi/wallet-core-sdk and it implements the common logic for account registration and management, credential issuance and verification, and more.

The sdk/core package is a comprehensive kit that enables you to issue, share, and revoke VCs. It also provides for the ancillary tasks associated with them such as the generation of API keys, DID anchoring, validating holder response, and more.

The entry point for this package is a method called CommonNetworkMember. By default, this will use Affinidi’s staging environment, though you can initialize it with specific service endpoints.

Generate API keys

It creates apiKey and apiKeyHash values after you register your entity at Affinidi’s stack environment, which can be staging, production, or dev. They are both request headers. apiKey is used when calling SDK methods and apiKeyHash is used for making API calls

const options = {env: ‘staging’,apiKey: ‘YOUR API KEY’ (or accessApiKey: ‘YOUR API KEY HASH VALUE’)}

Access Through an Interface

You can call/access the wallet through any platform.

const { AffinidiWallet } = require(‘@affinidi/wallet-{PLATFORM}-sdk’) // where platform is one of ‘browser’, ‘expo’, ‘node’, ‘react-native’

Accordingly, you will use the sdk/browser, sdk/expo, and sdk/react-native packages respectively.

Create a DID

A DID is a type of unique identifier (URI) that enables entities to generate and control their identifiers in the digital world.

Creating a DID is easy with our tech stack as you’ll just have to make the below calls.

const wallet = await AffinidiWallet.createWallet(options, password)const { did, encryptedSeed } = wallet

Here, encryptedSeed is a random auto-generated value that’s used as an input for private key generation. It is stored as an encrypted value in the protected vault and is never exposed to the public. It always remains in its encrypted form as a property to the wallet.

However, you need this value to access or open a wallet.

const wallet = AffinidiWallet.openWalletByEncryptedSeed(options, encryptedSeed, password)

To get the DID, make the below call.

const wallet = AffinidiWallet.openWalletByEncryptedSeed(options, password, encryptedSeed)const did = wallet.did

You can also sign up for the Affinidi cloud wallet using an existing DID or keys.

const { did, encryptedSeed } = await AffinidiWallet.createWallet(options, password)const keyParams = { encryptedSeed, password }const email = ‘example@affinity-project.org’const userPassword = ‘Password123’const options = { env: ‘dev’ }const messageParameters = { message: ‘Welcome to Affinity, here is your OTP: {{CODE}}’ } // (optional)const token = await AffinidiWallet.initiateSignUpByEmail(options, email, userPassword, messageParameters)const confirmationCode = ‘123456’const wallet = await AffinidiWallet.completeSignUp(options, token, confirmationCode, keyParams)

Sign a DID Document

Here is an image that shows the relationship between a DID, DID subject/controller, and a DID document.

A DID Document must be digitally signed for authentication.

This signature is verified using a set of parameters. For example, in a public key cryptography, a public key can be used to verify a digital signature, provided the signer has the associated private key.

The sdk/core package makes this signing easy, as you can use the following method.

const signedDidDocument = await wallet.signDidDocument(didDocument)

Change the Username and Password

Users have to be logged in to change the password and the method to call is,

await wallet.changePassword(oldPassword, newPassword)

If they are not logged in or have forgotten their password, the password recovery method is,

const token = await AffinidiWallet.initiateForgotPassword(options, login, messageParameters)

To change the username, the user requires a new phone number or email address.

const token = await wallet.initiateChangeEmail(newEmail)

or

const token = await wallet.initiateChangePhone(newPhone)

newEmail or newPhone — email address or phone number to be later used to log into cognito

The challenge for verification can be done via this method.

await wallet.completeChangeEmailOrPhone(options, token, confirmationCode)

Finally, to sign out the current user, call

await wallet.logOut()

Generate a Verifiable Presentation

You can generate a verifiable presentation with the below call.

const { isValid, did, challenge, suppliedPresentation } = await verifier.verifyPresentation(vp)

Request and Verify a Verifiable Presentation

The verifier can request the holder to provide a verifiable presentation containing one or more VCs required for verification.

Use the below method to request for a verifiable presentation that meets the w3c specification structure.

const jwtOptions = { audienceDid, expiresAt, nonce, callbackUrl }const presentationChallenge = await verifier.generatePresentationChallenge(credentialRequirements,issuerDid,jwtOptions,)

To verify the presentation, use

const { isValid, did, challenge, suppliedPresentation } = await verifier.verifyPresentation(vp)

If the verification is valid, it returns {did, nonce} , else it returns isValid: false.

Validating the Holder Response

This package has the methods to validate response tokens and verify the signature.

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

If the verification is not valid, this method will return isValid: false

On the other hand, if the response is valid, it returns issuer, nonce, selectedCredentials.

Thus, these are some things you can do with the sdk/core package.

sdk/browser, sdk/expo, and sdk/react-native

This package contains the @affinidi/wallet-[PLATFORM]-sdk package that extends the wallet-core-sdk logic with client specific implementations for crypto operations. Specifically, this package implements the logic to communicate with the encrypted data vault for VC storage, given that crypto operations can be platform dependent.

To install this package,run the below command.

npm i — save @affinidi/wallet-[PLATFORM]-sdk

sdk/issuer-kit

This package contains the @affinidi/issuer-kit and encompasses a framework for launching microservices to connect to external data providers & issue VCs.

This library spins up a VC producing server based on configurations defined by the Application, including any key functions required to build the VCs and external connections required to collect and validate data before issuance.

The Issuer Kit defines an extensible protocol for VC issuance, regardless of the source of the data. The flow can handle anything from primary issuers, where the application already has the data, to a multi-step process that connects with external data providers and solicits asynchronous input from end users.

issuer<VCSPhonePerson, IEndpointSpec>({endpoints, // Specification functions (initiate, verify)expirationLength: 60 * 60 * 24 * 365.25, // One year expiration for VCsfastifyOpts: {logger: {level: ‘debug’}}, // Options to pass to fastify()fastifyListenOpts: {port: 3000}, // Options to pass to fastify.listen()swaggerOpts: { // Options to pass to fastify-swaggerexposeRoute: true,swagger: {info: {title: ‘Issuer Phone Twilio API’,description: ‘Issue a Phone VC based on an SMS challenge’,version: ‘1.0.0’,},},},})

This kit returns a complete, but unsigned VC, and the issuer has to sign with the private key before issuing it to the holder.

Before moving to the next library, let’s talk a bit about the specification functions of endpoints, namely Initiate and Verify.

Initiate

This function creates a new and incomplete VC based on the inputs.

Verify

This is the last function before the unsigned VC is returned. It also includes a challenge token sent by the end-user to prove that he or she is in control of the contact information present in the VC. This challenge token is sent to users via an external API, and on successful response from the user, it issues a VC.

During implementation, please note that the verify function must implement the data transformation from source data to standardized credentialSubject using network-level accepted schemas and any other optional database or other post-completion cleanup tasks.

sdk/vc-data

This repository contains the suggested specification for Verifiable Credential data, referred to as credentialSubject in the VC data model. In general, these schemas are based on schema.org base types such as Person and Organization, with custom extensions for concepts not described by schema.org.

Install this package with the below code.

npm install — save @affinidi/vc-data

Besides these SDKs, we also have some common libraries that contain the utilities used across all Affinidi products and services.

We hope this gives you a good idea on what you can do with Affinidi’s stack.

For more questions and in-depth technical discussions, reach out to us on Discord, and we’ll be happy to answer any questions/doubts you may have.

--

--

Affinidi Pte. Ltd.

Reclaim your data, Reclaim your Identity, Reclaim Yourself