Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: Add policies to Verification API [DEV-2951] #294

Merged
merged 5 commits into from
Jul 11, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
675 changes: 356 additions & 319 deletions package-lock.json

Large diffs are not rendered by default.

15 changes: 8 additions & 7 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
"README.md"
],
"dependencies": {
"@cheqd/did-provider-cheqd": "^3.4.1",
"@cheqd/did-provider-cheqd": "^3.6.0",
"@cosmjs/amino": "^0.31.0",
"@cosmjs/encoding": "^0.30.1",
"@logto/express": "^2.0.2",
Expand All @@ -55,13 +55,14 @@
"@veramo/did-resolver": "^5.2.0",
"@veramo/key-manager": "^5.1.2",
"@veramo/kms-local": "^5.1.2",
"@verida/account-node": "^2.3.5",
"@verida/client-ts": "^2.3.5",
"@verida/account-node": "^2.3.6",
"@verida/client-ts": "^2.3.6",
"@verida/types": "^2.3.1",
"@verida/vda-did-resolver": "^2.3.5",
"@verida/vda-did-resolver": "^2.3.6",
"cookie-parser": "^1.4.6",
"copyfiles": "^2.4.1",
"cors": "^2.8.5",
"did-jwt": "^7.2.4",
"did-resolver": "^4.1.0",
"dotenv": "^16.3.1",
"express": "^4.18.2",
Expand Down Expand Up @@ -92,12 +93,12 @@
"@types/express-session": "^1.17.7",
"@types/helmet": "^4.0.0",
"@types/json-stringify-safe": "^5.0.0",
"@types/node": "^20.4.0",
"@types/node": "^20.4.1",
"@types/secp256k1": "^4.0.3",
"@types/swagger-ui-express": "^4.1.3",
"@types/uuid": "^9.0.2",
"@typescript-eslint/eslint-plugin": "^5.61.0",
"@typescript-eslint/parser": "^5.61.0",
"@typescript-eslint/eslint-plugin": "^5.62.0",
"@typescript-eslint/parser": "^5.62.0",
"buffer": "6.0.3",
"conventional-changelog-conventionalcommits": "^6.1.0",
"eslint": "^8.44.0",
Expand Down
29 changes: 27 additions & 2 deletions src/controllers/credentials.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ export class CredentialController {
return false
})
.withMessage('Entry must be a jwt string or an credential'),
check('policies').optional().isObject().withMessage('Verification policies should be an object'),
query('verifyStatus').optional().isBoolean().withMessage('verifyStatus should be a boolean value'),
query('publish').optional().isBoolean().withMessage('publish should be a boolean value')
]

Expand All @@ -41,6 +43,9 @@ export class CredentialController {
return false
})
.withMessage('Entry must be a jwt string or a presentation'),
check('verifierDid').optional().isString().withMessage('Invalid verifier DID'),
check('policies').optional().isObject().withMessage('Verification policies should be an object'),
query('verifyStatus').optional().isBoolean().withMessage('verifyStatus should be a boolean value')
]

