0.0.4 • Published 10 months ago

@idos-network/issuer-sdk-js v0.0.4

Weekly downloads
-
License
MIT
Repository
github
Last release
10 months ago

idOS Issuer JavaScript SDK

NPM License

Installing

Get our NPM package and its dependencies with pnpm or the equivalent of your package manager of choice:

pnpm add @idos-network/issuer-sdk-js

Before you start

When using this package, you're going to need to be familiar with how a dApp works with the idOS. Make sure you read idos-sdk-js's README before you proceed.

Setting up

Create an issuer config with your secret key. This config will be used to interact with the idOS.

// issuer-config.js
import { createIssuerConfig } from "@idos-network/issuer-sdk-js";

const signingKeyPair = nacl.sign.keyPair.fromSecretKey(ISSUER_SIGNING_SECRET_KEY);

const issuerConfig = await createIssuerConfig({
  // To use a non-prod environment, pass in "nodes.playground.idos.network".
  nodeUrl: "https://nodes.idos.network/",
  signingKeyPair,
});

Creating a user profile

This procedure can only be done by a Permissioned Issuer. Get in touch with us at engineering@idos.network if you're interested in being one.

To create a user profile in idOS, you need: 1. A wallet address associated with the user. 2. A public encryption key derived from either a password or a passkey chosen by the user in the idOS enclave app.

User Creation Process

Step 1: Decide on a user id

Deciding on a user id for a user is an issuer decision. You can use whichever you want, as long as it's an UUID.

// Server side

const userId = crypto.randomUUID();

// Remember it on your database
session.user.update({ userId })

// Return it to the front-end to be used in the next step
return { userId }

Step 2: Derive the Public Key

Use the idos.discoverUserEncryptionPublicKey function to derive a public key for the user. This key will be used to encrypt and decrypt user's credential content.

// Client side

import { idOS } from "@idos-network/idos-sdk-js";

// Arguments are described on idos-sdk-js's README. Be sure to read it.
// Note: make sure to set mode to "new" since you're creating a new idOS profile
const initParams = { ...YOUR_IDOS_INIT_PARAMS, mode: "new" };
const idos = await idOS.init(...);

// Get userId associated with this user from your server
const { userId } = await yourServer.getIdosInformation();

// Discover user encryption key
const { userEncryptionPublicKey } = await idos.discoverUserEncryptionPublicKey(userId);

// Report it back to your server
await yourServer.reportIdosEncryptionPublicKey(userEncryptionPublicKey);

Step 3: Creating a User Profile

Once the public key is derived, you can create the user profile in idOS by passing it to the createUser function alongside with user id and the wallet the user's going to use to drive their idOS profile.

// Server side

import { createUser } from "@idos-network/issuer-sdk-js";
import issuerConfig from "./issuer-config.js";

// Get this from the user's request, and remember it
const currentPublicKey = request.params['userEncryptionPublicKey']
session.user.currentPublicKey = currentPublicKey

// Get the stored user id
const userId = session.user.userId

// Build the user object
const user = {
  id: userId,
  recipient_encryption_public_key: currentPublicKey,
}

// Build the wallet object
const walletPayload = {
  // The user's wallet address (e.g., an Ethereum address)
  address: "0x0",
  // The type of user wallet (e.g., "EVM", "NEAR")
  wallet_type: "EVM",
  // The message that was signed by the address
  message: "app wants you to sign this message...",
  // The derived signature for the message, created with the user wallet
  signature: "0x3fda8a9fef767d974ceb481d606587b17c...",
  // The user wallet's public key
  public_key: "RxG8ByhoFYA6fL5X3qw2Ar9wpblWtmPp5MKtlmBsl0c=",
}

// Create the user on idOS nodes, and get some information back.
const [profile, wallet] = await createUser(issuerConfig, user, walletPayload);

Writing credentials

In order to write a credential to idOS, the issuer needs to obtain permission from the user. This can be done in two ways: using Write Grants, or using Permissioned Credential Creation. Below are the two methods for writing credentials.

Using Write Grants

The first method involves getting permission from the user via a Write Grant.

A Write Grant is a permission given by the user that allows a specific grantee to perform a few operations on their behalf. This is particularly relevant to not require the user to come back to your website if you want to add data to their profile.

To do this, you must first create a Write Grant using the idOS SDK. Here's an example of creating a write grant, by calling the idos.data.addWriteGrant:

// Client side

import { idOS } from "@idos-network/idos-sdk-js";
import * as Utf8Codec from "@stablelib/utf8";

// Arguments are described on idos-sdk-js's README. Be sure to read it.
const idos = await idOS.init(...);

// This is a placeholder for your signer's address. You could get it from
// some endpoint you expose. But, to keep it simple, we're using a constant.
const ISSUER_SIGNER_ADDRESS = "0xc00ffeec00ffeec00ffeec00ffeec00ffeec00ff";

// Ask the user for a Write Grant
await idos.data.addWriteGrant(ISSUER_SIGNER_ADDRESS);

Now that the user has created a Write Grant for us, the issuer, we can create a credential for the user:

// Server side

