From 0155389bf8ad3cfe6f4802d1ac5ce655321423c6 Mon Sep 17 00:00:00 2001 From: Simonas Karuzas Date: Thu, 9 Jul 2020 12:19:28 +0300 Subject: [PATCH] feat: Method identityManagerGetOrCreateIdentity --- __tests__/graphqlAgent.test.ts | 6 + __tests__/localAgent.test.ts | 6 + __tests__/restAgent.test.ts | 6 + __tests__/shared/webDidFlow.ts | 118 ++++++++++ .../abstract/abstract-identity-provider.ts | 2 +- .../src/abstract/abstract-identity-store.ts | 3 +- packages/daf-core/src/identity-manager.ts | 20 +- packages/daf-core/src/key-manager.ts | 3 + .../daf-ethr-did/src/identity-provider.ts | 2 +- packages/daf-graphql/src/base-type-def.ts | 17 ++ .../src/methods/identity-manager.ts | 71 +++++++ packages/daf-rest/src/methods.ts | 1 + packages/daf-typeorm/src/entities/identity.ts | 2 +- .../src/identity/identity-store.ts | 35 ++- packages/daf-web-did/LICENSE | 201 ++++++++++++++++++ packages/daf-web-did/README.md | 1 + packages/daf-web-did/api-extractor.json | 5 + packages/daf-web-did/package.json | 29 +++ packages/daf-web-did/src/identity-provider.ts | 65 ++++++ packages/daf-web-did/src/index.ts | 1 + packages/daf-web-did/tsconfig.json | 9 + packages/tsconfig.json | 1 + 22 files changed, 592 insertions(+), 12 deletions(-) create mode 100644 __tests__/shared/webDidFlow.ts create mode 100644 packages/daf-web-did/LICENSE create mode 100644 packages/daf-web-did/README.md create mode 100644 packages/daf-web-did/api-extractor.json create mode 100644 packages/daf-web-did/package.json create mode 100644 packages/daf-web-did/src/identity-provider.ts create mode 100644 packages/daf-web-did/src/index.ts create mode 100644 packages/daf-web-did/tsconfig.json diff --git a/__tests__/graphqlAgent.test.ts b/__tests__/graphqlAgent.test.ts index 3d3821390..926dfbf1d 100644 --- a/__tests__/graphqlAgent.test.ts +++ b/__tests__/graphqlAgent.test.ts @@ -18,6 +18,7 @@ import { DafResolver } from 'daf-resolver' import { JwtMessageHandler } from 'daf-did-jwt' import { W3c, IW3c, W3cMessageHandler } from 'daf-w3c' import { EthrIdentityProvider } from 'daf-ethr-did' +import { WebIdentityProvider } from 'daf-web-did' import { DIDComm, DIDCommMessageHandler, ISendMessageDIDCommAlpha1 } from 'daf-did-comm' import { Sdr, ISdr, SdrMessageHandler } from 'daf-selective-disclosure' import { KeyManagementSystem, SecretBox } from 'daf-libsodium' @@ -32,6 +33,7 @@ import fs from 'fs' import createVerifiableCredential from './shared/createVerifiableCredential' import handleSdrMessage from './shared/handleSdrMessage' import resolveDid from './shared/resolveDid' +import webDidFlow from './shared/webDidFlow' const databaseFile = 'graphql-database.sqlite' const infuraProjectId = '5ffc47f65c4042ce847ef66a3fa70d4c' @@ -90,6 +92,9 @@ const setup = async (): Promise => { gas: 1000001, ttl: 60 * 60 * 24 * 30 * 12 + 1, }), + 'did:web': new WebIdentityProvider({ + defaultKms: 'local', + }), }, }), new DafResolver({ infuraProjectId }), @@ -144,4 +149,5 @@ describe('GraphQL integration tests', () => { createVerifiableCredential(testContext) handleSdrMessage(testContext) resolveDid(testContext) + webDidFlow(testContext) }) diff --git a/__tests__/localAgent.test.ts b/__tests__/localAgent.test.ts index aa44d23d3..4aff37a08 100644 --- a/__tests__/localAgent.test.ts +++ b/__tests__/localAgent.test.ts @@ -15,6 +15,7 @@ import { DafResolver } from 'daf-resolver' import { JwtMessageHandler } from 'daf-did-jwt' import { W3c, IW3c, W3cMessageHandler } from 'daf-w3c' import { EthrIdentityProvider } from 'daf-ethr-did' +import { WebIdentityProvider } from 'daf-web-did' import { DIDComm, DIDCommMessageHandler, ISendMessageDIDCommAlpha1 } from 'daf-did-comm' import { Sdr, ISdr, SdrMessageHandler } from 'daf-selective-disclosure' import { KeyManagementSystem, SecretBox } from 'daf-libsodium' @@ -25,6 +26,7 @@ import fs from 'fs' import createVerifiableCredential from './shared/createVerifiableCredential' import handleSdrMessage from './shared/handleSdrMessage' import resolveDid from './shared/resolveDid' +import webDidFlow from './shared/webDidFlow' const databaseFile = 'local-database.sqlite' const infuraProjectId = '5ffc47f65c4042ce847ef66a3fa70d4c' @@ -84,6 +86,9 @@ const setup = async (): Promise => { gas: 1000001, ttl: 60 * 60 * 24 * 30 * 12 + 1, }), + 'did:web': new WebIdentityProvider({ + defaultKms: 'local', + }), }, }), new DafResolver({ infuraProjectId }), @@ -119,4 +124,5 @@ describe('Local integration tests', () => { createVerifiableCredential(testContext) handleSdrMessage(testContext) resolveDid(testContext) + webDidFlow(testContext) }) diff --git a/__tests__/restAgent.test.ts b/__tests__/restAgent.test.ts index ce062981c..81279f25e 100644 --- a/__tests__/restAgent.test.ts +++ b/__tests__/restAgent.test.ts @@ -18,6 +18,7 @@ import { DafResolver } from 'daf-resolver' import { JwtMessageHandler } from 'daf-did-jwt' import { W3c, IW3c, W3cMessageHandler } from 'daf-w3c' import { EthrIdentityProvider } from 'daf-ethr-did' +import { WebIdentityProvider } from 'daf-web-did' import { DIDComm, DIDCommMessageHandler, ISendMessageDIDCommAlpha1 } from 'daf-did-comm' import { Sdr, ISdr, SdrMessageHandler } from 'daf-selective-disclosure' import { KeyManagementSystem, SecretBox } from 'daf-libsodium' @@ -32,6 +33,7 @@ import fs from 'fs' import createVerifiableCredential from './shared/createVerifiableCredential' import handleSdrMessage from './shared/handleSdrMessage' import resolveDid from './shared/resolveDid' +import webDidFlow from './shared/webDidFlow' const databaseFile = 'rest-database.sqlite' const infuraProjectId = '5ffc47f65c4042ce847ef66a3fa70d4c' @@ -90,6 +92,9 @@ const setup = async (): Promise => { gas: 1000001, ttl: 60 * 60 * 24 * 30 * 12 + 1, }), + 'did:web': new WebIdentityProvider({ + defaultKms: 'local', + }), }, }), new DafResolver({ infuraProjectId }), @@ -138,4 +143,5 @@ describe('REST integration tests', () => { createVerifiableCredential(testContext) handleSdrMessage(testContext) resolveDid(testContext) + webDidFlow(testContext) }) diff --git a/__tests__/shared/webDidFlow.ts b/__tests__/shared/webDidFlow.ts new file mode 100644 index 000000000..74387e989 --- /dev/null +++ b/__tests__/shared/webDidFlow.ts @@ -0,0 +1,118 @@ +import { TAgent, IIdentityManager, IIdentity, IKey } from 'daf-core' +import { IW3c } from 'daf-w3c' + +type ConfiguredAgent = TAgent + +export default (testContext: { + getAgent: () => ConfiguredAgent + setup: () => Promise + tearDown: () => Promise +}) => { + describe('web did flow', () => { + let agent: ConfiguredAgent + let serviceIdentity: IIdentity + let serviceIdentityKey: IKey + let alice: IIdentity + let bob: IIdentity + + beforeAll(() => { + testContext.setup() + agent = testContext.getAgent() + }) + afterAll(testContext.tearDown) + + it('should create service identity', async () => { + serviceIdentity = await agent.identityManagerGetOrCreateIdentity({ + provider: 'did:web', + alias: 'example.com', + }) + + expect(serviceIdentity.provider).toEqual('did:web') + expect(serviceIdentity.alias).toEqual('example.com') + expect(serviceIdentity.did).toEqual('did:web:example.com') + serviceIdentityKey = serviceIdentity.keys[0] + }) + + it('should get existing service identity', async () => { + const testIdentity = await agent.identityManagerGetOrCreateIdentity({ + provider: 'did:web', + alias: 'example.com', + }) + + expect(testIdentity.keys[0]).toEqual(serviceIdentityKey) + expect(testIdentity.provider).toEqual('did:web') + expect(testIdentity.alias).toEqual('example.com') + expect(testIdentity.did).toEqual('did:web:example.com') + }) + + it('should create identity with alias: alice', async () => { + alice = await agent.identityManagerGetOrCreateIdentity({ + alias: 'alice', + }) + + expect(alice.provider).toEqual('did:ethr:rinkeby') + expect(alice.alias).toEqual('alice') + expect(alice.did).toBeDefined() + }) + + it('should create identity with alias: bob', async () => { + bob = await agent.identityManagerGetOrCreateIdentity({ + alias: 'bob', + }) + + expect(bob.provider).toEqual('did:ethr:rinkeby') + expect(bob.alias).toEqual('bob') + expect(bob.did).toBeDefined() + }) + + describe('should create verifiable credential', () => { + it('issuer: serviceIdentity', async () => { + const verifiableCredential = await agent.createVerifiableCredential({ + credential: { + issuer: { id: serviceIdentity.did }, + '@context': ['https://www.w3.org/2018/credentials/v1'], + type: ['VerifiableCredential'], + issuanceDate: new Date().toISOString(), + credentialSubject: { + id: alice.did, + name: 'Alice', + }, + }, + proofFormat: 'jwt', + }) + + expect(verifiableCredential.issuer).toEqual({ id: serviceIdentity.did }) + expect(verifiableCredential.credentialSubject).toEqual({ id: alice.did, name: 'Alice' }) + expect(verifiableCredential).toHaveProperty('proof.jwt') + }) + + it('issuer - Alice, subject - Bob', async () => { + const a = await agent.identityManagerGetOrCreateIdentity({ + alias: 'alice', + }) + + const b = await agent.identityManagerGetOrCreateIdentity({ + alias: 'bob', + }) + + const verifiableCredential = await agent.createVerifiableCredential({ + credential: { + issuer: { id: a.did }, + '@context': ['https://www.w3.org/2018/credentials/v1'], + type: ['VerifiableCredential'], + issuanceDate: new Date().toISOString(), + credentialSubject: { + id: b.did, + name: 'Bob', + }, + }, + proofFormat: 'jwt', + }) + + expect(verifiableCredential.issuer).toEqual({ id: alice.did }) + expect(verifiableCredential.credentialSubject).toEqual({ id: bob.did, name: 'Bob' }) + expect(verifiableCredential).toHaveProperty('proof.jwt') + }) + }) + }) +} diff --git a/packages/daf-core/src/abstract/abstract-identity-provider.ts b/packages/daf-core/src/abstract/abstract-identity-provider.ts index 587e34c01..4fa32181b 100644 --- a/packages/daf-core/src/abstract/abstract-identity-provider.ts +++ b/packages/daf-core/src/abstract/abstract-identity-provider.ts @@ -6,7 +6,7 @@ import { IKeyManager } from '../key-manager' */ export abstract class AbstractIdentityProvider { abstract createIdentity( - args: { kms?: string; options?: any }, + args: { kms?: string; alias?: string; options?: any }, context: IAgentContext, ): Promise> abstract deleteIdentity(args: IIdentity, context: IAgentContext): Promise diff --git a/packages/daf-core/src/abstract/abstract-identity-store.ts b/packages/daf-core/src/abstract/abstract-identity-store.ts index 1b199ffe9..d6fa07eb4 100644 --- a/packages/daf-core/src/abstract/abstract-identity-store.ts +++ b/packages/daf-core/src/abstract/abstract-identity-store.ts @@ -2,7 +2,8 @@ import { IIdentity } from '../types' export abstract class AbstractIdentityStore { abstract import(args: IIdentity): Promise - abstract get(args: { did?: string; alias?: string }): Promise + abstract get(args: { did: string }): Promise + abstract get(args: { alias: string }): Promise abstract delete(args: { did: string }): Promise abstract list(): Promise } diff --git a/packages/daf-core/src/identity-manager.ts b/packages/daf-core/src/identity-manager.ts index ce4c254db..33cb8cccd 100644 --- a/packages/daf-core/src/identity-manager.ts +++ b/packages/daf-core/src/identity-manager.ts @@ -16,7 +16,10 @@ export interface IIdentityManager extends IPluginMethodMap { }, context: IAgentContext, ) => Promise - // identityManagerGetOrCreateIdentity?: (args: { alias: string, provider?: string, kms?: string, options?: any}) => Promise + identityManagerGetOrCreateIdentity: ( + args: { alias: string; provider?: string; kms?: string; options?: any }, + context: IAgentContext, + ) => Promise identityManagerImportIdentity: (args: IIdentity) => Promise identityManagerDeleteIdentity: ( args: { did: string }, @@ -59,6 +62,7 @@ export class IdentityManager implements IAgentPlugin { identityManagerGetIdentities: this.identityManagerGetIdentities.bind(this), identityManagerGetIdentity: this.identityManagerGetIdentity.bind(this), identityManagerCreateIdentity: this.identityManagerCreateIdentity.bind(this), + identityManagerGetOrCreateIdentity: this.identityManagerGetOrCreateIdentity.bind(this), identityManagerImportIdentity: this.identityManagerImportIdentity.bind(this), identityManagerDeleteIdentity: this.identityManagerDeleteIdentity.bind(this), identityManagerAddKey: this.identityManagerAddKey.bind(this), @@ -92,12 +96,24 @@ export class IdentityManager implements IAgentPlugin { ): Promise { const providerName = provider || this.defaultProvider const identityProvider = this.getProvider(providerName) - const partialIdentity = await identityProvider.createIdentity({ kms, options }, context) + const partialIdentity = await identityProvider.createIdentity({ kms, alias, options }, context) const identity: IIdentity = { ...partialIdentity, alias, provider: providerName } await this.store.import(identity) return identity } + async identityManagerGetOrCreateIdentity( + { provider, alias, kms, options }: { alias: string; provider?: string; kms?: string; options?: any }, + context: IAgentContext, + ): Promise { + try { + const identity = await this.store.get({ alias }) + return identity + } catch { + return this.identityManagerCreateIdentity({ provider, alias, kms, options }, context) + } + } + async identityManagerImportIdentity(identity: IIdentity): Promise { await this.store.import(identity) return identity diff --git a/packages/daf-core/src/key-manager.ts b/packages/daf-core/src/key-manager.ts index c2d178493..1dbf56528 100644 --- a/packages/daf-core/src/key-manager.ts +++ b/packages/daf-core/src/key-manager.ts @@ -47,6 +47,9 @@ export class KeyManager implements IAgentPlugin { const partialKey = await kms.createKey({ type: args.type, meta: args.meta }) const key: IKey = { ...partialKey, kms: args.kms } await this.store.import(key) + if (key.privateKeyHex) { + delete key.privateKeyHex + } return key } diff --git a/packages/daf-ethr-did/src/identity-provider.ts b/packages/daf-ethr-did/src/identity-provider.ts index eac6ecc9f..3f9f69890 100644 --- a/packages/daf-ethr-did/src/identity-provider.ts +++ b/packages/daf-ethr-did/src/identity-provider.ts @@ -42,7 +42,7 @@ export class EthrIdentityProvider extends AbstractIdentityProvider { } async createIdentity( - { kms, options }: { kms: string; options?: any }, + { kms, options }: { kms?: string; options?: any }, context: IContext, ): Promise> { const key = await context.agent.keyManagerCreateKey({ kms: kms || this.defaultKms, type: 'Secp256k1' }) diff --git a/packages/daf-graphql/src/base-type-def.ts b/packages/daf-graphql/src/base-type-def.ts index 85deda2d7..76232ef26 100644 --- a/packages/daf-graphql/src/base-type-def.ts +++ b/packages/daf-graphql/src/base-type-def.ts @@ -2,9 +2,26 @@ export const baseTypeDef = ` type Query type Mutation +type Key { + kid: String! + kms: String! + type: String! + publicKeyHex: String +} + +type Service { + id: String! + type: String! + serviceEndpoint: String! + description: String +} + type Identity { did: String! provider: String + alias: String + keys: [Key] + services: [Service] } scalar Object diff --git a/packages/daf-graphql/src/methods/identity-manager.ts b/packages/daf-graphql/src/methods/identity-manager.ts index bc4ee7ab1..f20fbf35d 100644 --- a/packages/daf-graphql/src/methods/identity-manager.ts +++ b/packages/daf-graphql/src/methods/identity-manager.ts @@ -21,6 +21,19 @@ export const identityManagerGetIdentities: IAgentGraphQLMethod = { identityManagerGetIdentities{ did provider + alias + keys { + kid + kms + type + publicKeyHex + } + services { + id + type + serviceEndpoint + description + } } } `, @@ -38,6 +51,19 @@ export const identityManagerGetIdentity: IAgentGraphQLMethod = { identityManagerGetIdentity(did: $did) { did provider + alias + keys { + kid + kms + type + publicKeyHex + } + services { + id + type + serviceEndpoint + description + } } } `, @@ -48,12 +74,56 @@ export const identityManagerGetIdentity: IAgentGraphQLMethod = { `, } +export const identityManagerGetOrCreateIdentity: IAgentGraphQLMethod = { + type: 'Mutation', + query: ` + mutation identityManagerGetOrCreateIdentity($alias: String!, $provider: String, $kms: String) { + identityManagerGetOrCreateIdentity(alias: $alias, provider: $provider, kms: $kms) { + did + provider + alias + keys { + kid + kms + type + publicKeyHex + } + services { + id + type + serviceEndpoint + description + } + } + } + `, + typeDef: ` + extend type Mutation { + identityManagerGetOrCreateIdentity(alias: String!, provider: String, kms: String): Identity! + } + `, +} + export const identityManagerCreateIdentity: IAgentGraphQLMethod = { type: 'Mutation', query: ` mutation identityManagerCreateIdentity($alias: String, $provider: String, $kms: String) { identityManagerCreateIdentity(alias: $alias, provider: $provider, kms: $kms) { did + provider + alias + keys { + kid + kms + type + publicKeyHex + } + services { + id + type + serviceEndpoint + description + } } } `, @@ -83,6 +153,7 @@ export const supportedMethods: Record = { identityManagerGetIdentities, identityManagerGetIdentity, identityManagerCreateIdentity, + identityManagerGetOrCreateIdentity, identityManagerDeleteIdentity, // TODO identityManagerImportIdentity } diff --git a/packages/daf-rest/src/methods.ts b/packages/daf-rest/src/methods.ts index 92b9b6726..7b8411fc7 100644 --- a/packages/daf-rest/src/methods.ts +++ b/packages/daf-rest/src/methods.ts @@ -19,6 +19,7 @@ export const supportedMethods: Record = { identityManagerGetIdentities: { type: 'POST', path: '/identityManagerGetIdentities' }, identityManagerGetIdentity: { type: 'POST', path: '/identityManagerGetIdentity' }, identityManagerCreateIdentity: { type: 'POST', path: '/identityManagerCreateIdentity' }, + identityManagerGetOrCreateIdentity: { type: 'POST', path: '/identityManagerGetOrCreateIdentity' }, identityManagerImportIdentity: { type: 'POST', path: '/identityManagerImportIdentity' }, identityManagerDeleteIdentity: { type: 'POST', path: '/identityManagerDeleteIdentity' }, identityManagerAddKey: { type: 'POST', path: '/identityManagerAddKey' }, diff --git a/packages/daf-typeorm/src/entities/identity.ts b/packages/daf-typeorm/src/entities/identity.ts index c3bbe413f..e5062f55b 100644 --- a/packages/daf-typeorm/src/entities/identity.ts +++ b/packages/daf-typeorm/src/entities/identity.ts @@ -28,7 +28,7 @@ export class Identity extends BaseEntity { @Column({ nullable: true }) //@ts-ignore - alias: string + alias?: string @CreateDateColumn() //@ts-ignore diff --git a/packages/daf-typeorm/src/identity/identity-store.ts b/packages/daf-typeorm/src/identity/identity-store.ts index 90d165474..cd6edd0e3 100644 --- a/packages/daf-typeorm/src/identity/identity-store.ts +++ b/packages/daf-typeorm/src/identity/identity-store.ts @@ -12,13 +12,35 @@ export class IdentityStore extends AbstractIdentityStore { super() } - async get({ did, alias }: { did: string; alias?: string }): Promise { - //TODO alias - const identity = await (await this.dbConnection) - .getRepository(Identity) - .findOne(did, { relations: ['keys', 'services'] }) + async get({ did, alias }: { did: string; alias: string }): Promise { + let where = {} + if (did !== undefined && alias === undefined) { + where = { did } + } else if (did === undefined && alias !== undefined) { + where = { alias } + } else { + throw Error('[daf:typeorm:identity-store] Get requires did or alias') + } + + const identity = await (await this.dbConnection).getRepository(Identity).findOne({ + where, + relations: ['keys', 'services'], + }) + if (!identity) throw Error('Identity not found') - return identity + return { + did: identity.did, + controllerKeyId: identity.controllerKeyId, + alias: identity.alias, + provider: identity.provider, + services: identity.services, + keys: identity.keys.map(k => ({ + kid: k.kid, + type: k.type, + kms: k.kms, + publicKeyHex: k.publicKeyHex, + })), + } } async delete({ did }: { did: string }) { @@ -35,6 +57,7 @@ export class IdentityStore extends AbstractIdentityStore { identity.did = args.did identity.controllerKeyId = args.controllerKeyId identity.provider = args.provider + identity.alias = args.alias identity.keys = [] for (const argsKey of args.keys) { diff --git a/packages/daf-web-did/LICENSE b/packages/daf-web-did/LICENSE new file mode 100644 index 000000000..261eeb9e9 --- /dev/null +++ b/packages/daf-web-did/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/packages/daf-web-did/README.md b/packages/daf-web-did/README.md new file mode 100644 index 000000000..fdc617a4f --- /dev/null +++ b/packages/daf-web-did/README.md @@ -0,0 +1 @@ +# DAF web-did modules diff --git a/packages/daf-web-did/api-extractor.json b/packages/daf-web-did/api-extractor.json new file mode 100644 index 000000000..433f2b77c --- /dev/null +++ b/packages/daf-web-did/api-extractor.json @@ -0,0 +1,5 @@ +{ + "$schema": "https://developer.microsoft.com/json-schemas/api-extractor/v7/api-extractor.schema.json", + "extends": "../../api-extractor-base.json", + "mainEntryPointFilePath": "/build/index.d.ts" +} diff --git a/packages/daf-web-did/package.json b/packages/daf-web-did/package.json new file mode 100644 index 000000000..4b9c8dc0b --- /dev/null +++ b/packages/daf-web-did/package.json @@ -0,0 +1,29 @@ +{ + "name": "daf-web-did", + "description": "DAF web-did modules", + "version": "7.0.0-beta.2", + "main": "build/index.js", + "types": "build/index.d.ts", + "scripts": { + "build": "tsc" + }, + "dependencies": { + "daf-core": "^7.0.0-beta.2", + "debug": "^4.1.1" + }, + "devDependencies": { + "@types/debug": "^4.1.5", + "typescript": "^3.8.3" + }, + "files": [ + "build/**/*", + "src/**/*", + "README.md", + "LICENSE" + ], + "repository": "git@github.com:uport-project/daf.git", + "author": "Simonas Karuzas ", + "license": "Apache-2.0", + "keywords": [], + "gitHead": "63dd12da63b2245d32379b435a7a774a56a1f019" +} diff --git a/packages/daf-web-did/src/identity-provider.ts b/packages/daf-web-did/src/identity-provider.ts new file mode 100644 index 000000000..beed789c7 --- /dev/null +++ b/packages/daf-web-did/src/identity-provider.ts @@ -0,0 +1,65 @@ +import { IIdentity, IKey, IService, IAgentContext, IKeyManager, AbstractIdentityProvider } from 'daf-core' +import Debug from 'debug' +const debug = Debug('daf:web-did:identity-provider') + +type IContext = IAgentContext + +export class WebIdentityProvider extends AbstractIdentityProvider { + private defaultKms: string + + constructor(options: { defaultKms: string }) { + super() + this.defaultKms = options.defaultKms + } + + async createIdentity( + { kms, alias }: { kms?: string; alias?: string }, + context: IContext, + ): Promise> { + const key = await context.agent.keyManagerCreateKey({ kms: kms || this.defaultKms, type: 'Secp256k1' }) + + const identity: Omit = { + did: 'did:web:' + alias, + controllerKeyId: key.kid, + keys: [key], + services: [], + } + debug('Created', identity.did) + return identity + } + + async deleteIdentity(identity: IIdentity, context: IContext): Promise { + for (const { kid } of identity.keys) { + await context.agent.keyManagerDeleteKey({ kid }) + } + return true + } + + async addKey( + { identity, key, options }: { identity: IIdentity; key: IKey; options?: any }, + context: IContext, + ): Promise { + return true + } + + async addService( + { identity, service, options }: { identity: IIdentity; service: IService; options?: any }, + context: IContext, + ): Promise { + return true + } + + async removeKey( + args: { identity: IIdentity; kid: string; options?: any }, + context: IContext, + ): Promise { + return true + } + + async removeService( + args: { identity: IIdentity; id: string; options?: any }, + context: IContext, + ): Promise { + return true + } +} diff --git a/packages/daf-web-did/src/index.ts b/packages/daf-web-did/src/index.ts new file mode 100644 index 000000000..7959f2728 --- /dev/null +++ b/packages/daf-web-did/src/index.ts @@ -0,0 +1 @@ +export { WebIdentityProvider } from './identity-provider' diff --git a/packages/daf-web-did/tsconfig.json b/packages/daf-web-did/tsconfig.json new file mode 100644 index 000000000..53e51212f --- /dev/null +++ b/packages/daf-web-did/tsconfig.json @@ -0,0 +1,9 @@ +{ + "extends": "../tsconfig.settings.json", + "compilerOptions": { + "rootDir": "src", + "outDir": "build", + "declarationDir": "build" + }, + "references": [{ "path": "../daf-core" }] +} diff --git a/packages/tsconfig.json b/packages/tsconfig.json index 995943138..4853dd5d3 100644 --- a/packages/tsconfig.json +++ b/packages/tsconfig.json @@ -13,6 +13,7 @@ { "path": "daf-selective-disclosure" }, { "path": "daf-url" }, { "path": "daf-typeorm" }, + { "path": "daf-web-did" }, { "path": "daf-w3c" } ] }