Skip to content

Commit

Permalink
feat: Simpler create VC/VP (#309)
Browse files Browse the repository at this point in the history
  • Loading branch information
simonas-notcat committed Dec 17, 2020
1 parent 7812e51 commit 172c908
Show file tree
Hide file tree
Showing 4 changed files with 151 additions and 15 deletions.
68 changes: 64 additions & 4 deletions __tests__/shared/verifiableData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ export default (testContext: {
const verifiableCredential = await agent.createVerifiableCredential({
credential: {
issuer: { id: identifier.did },
'@context': ['https://www.w3.org/2018/credentials/v1'],
type: ['VerifiableCredential'],
'@context': ['https://www.w3.org/2018/credentials/v1', 'https://example.com/1/2/3'],
type: ['VerifiableCredential', 'Custom'],
issuanceDate: new Date().toISOString(),
credentialSubject: {
id: 'did:web:example.com',
Expand All @@ -40,6 +40,11 @@ export default (testContext: {
})

expect(verifiableCredential).toHaveProperty('proof.jwt')
expect(verifiableCredential['@context']).toEqual([
'https://www.w3.org/2018/credentials/v1',
'https://example.com/1/2/3',
])
expect(verifiableCredential['type']).toEqual(['VerifiableCredential', 'Custom'])

const hash = await agent.dataStoreSaveVerifiableCredential({ verifiableCredential })
expect(typeof hash).toEqual('string')
Expand All @@ -48,6 +53,24 @@ export default (testContext: {
expect(verifiableCredential).toEqual(verifiableCredential2)
})

it('should create verifiable credential (simple)', async () => {
const verifiableCredential = await agent.createVerifiableCredential({
credential: {
issuer: { id: identifier.did },
credentialSubject: {
id: 'did:web:example.com',
you: 'Rock',
},
},
proofFormat: 'jwt',
})

expect(verifiableCredential).toHaveProperty('proof.jwt')
expect(verifiableCredential).toHaveProperty('issuanceDate')
expect(verifiableCredential['@context']).toEqual(['https://www.w3.org/2018/credentials/v1'])
expect(verifiableCredential['type']).toEqual(['VerifiableCredential'])
})

it('should create verifiable presentation', async () => {
const verifiableCredential = await agent.createVerifiableCredential({
credential: {
Expand All @@ -67,15 +90,52 @@ export default (testContext: {
presentation: {
holder: identifier.did,
verifier: [],
'@context': ['https://www.w3.org/2018/credentials/v1'],
type: ['VerifiablePresentation'],
'@context': ['https://www.w3.org/2018/credentials/v1', 'https://example.com/1/2/3'],
type: ['VerifiablePresentation', 'Custom'],
issuanceDate: new Date().toISOString(),
verifiableCredential: [verifiableCredential],
},
proofFormat: 'jwt',
})

expect(verifiablePresentation).toHaveProperty('proof.jwt')
expect(verifiablePresentation['@context']).toEqual([
'https://www.w3.org/2018/credentials/v1',
'https://example.com/1/2/3',
])
expect(verifiablePresentation['type']).toEqual(['VerifiablePresentation', 'Custom'])

const hash = await agent.dataStoreSaveVerifiablePresentation({ verifiablePresentation })
expect(typeof hash).toEqual('string')

const verifiablePresentation2 = await agent.dataStoreGetVerifiablePresentation({ hash })
expect(verifiablePresentation).toEqual(verifiablePresentation2)
})

it('should create verifiable presentation (simple)', async () => {
const verifiableCredential = await agent.createVerifiableCredential({
credential: {
issuer: { id: identifier.did },
credentialSubject: {
id: 'did:web:example.com',
you: 'Rock',
},
},
proofFormat: 'jwt',
})

const verifiablePresentation = await agent.createVerifiablePresentation({
presentation: {
holder: identifier.did,
verifier: [],
verifiableCredential: [verifiableCredential],
},
proofFormat: 'jwt',
})

expect(verifiablePresentation).toHaveProperty('proof.jwt')
expect(verifiablePresentation['@context']).toEqual(['https://www.w3.org/2018/credentials/v1'])
expect(verifiablePresentation['type']).toEqual(['VerifiablePresentation'])

const hash = await agent.dataStoreSaveVerifiablePresentation({ verifiablePresentation })
expect(typeof hash).toEqual('string')
Expand Down
39 changes: 34 additions & 5 deletions packages/daf-w3c/api/daf-w3c.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,6 @@ import { IResolver } from 'daf-core';
import { Message } from 'daf-message-handler';
import { VerifiableCredential } from 'daf-core';
import { VerifiablePresentation } from 'daf-core';
import { W3CCredential } from 'daf-core';
import { W3CPresentation } from 'daf-core';

// @public
export class CredentialIssuer implements IAgentPlugin {
Expand All @@ -30,17 +28,48 @@ export class CredentialIssuer implements IAgentPlugin {
readonly schema: any;
}

// @public
export type EncodingFormat = 'jwt';

// @public
export interface ICreateVerifiableCredentialArgs {
credential: W3CCredential;
// Warning: (ae-forgotten-export) The symbol "EncodingFormat" needs to be exported by the entry point index.d.ts
credential: {
'@context'?: string[];
id?: string;
type?: string[];
issuer: {
id: string;
[x: string]: any;
};
issuanceDate?: string;
expirationDate?: string;
credentialSubject: {
id?: string;
[x: string]: any;
};
credentialStatus?: {
id: string;
type: string;
};
[x: string]: any;
};
proofFormat: EncodingFormat;
save?: boolean;
}

// @public
export interface ICreateVerifiablePresentationArgs {
presentation: W3CPresentation;
presentation: {
id?: string;
holder: string;
issuanceDate?: string;
expirationDate?: string;
'@context'?: string[];
type?: string[];
verifier: string[];
verifiableCredential: VerifiableCredential[];
[x: string]: any;
};
proofFormat: EncodingFormat;
save?: boolean;
}
Expand Down
58 changes: 52 additions & 6 deletions packages/daf-w3c/src/action-handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,20 @@ export interface ICreateVerifiablePresentationArgs {
*
* The signer of the Presentation is chosen based on the `holder` property
* of the `presentation`
*
* '@context', 'type' and 'issuanceDate' will be added automatically if omitted
*/
presentation: W3CPresentation
presentation: {
id?: string
holder: string
issuanceDate?: string
expirationDate?: string
'@context'?: string[]
type?: string[]
verifier: string[]
verifiableCredential: VerifiableCredential[]
[x: string]: any
}

/**
* If this parameter is true, the resulting VerifiablePresentation is sent to the
Expand Down Expand Up @@ -75,8 +87,26 @@ export interface ICreateVerifiableCredentialArgs {
*
* The signer of the Credential is chosen based on the `issuer.id` property
* of the `credential`
*
* '@context', 'type' and 'issuanceDate' will be added automatically if omitted
*/
credential: W3CCredential
credential: {
'@context'?: string[]
id?: string
type?: string[]
issuer: { id: string; [x: string]: any }
issuanceDate?: string
expirationDate?: string
credentialSubject: {
id?: string
[x: string]: any
}
credentialStatus?: {
id: string
type: string
}
[x: string]: any
}

/**
* If this parameter is true, the resulting VerifiablePresentation is sent to the
Expand Down Expand Up @@ -169,15 +199,23 @@ export class CredentialIssuer implements IAgentPlugin {
context: IContext,
): Promise<VerifiablePresentation> {
try {
const presentation: W3CPresentation = {
...args.presentation,
'@context': args.presentation['@context'] || ['https://www.w3.org/2018/credentials/v1'],
//FIXME: make sure 'VerifiablePresentation' is the first element in this array:
type: args.presentation.type || ['VerifiablePresentation'],
issuanceDate: args.presentation.issuanceDate || new Date().toISOString(),
}

//FIXME: if the identifier is not found, the error message should reflect that.
const identifier = await context.agent.didManagerGet({ did: args.presentation.holder })
const identifier = await context.agent.didManagerGet({ did: presentation.holder })
//FIXME: `args` should allow picking a key or key type
const key = identifier.keys.find((k) => k.type === 'Secp256k1')
if (!key) throw Error('No signing key for ' + identifier.did)
//FIXME: Throw an `unsupported_format` error if the `args.proofFormat` is not `jwt`
const signer = (data: string) => context.agent.keyManagerSignJWT({ kid: key.kid, data })
debug('Signing VP with', identifier.did)
const jwt = await createVerifiablePresentationJwt(args.presentation, { did: identifier.did, signer })
const jwt = await createVerifiablePresentationJwt(presentation, { did: identifier.did, signer })
//FIXME: flagging this as a potential privacy leak.
debug(jwt)
const verifiablePresentation = normalizePresentation(jwt)
Expand All @@ -197,16 +235,24 @@ export class CredentialIssuer implements IAgentPlugin {
context: IContext,
): Promise<VerifiableCredential> {
try {
const credential: W3CCredential = {
...args.credential,
'@context': args.credential['@context'] || ['https://www.w3.org/2018/credentials/v1'],
//FIXME: make sure 'VerifiableCredential' is the first element in this array:
type: args.credential.type || ['VerifiableCredential'],
issuanceDate: args.credential.issuanceDate || new Date().toISOString(),
}

//FIXME: if the identifier is not found, the error message should reflect that.
const identifier = await context.agent.didManagerGet({ did: args.credential.issuer.id })
const identifier = await context.agent.didManagerGet({ did: credential.issuer.id })
//FIXME: `args` should allow picking a key or key type
const key = identifier.keys.find((k) => k.type === 'Secp256k1')
if (!key) throw Error('No signing key for ' + identifier.did)
//FIXME: Throw an `unsupported_format` error if the `args.proofFormat` is not `jwt`
const signer = (data: string) => context.agent.keyManagerSignJWT({ kid: key.kid, data })

debug('Signing VC with', identifier.did)
const jwt = await createVerifiableCredentialJwt(args.credential, { did: identifier.did, signer })
const jwt = await createVerifiableCredentialJwt(credential, { did: identifier.did, signer })
//FIXME: flagging this as a potential privacy leak.
debug(jwt)
const verifiableCredential = normalizeCredential(jwt)
Expand Down
1 change: 1 addition & 0 deletions packages/daf-w3c/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export {
ICredentialIssuer,
ICreateVerifiableCredentialArgs,
ICreateVerifiablePresentationArgs,
EncodingFormat,
} from './action-handler'
const schema = require('../plugin.schema.json')
export { schema }

0 comments on commit 172c908

Please sign in to comment.