Skip to content

Commit

Permalink
feat(credential-w3c): align verification API between formats (#996)
Browse files Browse the repository at this point in the history
* feat(credential-w3c): align verification API between formats

fixes #935
fixes #954
fixes #375

* test: add test cases for VC/VP verification policies

* feat(credential-w3c): add extra options to VC/VP issuance and verification

* fix: forward the `fetchRemoteContext` parameter to the document loader

fixes #989
  • Loading branch information
mirceanis authored Sep 6, 2022
1 parent ac0c05b commit b987fc0
Show file tree
Hide file tree
Showing 29 changed files with 930 additions and 423 deletions.
26 changes: 13 additions & 13 deletions __tests__/shared/credentialStatus.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,9 +102,9 @@ export default (testContext: {
})
expect(vc).toHaveProperty('proof.jwt')

const verified = await agent.verifyCredential({ credential: vc })
const result = await agent.verifyCredential({ credential: vc })
expect(callsCounter).toHaveBeenCalledTimes(1)
expect(verified).toBeTruthy()
expect(result.verified).toEqual(true)
})

it('should check credentialStatus for revoked JWT credential', async () => {
Expand All @@ -114,9 +114,9 @@ export default (testContext: {
})
expect(vc).toHaveProperty('proof.jwt')

const verified = await agent.verifyCredential({ credential: vc })
const result = await agent.verifyCredential({ credential: vc })
expect(callsCounter).toHaveBeenCalledTimes(1)
expect(verified).toBeFalsy()
expect(result.verified).toEqual(false)
})

it('should fail checking credentialStatus with exception during verification', async () => {
Expand Down Expand Up @@ -152,9 +152,9 @@ export default (testContext: {
})
expect(vc).toHaveProperty('proof.jws')

const verified = await agent.verifyCredential({ credential: vc })
const result = await agent.verifyCredential({ credential: vc })
expect(callsCounter).toHaveBeenCalledTimes(1)
expect(verified).toBeTruthy()
expect(result.verified).toEqual(true)
})

it('should check credentialStatus for revoked JSON-LD credential', async () => {
Expand All @@ -164,9 +164,9 @@ export default (testContext: {
})
expect(vc).toHaveProperty('proof.jws')

const verified = await agent.verifyCredential({ credential: vc })
const result = await agent.verifyCredential({ credential: vc })
expect(callsCounter).toHaveBeenCalledTimes(1)
expect(verified).toBeFalsy()
expect(result.verified).toEqual(false)
})

it('should check credentialStatus for EIP712 credential', async () => {
Expand All @@ -176,9 +176,9 @@ export default (testContext: {
})
expect(vc).toHaveProperty('proof.proofValue')

const verified = await agent.verifyCredential({ credential: vc })
const result = await agent.verifyCredential({ credential: vc })
expect(callsCounter).toHaveBeenCalledTimes(1)
expect(verified).toBeTruthy()
expect(result.verified).toEqual(true)
})

it('should check credentialStatus for revoked EIP712 credential', async () => {
Expand All @@ -188,9 +188,9 @@ export default (testContext: {
})
expect(vc).toHaveProperty('proof.proofValue')

const verified = await agent.verifyCredential({ credential: vc })
const result = await agent.verifyCredential({ credential: vc })
expect(callsCounter).toHaveBeenCalledTimes(1)
expect(verified).toBeFalsy()
expect(result.verified).toEqual(false)
})
})

Expand Down Expand Up @@ -235,7 +235,7 @@ export default (testContext: {

// TODO It`s an exception flow an it'd be better to throw an exception instead of returning false
await expect(agent.verifyCredential({ credential: vc })).rejects.toThrow(
`The credential status can't be verified by the agent`,
`invalid_setup: The credential status can't be verified because there is no ICredentialStatusVerifier plugin installed.`,
)
})
})
Expand Down
178 changes: 172 additions & 6 deletions __tests__/shared/verifiableDataJWT.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,12 @@ import {
IIdentifier,
TAgent,
TKeyType,
VerifiableCredential,
VerifiablePresentation,
} from '../../packages/core/src'
import { ICredentialIssuer } from '../../packages/credential-w3c/src'
import { decodeJWT } from 'did-jwt'
import { VC_JWT_ERROR } from 'did-jwt-vc'

type ConfiguredAgent = TAgent<IDIDManager & ICredentialIssuer & IDataStore & IDataStoreORM>