import { createCredentialByGrant, encryptionPublicKey } from "@idos-network/issuer-sdk-js";
import issuerConfig from "./issuer-config.js";

const publicNotesId = crypto.randomUUID();

const credentialsPublicNotes = {
  // `id` is required to make `editCredential` work.
  id: publicNotesId,
  type: "human",
  level: "human",
  status: "approved",
  // make yourself discoverable by dApps.
  issuer: "MyCoolIssuer",
}

const credentialContent = JSON.stringify({
  "@context": [
    "https://www.w3.org/2018/credentials/v1",
  ],
  id: "uuid:087b9cf0-a968-471d-a4e8-a805a05357ed",
  type: ["VerifiableCredential"],
  issuer: "https://vc-issuers.cool-issuer.id/",
  level: "human",
  credentialSubject: {
    id: "uuid:33ce045b-19f8-4f5a-89d9-4575f66f4d40",
    name: "John Doe",
    email: "johndoe@example.com",
    country: "USA",
  },
  issuanceDate: "2022-06-01T12:00:00Z",
  expirationDate: "2022-06-30T12:00:00Z",
  proof: {
    type: "Ed25519Signature2020",
    created: "2022-06-01T12:00:00Z",
    verificationMethod: "https://vc-issuers.fractal.id/idos/keys/1",
    proofPurpose: "assertionMethod",
    proofValue: "z22DAdBQgJXUh69e4y9a7t7n9f6c7m7b8a6v6w5z4x3y2x1w",
  },
})

const credentialPayload = {
  id: crypto.randomUUID(),

  // user id of the user who is creating the credential.
  user_id: session.user.userId,

  // The verifiable credential content should be passed as it's seen in the example at https://verifiablecredentials.dev/ usually a stringfied JSON object.
  // credential content is encrypted, using the Issuer's secret encryption key, along with the receiver's public encryption key.
  // plaintextContent should be passed as a Uint8Array.
  plaintextContent: Utf8Codec.encode(credentialContent),

  // The public encryption key of the user who is creating the credential. also passed as a Uint8Array.
  receiverEncryptionPublicKey: Utf8Codec.encode(session.user.userEncryptionPublicKey),

   // These notes will be publicly disclosed and accessible without needing to decrypt the credential.
  publicNotes: JSON.stringify(credentialsPublicNotes),
}

const credential = await createCredentialByGrant(issuerConfig, credentialPayload);

This will create a credential in the idOS for the given user id.

⚠️ Notice

The credential content should be passed as is. It will be encrypted for the recipient before being stored on the idOS.

Using Permissioned Credential Creation

The second method allows the issuer, by virtue of being a Permissioned Issuer, to create a credential without a Write Grant. Get in touch with us at engineering@idos.network if you're interested in being one.

For this method, use the createCredentialPermissioned function to write the credential with the necessary encryption.

Example:

// Server side

import { createCredentialPermissioned } from "@idos-network/issuer-sdk-js";
import issuerConfig from "./issuer-config.js";

// See the previous example for more details on these fields
await createCredentialPermissioned(issuerConfig, credentialPayload);

Sharing credentials

The SDK provides issuer to share credentials with other grantees. This function is called shareCredentialByGrant.

// Server side
import issuerConfig from "./issuer-config.js";

await shareCredentialByGrant(issuerConfig,{
  ...credentialPayload,
  grantee: "GRANTEE_WALLET_ADDRESS",
  lockedUntil: Math.floor(Date.now() / 1000) + 1000,
  originalCredentialId: credentialPayload.id,
});

Editing credentials

The editCredential function allows issuers to update the public notes associated with a credential in the idOS. This is useful for actions like marking credentials as revoked or updating metadata.

In order for editCredential to work, the credential's public_notes field needs to be a valid JSON object with an id field, and the public_notes_id argument needs to have that value.

⚠️ Warning

If the new public_notes value doesn't have an id field, you'll stop being able to edit that credential.

// Server side
import issuerConfig from "./issuer-config.js";
const public_notes_id = crypto.randomUUID();
await editCredential(issuerConfig, {
  public_notes_id: publicNotesId,
  public_notes: JSON.stringify({
    ...credentialsPublicNotes,
    status: "revoked",
  }),
});

Revoking a credential

A previously created credential can be revoked by the issuer by calling the editCredential function. When creating a credential, the publicNotes field needs to have an id field that will be used to identify the credential to be revoked. Pass this id to the editCredential function to revoke the credential.

// Server side

import { editCredential } from "@idos-network/issuer-sdk-js";
import issuerConfig from "./issuer-config.js";

await editCredential(issuer, {
    publicNotesId: id, // the `id` of the credential to be revoked that is stored in the `publicNotes` field.
    publicNotes: JSON.stringify({
      ...publicNotes,
      status: "revoked" // updating the credential status to revoked
    }),
  });

Developing the SDK locally

Run:

pnpm dev

This will start the compiler in watch mode that will rebuild every time any of the source files are changed.

You can also create a production build by running the following command in the root folder of the SDK package:

pnpm build
0.0.4

10 months ago

0.0.3

11 months ago

0.0.2

11 months ago

0.0.1

11 months ago

0.0.1-0

11 months ago