Skip to content

Commit

Permalink
feat: updated oid4vci-holder and siopv2-rp to use credential-validati…
Browse files Browse the repository at this point in the history
…on module for verifying credentials.
  • Loading branch information
sksadjad committed Oct 4, 2024
1 parent 6464fac commit b25b66e
Show file tree
Hide file tree
Showing 16 changed files with 505 additions and 246 deletions.
34 changes: 34 additions & 0 deletions packages/credential-validation/__tests__/localAgent.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { createObjects, getConfig } from '../../agent-config/dist'
import { DataSource } from 'typeorm'

jest.setTimeout(60000)

import credentialValidationAgentLogic from './shared/credentialValidationAgentLogic'

let dbConnection: Promise<DataSource>
let agent: any

const setup = async (): Promise<boolean> => {
const config = await getConfig('packages/credential-validation/agent.yml')
const { localAgent, db } = await createObjects(config, { localAgent: '/agent', db: '/dbConnection' })
agent = localAgent
dbConnection = db

return true
}

const tearDown = async (): Promise<boolean> => {
await (await dbConnection).close()
return true
}

const getAgent = () => agent
const testContext = {
getAgent,
setup,
tearDown,
}

describe('Local integration tests', (): void => {
credentialValidationAgentLogic(testContext)
})
70 changes: 70 additions & 0 deletions packages/credential-validation/__tests__/restAgent.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import 'cross-fetch/polyfill'
// @ts-ignore
import express, { Router } from 'express'
import { Server } from 'http'
import { DataSource } from 'typeorm'
import { IAgent, createAgent, IAgentOptions } from '@veramo/core'
import { AgentRestClient } from '@veramo/remote-client'
import { AgentRouter, RequestWithAgentRouter } from '@veramo/remote-server'
import { createObjects, getConfig } from '../../agent-config/dist'
import credentialValidationAgentLogic from './shared/credentialValidationAgentLogic'
import { ICredentialValidation } from '../src'
jest.setTimeout(60000)

const port = 4103
const basePath = '/agent'

let serverAgent: IAgent
let restServer: Server
let dbConnection: Promise<DataSource>

const getAgent = (options?: IAgentOptions) =>
createAgent<ICredentialValidation>({
...options,
plugins: [
new AgentRestClient({
url: 'http://localhost:' + port + basePath,
enabledMethods: serverAgent.availableMethods(),
schema: serverAgent.getSchema(),
}),
],
})

const setup = async (): Promise<boolean> => {
const config = await getConfig('packages/credential-validation/agent.yml')
const { agent, db } = await createObjects(config, { agent: '/agent', db: '/dbConnection' })
serverAgent = agent
dbConnection = db

const agentRouter = AgentRouter({
exposedMethods: serverAgent.availableMethods(),
})

const requestWithAgent: Router = RequestWithAgentRouter({
agent: serverAgent,
})

return new Promise((resolve): void => {
const app = express()
app.use(basePath, requestWithAgent, agentRouter)
restServer = app.listen(port, (): void => {
resolve(true)
})
})
}

const tearDown = async (): Promise<boolean> => {
restServer.close()
await (await dbConnection).close()
return true
}

const testContext = {
getAgent,
setup,
tearDown,
}

describe('REST integration tests', (): void => {
credentialValidationAgentLogic(testContext)
})

Large diffs are not rendered by default.

155 changes: 155 additions & 0 deletions packages/credential-validation/agent.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
version: 3.0

constants:
baseUrl: http://localhost:3336
port: 3336
secretKey: 29739248cad1bd1a0fc4d9b75cd4d2990de535baf5caadfdf8d8f86664aa830c
methods:
- cvVerifyCredential
- cvVerifySchema
- cvVerifyMdoc
- cvVerifySDJWTCredential
- cvVerifyW3CCredential

dbConnection:
$require: typeorm?t=function#createConnection
$args:
- type: sqlite
database: ':memory:'
synchronize: false
migrationsRun: true
migrations:
$require: './packages/ssi-sdk-core/dist?t=function#flattenMigrations'
$args:
- migrations:
- $require: '@veramo/data-store?t=object#migrations'
- $require: './packages/data-store?t=object#DataStoreMigrations'
logging: ['info', 'warn']
entities:
$require: './packages/ssi-sdk-core/dist?t=function#flattenArray'
$args:
- items:
- $require: '@veramo/data-store?t=object#Entities'
- $require: './packages/data-store?t=object#DataStoreEntities'
# migrations:
# $require: '@veramo/data-store?t=object#migrations'
# entities:
# $require: '@veramo/data-store?t=object#Entities'

