Skip to content

Commit

Permalink
Update Examples to JWT (#1185)
Browse files Browse the repository at this point in the history
  • Loading branch information
abdulmth authored Jun 14, 2023
1 parent 4f27434 commit fcfe4e7
Show file tree
Hide file tree
Showing 46 changed files with 385 additions and 670 deletions.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { customResolution } from "../../../examples/dist/web/1_advanced/5_custom_resolution";
import { customResolution } from "../../../examples/dist/web/1_advanced/4_custom_resolution";
import { setup } from "../../support/setup";

describe(
Expand Down
11 changes: 0 additions & 11 deletions bindings/wasm/cypress/e2e/1_advanced/4_key_exchange.cy.js

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { domainLinkage } from "../../../examples/dist/web/1_advanced/6_domain_linkage";
import { domainLinkage } from "../../../examples/dist/web/1_advanced/5_domain_linkage";
import { setup } from "../../support/setup";

describe(
Expand Down
64 changes: 0 additions & 64 deletions bindings/wasm/docs/api-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -5238,9 +5238,6 @@ The resolver will only be able to resolve DID documents for methods it has been

* [Resolver](#Resolver)
* [new Resolver(config)](#new_Resolver_new)
* [.resolvePresentationIssuers(presentation)](#Resolver+resolvePresentationIssuers) ⇒ <code>Promise.&lt;Array.&lt;(CoreDocument\|IToCoreDocument)&gt;&gt;</code>
* [.resolvePresentationHolder(presentation)](#Resolver+resolvePresentationHolder) ⇒ <code>Promise.&lt;(CoreDocument\|IToCoreDocument)&gt;</code>
* [.verifyPresentation(presentation, options, fail_fast, holder, issuers)](#Resolver+verifyPresentation) ⇒ <code>Promise.&lt;void&gt;</code>
* [.resolve(did)](#Resolver+resolve) ⇒ <code>Promise.&lt;(CoreDocument\|IToCoreDocument)&gt;</code>

<a name="new_Resolver_new"></a>
Expand All @@ -5257,67 +5254,6 @@ will throw an error because the handler for the "iota" method then becomes ambig
| --- | --- |
| config | <code>ResolverConfig</code> |

<a name="Resolver+resolvePresentationIssuers"></a>

### resolver.resolvePresentationIssuers(presentation) ⇒ <code>Promise.&lt;Array.&lt;(CoreDocument\|IToCoreDocument)&gt;&gt;</code>
Fetches all DID Documents of `Credential` issuers contained in a `Presentation`.
Issuer documents are returned in arbitrary order.

# Errors
Errors if any issuer URL cannot be parsed to a DID whose associated method is supported by this Resolver, or
resolution fails.

**Kind**: instance method of [<code>Resolver</code>](#Resolver)

| Param | Type |
| --- | --- |
| presentation | [<code>Presentation</code>](#Presentation) |

<a name="Resolver+resolvePresentationHolder"></a>

### resolver.resolvePresentationHolder(presentation) ⇒ <code>Promise.&lt;(CoreDocument\|IToCoreDocument)&gt;</code>
Fetches the DID Document of the holder of a `Presentation`.

# Errors
Errors if the holder URL is missing, cannot be parsed to a valid DID whose method is supported by the resolver, or
DID resolution fails.

**Kind**: instance method of [<code>Resolver</code>](#Resolver)

| Param | Type |
| --- | --- |
| presentation | [<code>Presentation</code>](#Presentation) |

<a name="Resolver+verifyPresentation"></a>

### resolver.verifyPresentation(presentation, options, fail_fast, holder, issuers) ⇒ <code>Promise.&lt;void&gt;</code>
Verifies a `Presentation`.

### Important
See `PresentationValidator::validate` for information about which properties get
validated and what is expected of the optional arguments `holder` and `issuer`.

### Resolution
The DID Documents for the `holder` and `issuers` are optionally resolved if not given.
If you already have up-to-date versions of these DID Documents, you may want
to use `PresentationValidator::validate`.
See also `Resolver::resolvePresentationIssuers` and `Resolver::resolvePresentationHolder`.

### Errors
Errors from resolving the holder and issuer DID Documents, if not provided, will be returned immediately.
Otherwise, errors from validating the presentation and its credentials will be returned
according to the `fail_fast` parameter.

**Kind**: instance method of [<code>Resolver</code>](#Resolver)

| Param | Type |
| --- | --- |
| presentation | [<code>Presentation</code>](#Presentation) |
| options | [<code>PresentationValidationOptions</code>](#PresentationValidationOptions) |
| fail_fast | <code>number</code> |
| holder | [<code>CoreDocument</code>](#CoreDocument) \| <code>IToCoreDocument</code> \| <code>undefined</code> |
| issuers | <code>Array.&lt;(CoreDocument\|IToCoreDocument)&gt;</code> \| <code>undefined</code> |

<a name="Resolver+resolve"></a>

### resolver.resolve(did) ⇒ <code>Promise.&lt;(CoreDocument\|IToCoreDocument)&gt;</code>
Expand Down
5 changes: 2 additions & 3 deletions bindings/wasm/examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,8 @@ The following advanced examples are available:
| [1_did_issues_nft](src/1_advanced/1_did_issues_nft.ts) | Demonstrates how an identity can issue and own NFTs, and how observers can verify the issuer of the NFT. |
| [2_nft_owns_did](src/1_advanced/2_nft_owns_did.ts) | Demonstrates how an identity can be owned by NFTs, and how observers can verify that relationship. |
| [3_did_issues_tokens](src/1_advanced/3_did_issues_tokens.ts) | Demonstrates how an identity can issue and control a Token Foundry and its tokens. |
| [4_key_exchange](src/1_advanced/4_key_exchange.ts) | Demonstrates Elliptic-curve Diffie-Hellman (ECDH) cryptographic key exchange with DID Documents. |
| [5_custom_resolution](src/1_advanced/5_custom_resolution.ts) | Demonstrates how to set up a resolver using custom handlers. |
| [6_domain_linkage](src/1_advanced/6_domain_linkage.ts) | Demonstrates how to link a domain and a DID and verify the linkage. |
| [4_custom_resolution](src/1_advanced/4_custom_resolution.ts) | Demonstrates how to set up a resolver using custom handlers. |
| [5_domain_linkage](src/1_advanced/5_domain_linkage.ts) | Demonstrates how to link a domain and a DID and verify the linkage. |

## Browser

Expand Down
18 changes: 12 additions & 6 deletions bindings/wasm/examples/src/0_basic/0_create_did.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,11 @@ import {
IotaDID,
IotaDocument,
IotaIdentityClient,
KeyPair,
KeyType,
JwkMemStore,
JwsAlgorithm,
KeyIdMemStore,
MethodScope,
VerificationMethod,
Storage,
} from "@iota/identity-wasm/node";
import { Bech32Helper, IAliasOutput } from "@iota/iota.js";
import { API_ENDPOINT, ensureAddressHasFunds } from "../util";
Expand Down Expand Up @@ -50,11 +51,16 @@ export async function createIdentity(): Promise<{
// Create a new DID document with a placeholder DID.
// The DID will be derived from the Alias Id of the Alias Output after publishing.
const document = new IotaDocument(networkHrp);
const storage: Storage = new Storage(new JwkMemStore(), new KeyIdMemStore());

// Insert a new Ed25519 verification method in the DID document.
let keypair = new KeyPair(KeyType.Ed25519);
let method = new VerificationMethod(document.id(), keypair.type(), keypair.public(), "#key-1");
document.insertMethod(method, MethodScope.VerificationMethod());
await document.generateMethod(
storage,
JwkMemStore.ed25519KeyType(),
JwsAlgorithm.EdDSA,
"#key-1",
MethodScope.VerificationMethod(),
);

// Construct an Alias Output containing the DID document, with the wallet address
// set as both the state controller and governor.
Expand Down
27 changes: 19 additions & 8 deletions bindings/wasm/examples/src/0_basic/1_update_did.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,13 @@ import { Bip39 } from "@iota/crypto.js";
import {
IotaDocument,
IotaIdentityClient,
KeyPair,
KeyType,
JwkMemStore,
JwsAlgorithm,
KeyIdMemStore,
MethodRelationship,
MethodScope,
Service,
Storage,
Timestamp,
VerificationMethod,
} from "@iota/identity-wasm/node";
Expand All @@ -31,17 +33,26 @@ export async function updateIdentity() {
};

// Creates a new wallet and identity (see "0_create_did" example).
let { document } = await createDid(client, secretManager);
const storage: Storage = new Storage(new JwkMemStore(), new KeyIdMemStore());
let { document, fragment } = await createDid(
client,
secretManager,
storage,
);
const did = document.id();

// Resolve the latest state of the document.
// Technically this is equivalent to the document above.
document = await didClient.resolveDid(did);

// Insert a new Ed25519 verification method in the DID document.
let keypair = new KeyPair(KeyType.Ed25519);
let method = new VerificationMethod(document.id(), keypair.type(), keypair.public(), "#key-2");
document.insertMethod(method, MethodScope.VerificationMethod());
await document.generateMethod(
storage,
JwkMemStore.ed25519KeyType(),
JwsAlgorithm.EdDSA,
"#key-2",
MethodScope.VerificationMethod(),
);

// Attach a new method relationship to the inserted method.
document.attachMethodRelationship(did.join("#key-2"), MethodRelationship.Authentication);
Expand All @@ -56,8 +67,8 @@ export async function updateIdentity() {
document.setMetadataUpdated(Timestamp.nowUTC());

// Remove a verification method.
let originalMethod = document.resolveMethod("key-1") as VerificationMethod;
document.removeMethod(originalMethod?.id());
let originalMethod = document.resolveMethod(fragment) as VerificationMethod;
await document.purgeMethod(storage, originalMethod?.id());

// Resolve the latest output and update it with the given document.
const aliasOutput: IAliasOutput = await didClient.updateDidOutput(document);
Expand Down
11 changes: 8 additions & 3 deletions bindings/wasm/examples/src/0_basic/2_resolve_did.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
// Copyright 2020-2022 IOTA Stiftung
// Copyright 2020-2023 IOTA Stiftung
// SPDX-License-Identifier: Apache-2.0

import { Client, MnemonicSecretManager } from "@iota/client-wasm/node";
import { Bip39 } from "@iota/crypto.js";
import { IotaDocument, IotaIdentityClient } from "@iota/identity-wasm/node";
import { IotaDocument, IotaIdentityClient, JwkMemStore, KeyIdMemStore, Storage } from "@iota/identity-wasm/node";
import type { IAliasOutput } from "@iota/iota.js";
import { API_ENDPOINT, createDid } from "../util";

Expand All @@ -21,7 +21,12 @@ export async function resolveIdentity() {
};

// Creates a new wallet and identity (see "0_create_did" example).
const { document } = await createDid(client, secretManager);
const storage: Storage = new Storage(new JwkMemStore(), new KeyIdMemStore());
let { document } = await createDid(
client,
secretManager,
storage,
);
const did = document.id();

// Resolve the associated Alias Output and extract the DID document from it.
Expand Down
11 changes: 8 additions & 3 deletions bindings/wasm/examples/src/0_basic/3_deactivate_did.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
// Copyright 2020-2022 IOTA Stiftung
// Copyright 2020-2023 IOTA Stiftung
// SPDX-License-Identifier: Apache-2.0

import { Client, MnemonicSecretManager } from "@iota/client-wasm/node";
import { Bip39 } from "@iota/crypto.js";
import { IotaDocument, IotaIdentityClient } from "@iota/identity-wasm/node";
import { IotaDocument, IotaIdentityClient, JwkMemStore, KeyIdMemStore, Storage } from "@iota/identity-wasm/node";
import { IAliasOutput, IRent, TransactionHelper } from "@iota/iota.js";
import { API_ENDPOINT, createDid } from "../util";

Expand All @@ -21,7 +21,12 @@ export async function deactivateIdentity() {
};

// Creates a new wallet and identity (see "0_create_did" example).
let { document } = await createDid(client, secretManager);
const storage: Storage = new Storage(new JwkMemStore(), new KeyIdMemStore());
let { document } = await createDid(
client,
secretManager,
storage,
);
const did = document.id();

// Resolve the latest state of the DID document, so we can reactivate it later.
Expand Down
12 changes: 9 additions & 3 deletions bindings/wasm/examples/src/0_basic/4_delete_did.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
// Copyright 2020-2022 IOTA Stiftung
// Copyright 2020-2023 IOTA Stiftung
// SPDX-License-Identifier: Apache-2.0

import { Client, MnemonicSecretManager } from "@iota/client-wasm/node";
import { Bip39 } from "@iota/crypto.js";
import { IotaIdentityClient } from "@iota/identity-wasm/node";
import { IotaIdentityClient, JwkMemStore, KeyIdMemStore, Storage } from "@iota/identity-wasm/node";
import { API_ENDPOINT, createDid } from "../util";

/** Demonstrates how to delete a DID in an Alias Output, reclaiming the storage deposit. */
Expand All @@ -20,7 +20,13 @@ export async function deleteIdentity() {
};

// Creates a new wallet and identity (see "0_create_did" example).
const { address, document } = await createDid(client, secretManager);
// const { address, document } = await createDid(client, secretManager);
const storage: Storage = new Storage(new JwkMemStore(), new KeyIdMemStore());
let { address, document } = await createDid(
client,
secretManager,
storage,
);
const did = document.id();

// Deletes the Alias Output and its contained DID Document, rendering the DID permanently destroyed.
Expand Down
47 changes: 35 additions & 12 deletions bindings/wasm/examples/src/0_basic/5_create_vc.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
// Copyright 2020-2022 IOTA Stiftung
// Copyright 2020-2023 IOTA Stiftung
// SPDX-License-Identifier: Apache-2.0

import { Client, MnemonicSecretManager } from "@iota/client-wasm/node";
import { Bip39 } from "@iota/crypto.js";
import {
Credential,
CredentialValidationOptions,
CredentialValidator,
FailFast,
ProofOptions,
JwkMemStore,
JwsSignatureOptions,
JwtCredentialValidationOptions,
JwtCredentialValidator,
KeyIdMemStore,
Storage,
} from "@iota/identity-wasm/node";
import { API_ENDPOINT, createDid } from "../util";

Expand All @@ -30,10 +33,20 @@ export async function createVC() {
};

// Create an identity for the issuer with one verification method `key-1`.
const { document: issuerDocument, keypair: keypairIssuer } = await createDid(client, secretManager);
const issuerStorage: Storage = new Storage(new JwkMemStore(), new KeyIdMemStore());
let { document: issuerDocument, fragment: issuerFragment } = await createDid(
client,
secretManager,
issuerStorage,
);

// Create an identity for the holder, in this case also the subject.
const { document: aliceDocument } = await createDid(client, secretManager);
const aliceStorage: Storage = new Storage(new JwkMemStore(), new KeyIdMemStore());
let { document: aliceDocument } = await createDid(
client,
secretManager,
aliceStorage,
);

// Create a credential subject indicating the degree earned by Alice, linked to their DID.
const subject = {
Expand All @@ -52,22 +65,32 @@ export async function createVC() {
credentialSubject: subject,
});

// Sign Credential.
let signedVc = issuerDocument.signCredential(unsignedVc, keypairIssuer.private(), "#key-1", ProofOptions.default());
// Create signed JWT credential.
const credentialJwt = await issuerDocument.createCredentialJwt(
issuerStorage,
issuerFragment,
unsignedVc,
new JwsSignatureOptions(),
);
console.log(`Credential JWT > ${credentialJwt.toString()}`);

// Before sending this credential to the holder the issuer wants to validate that some properties
// of the credential satisfy their expectations.

// Validate the credential's signature, the credential's semantic structure,
// check that the issuance date is not in the future and that the expiration date is not in the past.
CredentialValidator.validate(signedVc, issuerDocument, CredentialValidationOptions.default(), FailFast.AllErrors);
// Note that the validation returns an object containing the decoded credential.
const decoded_credential = new JwtCredentialValidator().validate(
credentialJwt,
issuerDocument,
new JwtCredentialValidationOptions({}),
FailFast.FirstError,
);

// Since `validate` did not throw any errors we know that the credential was successfully validated.
console.log(`VC successfully validated`);

// The issuer is now sure that the credential they are about to issue satisfies their expectations.
// The credential is then serialized to JSON and transmitted to the holder in a secure manner.
// Note that the credential is NOT published to the IOTA Tangle. It is sent and stored off-chain.
const credentialJSON = signedVc.toJSON();
console.log(`Issued credential: ${JSON.stringify(credentialJSON, null, 2)}`);
console.log(`Issued credential: ${JSON.stringify(decoded_credential.intoCredential(), null, 2)}`);
}
Loading

0 comments on commit fcfe4e7

Please sign in to comment.