public async issue(request: Request, response: Response) {
Expand Down Expand Up @@ -76,8 +81,18 @@ export class CredentialController {
if (!result.isEmpty()) {
return response.status(400).json({ error: result.array()[0].msg })
}

const { credential, policies } = request.body
const verifyStatus = request.query.verifyStatus === 'true' ? true : false
try {
const result = await Credentials.instance.verify_credentials(request.body.credential, request.body.statusOptions, response.locals.customerId)
const result = await Identity.instance.verifyCredential(
credential,
{
verifyStatus,
policies
},
response.locals.customerId
)
if (result.error) {
return response.status(400).json({
verified: result.verified,
Expand Down Expand Up @@ -144,8 +159,18 @@ export class CredentialController {
return response.status(400).json({ error: result.array()[0].msg })
}

const { presentation, verifierDid, policies } = request.body
const verifyStatus = request.query.verifyStatus === 'true' ? true : false
try {
const result = await Identity.instance.verifyPresentation(request.body.presentation, request.body.statusOptions, response.locals.customerId)
const result = await Identity.instance.verifyPresentation(
presentation,
{
verifyStatus,
policies,
domain: verifierDid
},
response.locals.customerId
)
if (result.error) {
return response.status(400).json({
verified: result.verified,
Expand Down
13 changes: 1 addition & 12 deletions src/services/credentials.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import {
VC_CONTEXT,
VC_TYPE
} from '../types/constants.js'
import { CredentialRequest, VerifyCredentialStatusOptions, VerifyPresentationStatusOptions } from '../types/types.js'
import { CredentialRequest, VerificationOptions } from '../types/types.js'
import { Identity } from './identity/index.js'
import { VeridaService } from '../services/connectors/verida.js'
import { v4 } from 'uuid'
Expand Down Expand Up @@ -50,15 +50,4 @@ export class Credentials {
}
return verifiable_credential
}

async verify_credentials(credential: W3CVerifiableCredential | string, statusOptions: VerifyCredentialStatusOptions | null, agentId: string): Promise<IVerifyResult> {
const result = await Identity.instance.verifyCredential(credential, statusOptions, agentId)
delete(result.payload)
return result
}

async verify_presentation(presentation: W3CVerifiablePresentation, statusOptions: VerifyPresentationStatusOptions | null, agentId: string): Promise<IVerifyResult> {
const result = await Identity.instance.verifyPresentation(presentation, statusOptions, agentId)
return result
}
}
10 changes: 5 additions & 5 deletions src/services/identity/IIdentity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ import type {
} from '@veramo/core'
import type { AbstractPrivateKeyStore } from '@veramo/key-manager'
import type { ResourcePayload } from '@cheqd/did-provider-cheqd'
import type { BulkRevocationResult, BulkSuspensionResult, BulkUnsuspensionResult, CreateEncryptedStatusList2021Result, CreateStatusList2021Result, RevocationResult, SuspensionResult, UnsuspensionResult } from '@cheqd/did-provider-cheqd/build/types/agent/ICheqd'
import type { BroadCastStatusListOptions, CreateStatusListOptions, CredentialRequest, StatusOptions, UpdateStatusListOptions, VeramoAgent, VerifyCredentialStatusOptions, VerifyPresentationStatusOptions } from '../../types/types'
import type { BulkRevocationResult, BulkSuspensionResult, BulkUnsuspensionResult, CreateStatusList2021Result, RevocationResult, SuspensionResult, UnsuspensionResult } from '@cheqd/did-provider-cheqd/build/types/agent/ICheqd'
import type { BroadCastStatusListOptions, CreateStatusListOptions, CredentialRequest, StatusOptions, UpdateStatusListOptions, VeramoAgent, VerificationOptions } from '../../types/types'

export interface IIdentity {
agent?: TAgent<any>
Expand All @@ -30,9 +30,9 @@ export interface IIdentity {
importDid(did: string, privateKeyHex: string, publicKeyHex: string, agentId?: string): Promise<IIdentifier>
createResource(network: string, payload: ResourcePayload, agentId?: string): Promise<any>
createCredential(credential: CredentialPayload, format: CredentialRequest['format'], statusOptions: StatusOptions | null, agentId?: string): Promise<VerifiableCredential>
verifyCredential(credential: VerifiableCredential | string, statusOptions: VerifyCredentialStatusOptions | null, agentId?: string): Promise<IVerifyResult>
verifyPresentation(presentation: VerifiablePresentation | string, statusOptions: VerifyPresentationStatusOptions, agentId?: string): Promise<IVerifyResult>
createStatusList2021(did: string, resourceOptions: ResourcePayload, statusOptions: CreateStatusListOptions, agentId: string): Promise<CreateStatusList2021Result | CreateEncryptedStatusList2021Result>
verifyCredential(credential: VerifiableCredential | string, verificationOptions: VerificationOptions, agentId?: string): Promise<IVerifyResult>
verifyPresentation(presentation: VerifiablePresentation | string, verificationOptions: VerificationOptions, agentId?: string): Promise<IVerifyResult>
createStatusList2021(did: string, resourceOptions: ResourcePayload, statusOptions: CreateStatusListOptions, agentId: string): Promise<CreateStatusList2021Result>
updateStatusList2021(did: string, statusOptions: UpdateStatusListOptions, publish?: boolean, agentId?: string): Promise<BulkRevocationResult | BulkSuspensionResult | BulkUnsuspensionResult>
broadcastStatusList2021(did: string, resourceOptions: ResourcePayload, statusOptions: BroadCastStatusListOptions, agentId?: string): Promise<boolean>
revokeCredentials(credential: VerifiableCredential | VerifiableCredential[], publish: boolean, agentId?: string): Promise<RevocationResult| BulkRevocationResult>
Expand Down
61 changes: 43 additions & 18 deletions src/services/identity/agent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import {
MinimalImportableKey,
TAgent,
VerifiableCredential,
VerifiablePresentation,
VerifiablePresentation
} from '@veramo/core'
import { KeyManager } from '@veramo/key-manager'
import { DIDStore, KeyStore } from '@veramo/data-store'
Expand All @@ -34,6 +34,7 @@ import type {
ICheqdRevokeBulkCredentialsWithStatusList2021Args,
ICheqdUpdateIdentifierArgs,
ICheqdVerifyCredentialWithStatusList2021Args,
ICheqdVerifyPresentationWithStatusList2021Args,
} from '@cheqd/did-provider-cheqd/build/types/agent/ICheqd'
import {
BroadCastStatusListOptions,
Expand All @@ -46,10 +47,10 @@ import {
SuspensionStatusOptions,
UpdateStatusListOptions,
VeramoAgent,
VerifyCredentialStatusOptions,
VerifyPresentationStatusOptions
VerificationOptions
} from '../../types/types.js'
import { VC_PROOF_FORMAT, VC_REMOVE_ORIGINAL_FIELDS } from '../../types/constants.js'
import { decodeJWT } from 'did-jwt'

const resolverUrl = "https://resolver.cheqd.net/1.0/identifiers/"

Expand Down Expand Up @@ -236,16 +237,26 @@ export class Veramo {
}
}

async verifyCredential(agent: VeramoAgent, credential: string | VerifiableCredential, statusOptions: VerifyCredentialStatusOptions | null): Promise<IVerifyResult> {
if(typeof credential !== 'string' && credential.credentialStatus) {
return await agent.cheqdVerifyCredential({
async verifyCredential(agent: VeramoAgent, credential: string | VerifiableCredential, verificationOptions: VerificationOptions = {}): Promise<IVerifyResult> {
const decodedCredential = typeof credential === 'string' ? decodeJWT(credential) as unknown as VerifiableCredential : credential
let result: IVerifyResult
if(verificationOptions.verifyStatus) {
result = await agent.cheqdVerifyCredential({
credential: credential as VerifiableCredential,
fetchList: true,
...statusOptions
verificationArgs: {
...verificationOptions,
fetchRemoteContexts: verificationOptions.fetchRemoteContexts || decodedCredential.proof.jws
}
} as ICheqdVerifyCredentialWithStatusList2021Args)
} else {
result = await agent.verifyCredential({
credential,
...verificationOptions,
fetchRemoteContexts: verificationOptions.fetchRemoteContexts || decodedCredential.proof.jws
})
}

const result = await agent.verifyCredential({ credential, fetchRemoteContexts: true })
if (result.didResolutionResult) {
delete(result.didResolutionResult)
}
Expand All @@ -257,19 +268,28 @@ export class Veramo {
if (result.verifiableCredential) {
delete(result.verifiableCredential)
}

if (result.payload) {
delete(result.payload)
}

return result
}

async verifyPresentation(agent: VeramoAgent, presentation: VerifiablePresentation | string, statusOptions: VerifyPresentationStatusOptions | null): Promise<IVerifyResult> {
// TODO: expose domain in did-provider-cheqd
// if(typeof presentation !== 'string') {
// return await agent.cheqdVerifyPresentation({
// presentation: presentation as VerifiablePresentation,
// fetchList: true,
// ...statusOptions
// } as ICheqdVerifyPresentationWithStatusList2021Args)
// }
const result = await agent.verifyPresentation({ presentation, fetchRemoteContexts: true, policies: {audience: false} })
async verifyPresentation(agent: VeramoAgent, presentation: VerifiablePresentation | string, verificationOptions: VerificationOptions = {}): Promise<IVerifyResult> {
let result: IVerifyResult
if(verificationOptions.verifyStatus) {
result = await agent.cheqdVerifyPresentation({
presentation: presentation as VerifiablePresentation,
fetchList: true,
verificationArgs: {
...verificationOptions
},
} as ICheqdVerifyPresentationWithStatusList2021Args)
} else {
result = await agent.verifyPresentation({ presentation, ...verificationOptions, fetchRemoteContexts: verificationOptions.fetchRemoteContexts || false })
}

if (result.didResolutionResult) {
delete(result.didResolutionResult)
}
Expand All @@ -281,6 +301,11 @@ export class Veramo {
if (result.verifiablePresentation) {
delete(result.verifiablePresentation)
}

if (result.payload) {
delete(result.payload)
}

return result
}

Expand Down
14 changes: 7 additions & 7 deletions src/services/identity/local.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@ import {
import { AbstractPrivateKeyStore, MemoryPrivateKeyStore } from '@veramo/key-manager'
import { KeyManagementSystem } from '@veramo/kms-local'
import { CheqdDIDProvider, ResourcePayload } from '@cheqd/did-provider-cheqd'
import { BulkRevocationResult, BulkSuspensionResult, BulkUnsuspensionResult, CreateEncryptedStatusList2021Result, CreateStatusList2021Result, ICheqdBroadcastEncryptedStatusList2021Args } from '@cheqd/did-provider-cheqd/build/types/agent/ICheqd'
import { BulkRevocationResult, BulkSuspensionResult, BulkUnsuspensionResult, CreateStatusList2021Result } from '@cheqd/did-provider-cheqd/build/types/agent/ICheqd'
import { CheqdNetwork } from '@cheqd/sdk'

import { BroadCastStatusListOptions, CreateStatusListOptions, CredentialRequest, DefaultRPCUrl, StatusOptions, UpdateStatusListOptions, VeramoAgent, VerifyCredentialStatusOptions, VerifyPresentationStatusOptions } from '../../types/types.js'
import { BroadCastStatusListOptions, CreateStatusListOptions, CredentialRequest, DefaultRPCUrl, StatusOptions, UpdateStatusListOptions, VeramoAgent, VerificationOptions } from '../../types/types.js'
import { Connection } from '../../database/connection/connection.js'
import { IIdentity } from './IIdentity.js'
import { Veramo } from './agent.js'
Expand Down Expand Up @@ -146,15 +146,15 @@ export class LocalIdentity implements IIdentity {
}
}

async verifyCredential(credential: VerifiableCredential | string, statusOptions: VerifyCredentialStatusOptions | null): Promise<IVerifyResult> {
return await Veramo.instance.verifyCredential(this.initAgent(), credential, statusOptions)
async verifyCredential(credential: VerifiableCredential | string, verificationOptions: VerificationOptions): Promise<IVerifyResult> {
return await Veramo.instance.verifyCredential(this.initAgent(), credential, verificationOptions)
}

async verifyPresentation(presentation: VerifiablePresentation | string, statusOptions: VerifyPresentationStatusOptions | null): Promise<IVerifyResult> {
return await Veramo.instance.verifyPresentation(this.initAgent(), presentation, statusOptions)
async verifyPresentation(presentation: VerifiablePresentation | string, verificationOptions: VerificationOptions): Promise<IVerifyResult> {
return await Veramo.instance.verifyPresentation(this.initAgent(), presentation, verificationOptions)
}

async createStatusList2021(did: string, resourceOptions: ResourcePayload, statusListOptions: CreateStatusListOptions): Promise<CreateStatusList2021Result | CreateEncryptedStatusList2021Result> {
async createStatusList2021(did: string, resourceOptions: ResourcePayload, statusListOptions: CreateStatusListOptions): Promise<CreateStatusList2021Result> {
return await Veramo.instance.createStatusList2021(this.initAgent(), did, resourceOptions, statusListOptions)
}

Expand Down
14 changes: 7 additions & 7 deletions src/services/identity/postgres.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,15 @@ import { KeyManagementSystem, SecretBox } from '@veramo/kms-local'
import { PrivateKeyStore } from '@veramo/data-store'
import { CheqdDIDProvider, ResourcePayload } from '@cheqd/did-provider-cheqd'
import { CheqdNetwork } from '@cheqd/sdk'
import { BroadCastStatusListOptions, cheqdDidRegex, CreateStatusListOptions, CredentialRequest, DefaultRPCUrl, StatusOptions, UpdateStatusListOptions, VeramoAgent, VerifyCredentialStatusOptions, VerifyPresentationStatusOptions } from '../../types/types.js'
import { BroadCastStatusListOptions, cheqdDidRegex, CreateStatusListOptions, CredentialRequest, DefaultRPCUrl, StatusOptions, UpdateStatusListOptions, VeramoAgent, VerificationOptions } from '../../types/types.js'
import { Connection } from '../../database/connection/connection.js'
import { CustomerEntity } from '../../database/entities/customer.entity.js'
import { IIdentity } from './IIdentity.js'
import { CustomerService } from '../customer.js'
import { Veramo } from './agent.js'

import * as dotenv from 'dotenv'
import { BulkRevocationResult, BulkSuspensionResult, BulkUnsuspensionResult, CreateEncryptedStatusList2021Result, CreateStatusList2021Result } from '@cheqd/did-provider-cheqd/build/types/agent/ICheqd.js'
import { BulkRevocationResult, BulkSuspensionResult, BulkUnsuspensionResult, CreateStatusList2021Result } from '@cheqd/did-provider-cheqd/build/types/agent/ICheqd.js'
dotenv.config()

const {
Expand Down Expand Up @@ -214,17 +214,17 @@ export class PostgresIdentity implements IIdentity {
}
}

async verifyCredential(credential: string | VerifiableCredential, statusOptions: VerifyCredentialStatusOptions | null, agentId: string): Promise<IVerifyResult> {
async verifyCredential(credential: string | VerifiableCredential, verificationOptions: VerificationOptions, agentId: string): Promise<IVerifyResult> {
const agent = await this.createAgent(agentId)
return await Veramo.instance.verifyCredential(agent, credential, statusOptions)
return await Veramo.instance.verifyCredential(agent, credential, verificationOptions)
}

async verifyPresentation(presentation: VerifiablePresentation | string, statusOptions: VerifyPresentationStatusOptions | null, agentId: string): Promise<IVerifyResult> {
async verifyPresentation(presentation: VerifiablePresentation | string, verificationOptions: VerificationOptions, agentId: string): Promise<IVerifyResult> {
const agent = await this.createAgent(agentId)
return await Veramo.instance.verifyPresentation(agent, presentation, statusOptions)
return await Veramo.instance.verifyPresentation(agent, presentation, verificationOptions)
}

async createStatusList2021(did: string, resourceOptions: ResourcePayload, statusOptions: CreateStatusListOptions, agentId: string): Promise<CreateStatusList2021Result | CreateEncryptedStatusList2021Result> {
async createStatusList2021(did: string, resourceOptions: ResourcePayload, statusOptions: CreateStatusListOptions, agentId: string): Promise<CreateStatusList2021Result> {
const agent = await this.createAgent(agentId)
return await Veramo.instance.createStatusList2021(agent, did, resourceOptions, statusOptions)
}
Expand Down
Loading