server:
baseUrl:
$ref: /constants/baseUrl
port:
$ref: /constants/port
use:
# CORS
- - $require: 'cors'

# Add agent to the request object
- - $require: '@veramo/remote-server?t=function#RequestWithAgentRouter'
$args:
- agent:
$ref: /agent

# API base path
- - /agent
- $require: '@veramo/remote-server?t=function#apiKeyAuth'
$args:
# Please configure your own API key. This is used when executing agent methods through ${baseUrl}/agent or ${baseUrl}/api-docs
- apiKey: test123
- $require: '@veramo/remote-server?t=function#AgentRouter'
$args:
- exposedMethods:
$ref: /constants/methods

# Open API schema
- - /open-api.json
- $require: '@veramo/remote-server?t=function#ApiSchemaRouter'
$args:
- basePath: :3336/agent
securityScheme: bearer
apiName: Agent
apiVersion: '1.0.0'
exposedMethods:
$ref: /constants/methods

# Swagger docs
- - /api-docs
- $require: swagger-ui-express?t=object#serve
- $require: swagger-ui-express?t=function#setup
$args:
- null
- swaggerOptions:
url: '/open-api.json'

# Execute during server initialization
init:
- $require: '@veramo/remote-server?t=function#createDefaultDid'
$args:
- agent:
$ref: /agent
baseUrl:
$ref: /constants/baseUrl
messagingServiceEndpoint: /messaging

keyManager:
$require: '@sphereon/ssi-sdk-ext.key-manager#SphereonKeyManager'
$args:
- store:
$require: '@veramo/data-store#KeyStore'
$args:
- $ref: /dbConnection
kms:
local:
$require: '@sphereon/ssi-sdk-ext.kms-local#SphereonKeyManagementSystem'
$args:
- $require: '@veramo/data-store#PrivateKeyStore'
$args:
- $ref: /dbConnection
- $require: '@sphereon/ssi-sdk-ext.kms-local#SecretBox'
$args:
- $ref: /constants/secretKey

didManager:
$require: '@veramo/did-manager#DIDManager'
$args:
- store:
$require: '@veramo/data-store#DIDStore'
$args:
- $ref: /dbConnection
defaultProvider: did:ebsi