Expand All @@ -25,14 +28,10 @@ export default (testContext: {
beforeAll(async () => {
await testContext.setup()
agent = testContext.getAgent()
identifier = await agent.didManagerCreate({ kms: 'local', provider: 'did:key' })
})
afterAll(testContext.tearDown)

it('should create identifier', async () => {
identifier = await agent.didManagerCreate({ kms: 'local' })
expect(identifier).toHaveProperty('did')
})

it('should create verifiable credential in JWT', async () => {
const verifiableCredential = await agent.createVerifiableCredential({
credential: {
Expand Down Expand Up @@ -274,7 +273,7 @@ export default (testContext: {
}

beforeAll(async () => {
const imported = await agent.didManagerImport(importedDID)
await agent.didManagerImport(importedDID)
})

it('signs JWT with ES256K', async () => {
Expand All @@ -299,5 +298,172 @@ export default (testContext: {
})
})
})

describe('credential verification policies', () => {
let credential: VerifiableCredential

beforeAll(async () => {
const issuanceDate = '2019-08-19T09:15:20.000Z' // 1566206120
const expirationDate = '2019-08-20T10:42:31.000Z' // 1566297751
credential = await agent.createVerifiableCredential({
proofFormat: 'jwt',
credential: {
issuer: identifier.did,
issuanceDate,
expirationDate,
credentialSubject: {
hello: 'world',
},
},
})
})

it('can verify credential at a particular time', async () => {
const result = await agent.verifyCredential({ credential })
expect(result.verified).toBe(false)
expect(result?.error?.errorCode).toEqual(VC_JWT_ERROR.INVALID_JWT)

const result2 = await agent.verifyCredential({
credential,
policies: { now: 1566297000 },
})
expect(result2.verified).toBe(true)
})

it('can override expiry check', async () => {
const result = await agent.verifyCredential({
credential,
policies: { expirationDate: false },
})
expect(result.verified).toBe(true)
})

it('can override issuance check', async () => {
const result = await agent.verifyCredential({
credential,
policies: { issuanceDate: false, now: 1565000000 },
})
expect(result.verified).toBe(true)
})

it('can override audience check', async () => {
const cred = await agent.createVerifiableCredential({
proofFormat: 'jwt',
credential: {
issuer: identifier.did,
aud: 'override me',
credentialSubject: {
hello: 'world',
},
},
})
const result = await agent.verifyCredential({ credential: cred })
expect(result.verified).toBe(false)
expect(result.error?.errorCode).toEqual(VC_JWT_ERROR.INVALID_AUDIENCE)

const result2 = await agent.verifyCredential({ credential: cred, policies: { audience: false } })
expect(result2.verified).toBe(true)
})

it('can override credentialStatus check', async () => {
const cred = await agent.createVerifiableCredential({
proofFormat: 'jwt',
credential: {
issuer: identifier.did,
credentialSubject: {
hello: 'world',
},
credentialStatus: {
id: 'override me',
type: 'ThisMethodDoesNotExist2022',
},
},
})
await expect(agent.verifyCredential({ credential: cred })).rejects.toThrow(/^invalid_setup:/)

const result2 = await agent.verifyCredential({
credential: cred,
policies: { credentialStatus: false },
})
expect(result2.verified).toBe(true)
})
})

describe('presentation verification policies', () => {
let credential: VerifiableCredential
let presentation: VerifiablePresentation

beforeAll(async () => {
const issuanceDate = '2019-08-19T09:15:20.000Z' // 1566206120
const expirationDate = '2019-08-20T10:42:31.000Z' // 1566297751
credential = await agent.createVerifiableCredential({
proofFormat: 'jwt',
credential: {
issuer: identifier.did,
credentialSubject: {
hello: 'world',
},
},
})
presentation = await agent.createVerifiablePresentation({
proofFormat: 'jwt',
presentation: {
holder: identifier.did,
verifiableCredential: [credential],
issuanceDate,
expirationDate,
},
})
})

it('can verify presentation at a particular time', async () => {
const result = await agent.verifyPresentation({ presentation })
expect(result.verified).toBe(false)
expect(result?.error?.errorCode).toEqual(VC_JWT_ERROR.INVALID_JWT)

const result2 = await agent.verifyPresentation({
presentation,
policies: { now: 1566297000 },
})
expect(result2.verified).toBe(true)
})

it('can override expiry check', async () => {
const result = await agent.verifyPresentation({
presentation,
policies: { expirationDate: false },
})
expect(result.verified).toBe(true)
})

it('can override issuance check', async () => {
const result = await agent.verifyPresentation({
presentation,
policies: { issuanceDate: false, now: 1565000000 },
})
expect(result.verified).toBe(true)
})

it('can override audience check', async () => {
const pres = await agent.createVerifiablePresentation({
proofFormat: 'jwt',
presentation: {
holder: identifier.did,
verifiableCredential: [credential],
},
challenge: '1234',
domain: 'example.com',
})
const result = await agent.verifyPresentation({ presentation: pres })
expect(result.verified).toBe(false)
expect(result.error?.errorCode).toEqual(VC_JWT_ERROR.INVALID_AUDIENCE)

const result2 = await agent.verifyPresentation({
presentation: pres,
policies: { audience: false },
})
expect(result2.verified).toBe(true)
})
})
})
}
Loading

0 comments on commit b987fc0

Please sign in to comment.