Skip to main content

Resolve an IOTA Identity

DID resolution is the process of fetching and decoding a DID Document corresponding to a given DID. The IOTA Identity framework supports resolving DID Documents that are stored on the IOTA and Shimmer networks and enables users to plug in handlers for additional methods.

This is similar to, but not to be confused with, the W3C DID Resolution specification, which defines function signatures for resolution in the context of web or REST APIs, whereas the IOTA Identity framework provides strongly-typed resolution for a better developer experience.

This functionality is primarily provided by the Resolver, which can:

Resolving an IOTA DID

The following examples demonstrate how to resolve an IOTA DID Document from its DID.

Resolver

Once the Resolver has been configured with a Client it will resolve IOTA DID Documents according to the read procedure defined in the IOTA DID Method Specification. It fetches the latest Alias Output from the network specified in the DID (see DID Format), then extracts and validates the DID Document from it.

use identity_iota::iota::IotaDID;
use identity_iota::iota::IotaDocument;
use identity_iota::resolver::Resolver;
use iota_client::Client;

#[tokio::main]
async fn main() -> anyhow::Result<()>{
// Configure a client for the Shimmer testnet "rms".
let node_url = "https://api.testnet.shimmer.network/";
let client = Client::builder()
.with_primary_node(node_url, None)?
.finish()?;

// Construct a resolver using the client.
let mut resolver = Resolver::<IotaDocument>::new();
resolver.attach_iota_handler(client);

// Parse the DID and resolve its DID Document.
let did = IotaDID::parse("did:iota:rms:0x7b48b06232b8a1e7a31c314cab1ceedb84e2e9dd2b1fae79b67eaa4595f15e47")?;
let document: IotaDocument = resolver.resolve(&did).await?;

Ok(())
}

Client

The Client can also be used directly, to resolve individual DIDs from its configured network.

use identity_iota::iota::IotaDID;
use identity_iota::iota::IotaDocument;
use identity_iota::iota::IotaIdentityClientExt;
use iota_client::Client;

#[tokio::main]
async fn main() -> anyhow::Result<()>{
// Configure a client for the Shimmer testnet "rms".
let node_url = "https://api.testnet.shimmer.network/";
let client = Client::builder()
.with_primary_node(node_url, None)?
.finish()?;

// Parse the DID and resolve its DID Document.
let did = IotaDID::parse("did:iota:rms:0x7b48b06232b8a1e7a31c314cab1ceedb84e2e9dd2b1fae79b67eaa4595f15e47")?;
let document: IotaDocument = client.resolve_did(&did).await?;
Ok(())
}

Advanced Resolver configuration

The Resolver can be configured to support many use cases by attaching custom resolution handlers. This enables the resolver to resolve multiple DID methods as well as customizing how a particular DID method (such as for instance the IOTA method) gets resolved. This feature is mainly intended to be used together with the Resolver's convenience methods for handling verifiable presentations and credentials.

Resolving multiple DID methods

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

// Use this external package to avoid implementing the entire did:key method in this example.
import * as ed25519 from "@transmute/did-key-ed25519";

/** Demonstrates how to set up a resolver using custom handlers.
*/
export async function customResolution() {
// Set up a handler for resolving Ed25519 did:key
const keyHandler = async function(didKey: string): Promise<CoreDocument> {
let document = await ed25519.resolve(
didKey,
{ accept: "application/did+ld+json" },
);
return CoreDocument.fromJSON(document.didDocument);
};

// Create a new Client to interact with the IOTA ledger.
const client = new Client({
primaryNode: API_ENDPOINT,
localPow: true,
});
const didClient = new IotaIdentityClient(client);

// Construct a Resolver capable of resolving the did:key and iota methods.
let handlerMap: Map<string, (did: string) => Promise<IotaDocument | CoreDocument>> = new Map();
handlerMap.set("key", keyHandler);

const resolver = new Resolver(
{
client: didClient,
handlers: handlerMap,
},
);

// A valid Ed25519 did:key value taken from https://w3c-ccg.github.io/did-method-key/#example-1-a-simple-ed25519-did-key-value.
const didKey = "did:key:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK";

// Generate a random mnemonic for our wallet.
const secretManager: MnemonicSecretManager = {
mnemonic: Bip39.randomMnemonic(),
};

// Creates a new wallet and identity for us to resolve (see "0_create_did" example).
const { document } = await createDid(client, secretManager);
const did = document.id();

// Resolve didKey into a DID document.
const didKeyDoc = await resolver.resolve(didKey);

// Resolve the DID we created on the IOTA ledger.
const didIotaDoc = await resolver.resolve(did.toString());

// Check that the types of the resolved documents match our expectations:

if (didKeyDoc instanceof CoreDocument) {
console.log("Resolved DID Key document:", JSON.stringify(didKeyDoc, null, 2));
} else {
throw new Error(
"the resolved document type should match the output type of keyHandler",
);
}

if (didIotaDoc instanceof IotaDocument) {
console.log("Resolved IOTA DID document:", JSON.stringify(didIotaDoc, null, 2));
} else {
throw new Error(
"the resolved document type should match IotaDocument",
);
}
}

Resolution for Verifiable Presentations

When validating verifiable presentations, it is necessary to resolve the DID Documents of the verifiable credential issuers and presentation holder to verify their signatures. Resolving the necessary DID Documents is performed automatically when verifying presentations via the Resolver (see this example).

When direct access to these DID Documents is desired, the Resolver also provides standalone methods to:

  • Resolve a presentation holder's DID Document.
  • Resolve the DID Documents of the issuers of the credentials in a verifiable presentation.
  • Resolve the issuer's DID Document for a given verifiable credential.