Skip to content
This repository has been archived by the owner on Dec 12, 2024. It is now read-only.

Commit

Permalink
Identity Agent Guide (#1149)
Browse files Browse the repository at this point in the history
* initial guide; code snippets and tests need to be added

* update wording

* move to dwn

* put apps back to 4th position

* typo

* updating based on review

* linking agents guide

* Update site/docs/web5/build/decentralized-web-nodes/using-identity-agents.mdx

Co-authored-by: Angie Jones <[email protected]>

* passphrase update; users can use whatever they want

* Update site/docs/web5/build/decentralized-web-nodes/using-identity-agents.mdx

Co-authored-by: Frank Hinek <[email protected]>

* using identity agent wrapper instead

* update test descriptions

* more details in guide

* adding for more clarity

* capitalization

* fix typo

* remove unnecessary wording

* combine create identities code snippet

* agent tests

* how the agent connects to web5

* pinning version

* updating lock file to match packagejson

* Update site/code-snippets/web5/build/decentralized-web-nodes/use-identity-agents.js

Co-authored-by: Angie Jones <[email protected]>

* Update site/docs/web5/build/decentralized-web-nodes/using-identity-agents.mdx

Co-authored-by: Angie Jones <[email protected]>

* separate apps

* Update site/docs/web5/build/decentralized-web-nodes/using-identity-agents.mdx

Co-authored-by: Angie Jones <[email protected]>

* bolding the word separate to emphasize separate apps

* italic to bold

* Update site/docs/web5/build/decentralized-web-nodes/using-identity-agents.mdx

Co-authored-by: Angie Jones <[email protected]>

* Update site/docs/web5/build/decentralized-web-nodes/using-identity-agents.mdx

Co-authored-by: Angie Jones <[email protected]>

* connectToWeb5 snippet

---------

Co-authored-by: Angie Jones <[email protected]>
Co-authored-by: Frank Hinek <[email protected]>
  • Loading branch information
3 people authored Jan 19, 2024
1 parent 9af59ee commit 53da9fc
Show file tree
Hide file tree
Showing 6 changed files with 203 additions and 0 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
"@web5/api": "0.8.4",
"@web5/credentials": "0.4.1",
"@web5/dids": "0.2.3",
"@web5/identity-agent": "0.2.5",
"font-awesome": "4.7.0",
"googleapis": "128.0.0",
"node-fetch": "3.3.2",
Expand Down
21 changes: 21 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { test, expect, describe } from 'vitest';
import {
getDwnEndpoints,
} from '../../../../code-snippets/web5/build/decentralized-web-nodes/use-identity-agents';

let agent;

describe('create identity agent', () => {
// TO DO: add more tests for each code snippets after the team determines how to conditionally run tests for Web5.connect() vs. the Identity Agent
test('createDidOptions returns an object with cryptographic keys and service endpoints', async () => {
const didOptions = await getDwnEndpoints();

expect(didOptions).toHaveProperty('keySet.verificationMethodKeys');
expect(Array.isArray(didOptions.keySet.verificationMethodKeys)).toBe(true);
expect(didOptions).toHaveProperty('services');
expect(Array.isArray(didOptions.services)).toBe(true);
didOptions.services.forEach(service => {
expect(service).toHaveProperty('id');
expect(service).toHaveProperty('serviceEndpoint');
expect(service).toHaveProperty('type');
expect(service.type).toBe('DecentralizedWebNode');
});
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import { IdentityAgent } from '@web5/identity-agent';
import { getTechPreviewDwnEndpoints } from '@web5/api';
import { DidIonMethod } from '@web5/dids';


export async function createIdentityAgent() {
const agent = await IdentityAgent.create();
return agent;
}

export async function authenticateIdentityAgent(agent) {
await agent.start({ passphrase: 'default-passphrase' });
return agent.agentDid;
}

export async function getDwnEndpoints() {
// selects DWN endpoints that are provided by default during the Web5 tech preview period
const serviceEndpointNodes = await getTechPreviewDwnEndpoints();

// generates key pairs used for authorization and encryption when interfacing with DWNs
const didOptions = await DidIonMethod.generateDwnOptions({ serviceEndpointNodes });
return didOptions;
}

export async function createSocialMediaAndCareerIdentity() {
const socialMediaIdentity = await agent.identityManager.create({
name: 'SocialMedia',
didMethod: 'ion',
didOptions,
kms: 'local'
});

const careerIdentity = await agent.identityManager.create({
name: 'Career',
didMethod: 'ion',
didOptions,
kms: 'local'
});

return { socialMediaIdentity, careerIdentity };
}

export async function connectIdentityToWeb5() {
const { web5 } = await Web5.connect({
connectedDid: socialMediaIdentity.did,
agent,
});
return web5;
}

export async function connectToWeb5() {
const { web5 } = await Web5.connect({
connectedDid: socialIdentity.did,
agent,
});
return web5;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
---
sidebar_position: 9
---

import CodeSnippet from '@site/src/components/CodeSnippet';

# Using Identity Agents

Identity Agents are a specialized type of [agent](https://developer.tbd.website/docs/web5/learn/agents/) that act as personal identity managers. Similar to how a password manager securely stores login credentials for different web apps, Identity Agents manage your [DIDs](https://developer.tbd.website/docs/web5/learn/decentralized-identifiers).

By default, the `Web5.connect()` function generates a **new** identity; however, Identity Agents allow you to connect to a Web5 app with an **existing** identity. This is useful for maintaining a cohesive online presence.

This guide will walk you through creating an Identity Agent as a standalone application to manage multiple user identities and connect to a **separate** Web5 application.


<details>
<summary>Prerequisites</summary>

**Install the following packages**

```bash
npm i @web5/dids @web5/identity-agent @web5/api
```

**Import the following modules**

```js
import { DidIonMethod } from '@web5/dids';
import { IdentityAgent } from '@web5/identity-agent';
import { Web5, getTechPreviewDwnEndpoints } from '@web5/api';
```

</details>

## Initialize the Agent
To create an Identity Agent, start by creating an instance of the `IdentityAgent`.

<CodeSnippet functionName="createIdentityAgent" />

## Prompt Users to Authenticate
In your Identity Agent app, include the code snippet below to prompt users to authenticate with a one-time passphrase for security purposes.

<CodeSnippet functionName="authenticateIdentityAgent" />

## Connect DIDs to DWNs
To add [DWNs](https://developer.tbd.website/docs/web5/learn/decentralized-web-nodes/) as service endpoints to the DIDs that will be managed by the Identity Agent, you can add the endpoints as `didOptions`.

Below is an example using TBD-hosted DWN endpoints:

<CodeSnippet functionName="getDwnEndpoints" />


<details>
<summary>Expected Output of didOptions</summary>

```js
{
keySet: { verificationMethodKeys: [ [Object], [Object] ] },
services: [
{
id: '#dwn',
serviceEndpoint: [Object],
type: 'DecentralizedWebNode'
}
]
}
```

</details>

## Create Identities
Now that `didOptions` contains cryptographic key pairs and service endpoints, you can create as many identities as necessary.

Each identity, linked to a unique DID, represents and compartmentalizes different aspects of a user. For example, a user can have an identity for social media interactions and another for professional engagements.

<CodeSnippet functionName="createSocialMediaAndCareerIdentity" />

:::note
* The `name` field serves as a friendly name for reference.
* The `kms` field stands for [Key Management Service](/docs/web5/build/decentralized-identifiers/key-management) and can securely store and manage the cryptographic keys associated with a DID. If you don't specify a particular key management service, such as AWS Key Management Service, Web5 will default to an in-memory key manager.
:::

## Use your Identity in a Web5 Application
Once your Identity Agent is set up to manage multiple identities, you can use it to help you login to a Web5 application. Here's the typical workflow:

1. The Web5 application may display a QR code or a deep link for login purposes.
2. Use the Identity Agent to scan the QR code or click the deep link to establish a connection between your Identity Agent and the Web5 application.
3. The Identity Agent then prompts you to select the identity you prefer to use for authentication.

## Connect to Web5
Finally, the Web5 application can use the DID linked to your identity, so that you can interact within the Web5 application as your chosen identity.

<CodeSnippet functionName="connectToWeb5" />

6 changes: 6 additions & 0 deletions site/src/util/code-snippets-map.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,12 @@
"sendProtocolToRemoteDWNs": "const { protocol } = await web5.dwn.protocols.configure({\n message: {\n definition: protocolDefinition\n }\n});\n\n//immediately send protocol to user's remote DWNs\nconst {status} = await protocol.send(userDid);",
"sendRecordToDWNOfRecipient": "const { record } = await web5.dwn.records.create({\n data: \"this record will be created but not saved to DWN\",\n store: false, //remove this line if you want to keep a copy of the record in the sender's DWN\n message: {\n dataFormat: 'text/plain'\n },\n});\n\n//send record to recipient's DWN\nconst {status} = await record.send(recipientDid);",
"updateDwnRecord": "// Get the record\nconst { record } = await web5.dwn.records.read({\n message: {\n filter: {\n recordId: createdRecord.id\n }\n }\n});\n\n// Update the record\n// highlight-next-line\nconst {status} = await record.update({ data: \"Hello, I'm updated!\" });",
"createIdentityAgent": "const agent = await IdentityAgent.create();",
"authenticateIdentityAgent": "await agent.start({ passphrase: 'default-passphrase' });",
"getDwnEndpoints": "// selects DWN endpoints that are provided by default during the Web5 tech preview period\nconst serviceEndpointNodes = await getTechPreviewDwnEndpoints();\n\n// generates key pairs used for authorization and encryption when interfacing with DWNs\nconst didOptions = await DidIonMethod.generateDwnOptions({ serviceEndpointNodes });",
"createSocialMediaAndCareerIdentity": "const socialMediaIdentity = await agent.identityManager.create({\n name: 'SocialMedia',\n didMethod: 'ion',\n didOptions,\n kms: 'local'\n });\n\n const careerIdentity = await agent.identityManager.create({\n name: 'Career',\n didMethod: 'ion',\n didOptions,\n kms: 'local'\n });",
"connectIdentityToWeb5": "const { web5 } = await Web5.connect({\n connectedDid: socialMediaIdentity.did,\n agent,\n });",
"connectToWeb5": "const { web5 } = await Web5.connect({\n connectedDid: socialIdentity.did,\n agent,\n });",
"createTextRecord": "const { record } = await web5.dwn.records.create({\n data: 'Hello, Web5!',\n message: {\n dataFormat: 'text/plain',\n },\n });",
"createJsonRecord": "// Create a JSON record\nconst { record } = await web5.dwn.records.create({\n data: {\n content: \"Hello Web5\",\n description: \"Keep Building!\"\n },\n message: {\n dataFormat: 'application/json'\n }\n});",
"uploadImage": "// Create a blob record\n async function upload(event) {\n const blob = new Blob(event.currentTarget.files, { type: \"image/png\" });\n const { record } = await web5.dwn.records.create({\n data: blob,\n message: {\n dataFormat: \"image/png\"\n }\n });\n \n }",
Expand Down

0 comments on commit 53da9fc

Please sign in to comment.