# Agent
agent:
$require: '@veramo/core#Agent'
$args:
- schemaValidation: false
plugins:
- $ref: /keyManager
- $ref: /didManager
- $require: '@veramo/core#Agent'
- $require: '@veramo/data-store#DataStore'
$args:
- $ref: /dbConnection
- $require: '@veramo/data-store#DataStoreORM'
$args:
- $ref: /dbConnection
# - $require: '@veramo/credential-w3c#CredentialPlugin'
- $require: ./packages/credential-validation/dist#CredentialValidation
# - $require: ./packages/presentation-exchange/dist#PresentationExchange
# - $require: ./packages/siopv2-oid4vp-op-auth/dist#DidAuthSiopOpAuthenticator
# - $require: ./packages/oid4vci-holder/dist#OID4VCIHolder
# - $require: ./packages/issuance-branding/dist#IssuanceBranding
# $args:
# - store:
# $require: './packages/data-store/dist#IssuanceBrandingStore'
# $args:
# - $ref: /dbConnection
# - $require: ./packages/contact-manager/dist#ContactManager
# $args:
# - store:
# $require: './packages/data-store/dist#ContactStore'
# $args:
# - $ref: /dbConnection
# $args:
# - presentationSignCallback: { }
3 changes: 3 additions & 0 deletions packages/credential-validation/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,12 @@
"dependencies": {
"@sphereon/ssi-types": "workspace:*",
"@sphereon/ssi-sdk.agent-config": "workspace:*",
"@sphereon/ssi-sdk.core": "workspace:*",
"@sphereon/ssi-sdk.mdl-mdoc": "workspace:*",
"@sphereon/kmp-mdl-mdoc": "0.2.0-SNAPSHOT.22",
"@sphereon/ssi-sdk.sd-jwt": "workspace:*",
"@veramo/core": "4.2.0",
"@veramo/utils": "4.2.0",
"ajv": "^8.17.1",
"ajv-formats": "^3.0.1",
"cross-fetch": "^3.1.8",
Expand Down
38 changes: 25 additions & 13 deletions packages/credential-validation/src/agent/CredentialValidation.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
import { IAgentPlugin, IVerifyCredentialArgs, W3CVerifiableCredential as VeramoW3CVerifiableCredential } from '@veramo/core'
import {
CredentialVerificationError,
ICredentialValidation,
RequiredContext,
schema,
VerifyCredentialArgs,
VerificationResult,
VerificationSubResult,
ICredentialValidation,
SchemaValidation,
ValidateSchemaArgs,
VerifySDJWTCredentialArgs,
VerificationResult,
VerificationSubResult,
VerifyCredentialArgs,
VerifyMdocCredentialArgs,
CredentialVerificationError,
VerifySDJWTCredentialArgs,
} from '../index'
import {
CredentialMapper,
Expand All @@ -24,15 +24,15 @@ import fetch from 'cross-fetch'
import Ajv2020 from 'ajv/dist/2020'
import addFormats from 'ajv-formats'
import { com } from '@sphereon/kmp-mdl-mdoc'
import { IVerifySdJwtVcResult } from '@sphereon/ssi-sdk.sd-jwt'
import decodeFrom = com.sphereon.kmp.decodeFrom
import IssuerSignedCbor = com.sphereon.mdoc.data.device.IssuerSignedCbor
import { IVerifySdJwtVcResult } from '@sphereon/ssi-sdk.sd-jwt'
import IVerifySignatureResult = com.sphereon.crypto.IVerifySignatureResult

// Exposing the methods here for any REST implementation
export const credentialValidationMethods: Array<string> = [
'cvVerifyCredential',
'cvValidateSchema',
'cvVerifySchema',
'cvVerifyMdoc',
'cvVerifySDJWTCredential',
'cvVerifyW3CCredential',
Expand All @@ -45,7 +45,7 @@ export class CredentialValidation implements IAgentPlugin {
readonly schema = schema.ICredentialValidation
readonly methods: ICredentialValidation = {
cvVerifyCredential: this.cvVerifyCredential.bind(this),
cvValidateSchema: this.cvValidateSchema.bind(this),
cvVerifySchema: this.cvVerifySchema.bind(this),
cvVerifyMdoc: this.cvVerifyMdoc.bind(this),
cvVerifySDJWTCredential: this.cvVerifySDJWTCredential.bind(this),
cvVerifyW3CCredential: this.cvVerifyW3CCredential.bind(this),
Expand All @@ -70,8 +70,12 @@ export class CredentialValidation implements IAgentPlugin {
}

private async cvVerifyCredential(args: VerifyCredentialArgs, context: RequiredContext): Promise<VerificationResult> {
const { credential, hasher } = args

const { credential, hasher, policies } = args
// defaulting the schema validation to when_present
const schemaResult = await this.cvVerifySchema({ credential, validationPolicy: policies?.schemaValidation ?? SchemaValidation.WHEN_PRESENT })
if (!schemaResult.result) {
return schemaResult
}
if (CredentialMapper.isMsoMdocOid4VPEncoded(credential)) {
return await this.cvVerifyMdoc({ credential }, context)
} else if (CredentialMapper.isSdJwtEncoded(credential)) {
Expand All @@ -81,9 +85,17 @@ export class CredentialValidation implements IAgentPlugin {
}
}

private async cvValidateSchema(args: ValidateSchemaArgs): Promise<VerificationResult> {
private async cvVerifySchema(args: ValidateSchemaArgs): Promise<VerificationResult> {
const { credential, hasher, validationPolicy } = args
return this.validateSchema(CredentialMapper.toWrappedVerifiableCredential(credential, { hasher }), validationPolicy)
const wrappedCredential: WrappedVerifiableCredential = CredentialMapper.toWrappedVerifiableCredential(credential, { hasher })
if (validationPolicy === SchemaValidation.NEVER) {
return {
result: true,
source: wrappedCredential,
subResults: [],
}
}
return this.validateSchema(wrappedCredential, validationPolicy)
}

private async validateSchema(wrappedVC: WrappedVerifiableCredential, validationPolicy?: SchemaValidation): Promise<VerificationResult> {
Expand Down
Loading

0 comments on commit b25b66e

Please sign in to comment.