diff --git a/.github/workflows/continuous-delivery.yml b/.github/workflows/continuous-delivery.yml index ffdc2e57..175bf207 100644 --- a/.github/workflows/continuous-delivery.yml +++ b/.github/workflows/continuous-delivery.yml @@ -42,3 +42,5 @@ jobs: tags: | ${{ env.REGISTRY }}/${{ github.repository_owner }}/${{ env.SERVICE }}:${{ env.TAG }} ${{ env.REGISTRY }}/${{ github.repository_owner }}/${{ env.SERVICE }}:latest + + diff --git a/src/controllers/multi-tenancy/MultiTenancyController.ts b/src/controllers/multi-tenancy/MultiTenancyController.ts index 739463d8..551d5258 100644 --- a/src/controllers/multi-tenancy/MultiTenancyController.ts +++ b/src/controllers/multi-tenancy/MultiTenancyController.ts @@ -1,7 +1,7 @@ /* eslint-disable prettier/prettier */ import type { RestAgentModules, RestMultiTenantAgentModules } from '../../cliAgent' import type { Version } from '../examples' -import type { RecipientKeyOption, SchemaMetadata } from '../types' +import type { CustomW3cJsonLdSignCredentialOptions, RecipientKeyOption, SafeW3cJsonLdVerifyCredentialOptions, SchemaMetadata } from '../types' import type { PolygonDidCreateOptions } from '@ayanworks/credo-polygon-w3c-module/build/dids' import type { AcceptProofRequestOptions, @@ -15,7 +15,8 @@ import type { ProofExchangeRecordProps, ProofsProtocolVersionType, Routing, -} from '@credo-ts/core' + W3cJsonLdSignCredentialOptions, + W3cVerifiableCredential} from '@credo-ts/core' import type { IndyVdrDidCreateOptions, IndyVdrDidCreateResult } from '@credo-ts/indy-vdr' import type { QuestionAnswerRecord, ValidResponse } from '@credo-ts/question-answer' import type { TenantRecord } from '@credo-ts/tenants' @@ -27,6 +28,7 @@ import { parseIndyCredentialDefinitionId, parseIndySchemaId, } from '@credo-ts/anoncreds' +import { assertAskarWallet } from '@credo-ts/askar/build/utils/assertAskarWallet' import { AcceptCredentialOfferOptions, Agent, @@ -45,7 +47,9 @@ import { injectable, createPeerDidDocumentFromServices, PeerDidNumAlgo, -} from '@credo-ts/core' + W3cJsonLdVerifiableCredential, + W3cCredential, + ClaimFormat} from '@credo-ts/core' import { QuestionAnswerRole, QuestionAnswerState } from '@credo-ts/question-answer' import axios from 'axios' import * as fs from 'fs' @@ -89,7 +93,7 @@ import { CreateProofRequestOobOptions, CreateOfferOobOptions, CreateSchemaInput, -} from '../types' + VerifyDataOptions , SignDataOptions } from '../types' import { Body, Controller, Delete, Get, Post, Query, Route, Tags, Path, Example, Security, Response } from 'tsoa' @@ -1913,4 +1917,124 @@ export class MultiTenancyController extends Controller { throw ErrorHandlingService.handle(error) } } + + /** + * Verify data using a key + * + * @param tenantId Tenant identifier + * @param request Verify options + * data - Data has to be in base64 format + * publicKeyBase58 - Public key in base58 format + * signature - Signature in base64 format + * @returns isValidSignature - true if signature is valid, false otherwise + */ + @Security('apiKey') + @Post('/verify/:tenantId') + public async verify(@Path('tenantId') tenantId: string, @Body() request: VerifyDataOptions) { + try { + const isValidSignature = await this.agent.modules.tenants.withTenantAgent({ tenantId }, async (tenantAgent) => { + assertAskarWallet(tenantAgent.context.wallet) + const isValidSignature = await tenantAgent.context.wallet.verify({ + data: TypedArrayEncoder.fromBase64(request.data), + key: Key.fromPublicKeyBase58(request.publicKeyBase58, request.keyType), + signature: TypedArrayEncoder.fromBase64(request.signature), + }) + return isValidSignature + }) + return isValidSignature + } catch (error) { + throw ErrorHandlingService.handle(error) + } + } + + @Security('apiKey') + @Post('/credential/sign/:tenantId') + public async signCredential( + @Path('tenantId') tenantId: string, + @Query('storeCredential') storeCredential: boolean, + @Query('dataTypeToSign') dataTypeToSign: 'rawData' | 'jsonLd', + @Body() data: CustomW3cJsonLdSignCredentialOptions | SignDataOptions | any + ) { + try { + return await this.agent.modules.tenants.withTenantAgent({ tenantId }, async (tenantAgent) => { + // JSON-LD VC Signing + if (dataTypeToSign === 'jsonLd') { + const credentialData = data as unknown as W3cJsonLdSignCredentialOptions + credentialData.format = ClaimFormat.LdpVc + + const signedCredential = await tenantAgent.w3cCredentials.signCredential(credentialData) as W3cJsonLdVerifiableCredential + + if (storeCredential) { + return await tenantAgent.w3cCredentials.storeCredential({ credential: signedCredential }) + } + + return signedCredential.toJson() + } + + // Raw Data Signing + const rawData = data as SignDataOptions + + if (!rawData.data) throw new BadRequestError('Missing "data" for raw data signing.') + + const hasDidOrMethod = rawData.did || rawData.method + const hasPublicKey = rawData.publicKeyBase58 && rawData.keyType + + if (!hasDidOrMethod && !hasPublicKey) { + throw new BadRequestError('Either (did or method) OR (publicKeyBase58 and keyType) must be provided.') + } + + let keyToUse: Key + + if (hasDidOrMethod) { + const dids = await tenantAgent.dids.getCreatedDids({ + method: rawData.method || undefined, + did: rawData.did || undefined, + }) + + const verificationMethod = dids[0]?.didDocument?.verificationMethod?.[0]?.publicKeyBase58 + if (!verificationMethod) { + throw new BadRequestError('No publicKeyBase58 found for the given DID or method.') + } + + keyToUse = Key.fromPublicKeyBase58(verificationMethod, rawData.keyType) + } else { + keyToUse = Key.fromPublicKeyBase58(rawData.publicKeyBase58, rawData.keyType) + } + + if (!keyToUse) { + throw new Error('Unable to construct signing key.') + } + + const signature = await tenantAgent.context.wallet.sign({ + data: TypedArrayEncoder.fromBase64(rawData.data), + key: keyToUse, + }) + + return TypedArrayEncoder.toBase64(signature) + }) + } catch (error) { + throw ErrorHandlingService.handle(error) + } + } + + @Security('apiKey') + @Post('/credential/verify/:tenantId') + public async verifyCredential( + @Path('tenantId') tenantId: string, + @Body() credentialToVerify: SafeW3cJsonLdVerifyCredentialOptions | any + ) { + let formattedCredential + try { + await this.agent.modules.tenants.withTenantAgent({ tenantId }, async (tenantAgent) => { + const {credential, ...credentialOptions}= credentialToVerify + const transformedCredential = JsonTransformer.fromJSON(credentialToVerify?.credential, W3cJsonLdVerifiableCredential) + const signedCred = await tenantAgent.w3cCredentials.verifyCredential({credential: transformedCredential, ...credentialOptions}) + formattedCredential = signedCred + }) + return formattedCredential + } catch (error) { + throw ErrorHandlingService.handle(error) + } + } } + diff --git a/src/controllers/types.ts b/src/controllers/types.ts index 3753d6f2..227d94a0 100644 --- a/src/controllers/types.ts +++ b/src/controllers/types.ts @@ -25,8 +25,16 @@ import type { Attachment, KeyType, JsonLdCredentialFormat, + JsonObject, + W3cJsonLdVerifyCredentialOptions, + DataIntegrityProofOptions, + W3cJsonLdSignCredentialOptions, + W3cCredential, + W3cCredentialSubject, } from '@credo-ts/core' +import type { SingleOrArray } from '@credo-ts/core/build/utils' import type { DIDDocument } from 'did-resolver' +import { LinkedDataProofOptions } from '@credo-ts/core/build/modules/vc/data-integrity/models/LinkedDataProof' export type TenantConfig = Pick & { walletConfig: Pick @@ -37,10 +45,6 @@ export interface AgentInfo { endpoints: string[] isInitialized: boolean publicDid: void - // publicDid?: { - // did: string - // verkey: string - // } } export interface AgentMessageType { @@ -388,3 +392,48 @@ export interface SchemaMetadata { * @example "ea4e5e69-fc04-465a-90d2-9f8ff78aa71d" */ export type ThreadId = string + +export type SignDataOptions = { + data: string + keyType: KeyType + publicKeyBase58: string + did?: string + method?: string +} + +export type VerifyDataOptions = { + data: string + keyType: KeyType + publicKeyBase58: string + signature: string +} + +export interface jsonLdCredentialOptions { + '@context': Array + type: Array + credentialSubject: SingleOrArray + proofType: string +} + +export interface credentialPayloadToSign { + issuerDID: string + method: string + credential: jsonLdCredentialOptions // TODO: add support for other credential format +} +export interface SafeW3cJsonLdVerifyCredentialOptions extends W3cJsonLdVerifyCredentialOptions { + // Ommited due to issues with TSOA + proof: SingleOrArray | DataIntegrityProofOptions> +} + +export type ExtensibleW3cCredentialSubject = W3cCredentialSubject & { + [key: string]: unknown +} + +export type ExtensibleW3cCredential = W3cCredential & { + [key: string]: unknown + credentialSubject: SingleOrArray +} + +export type CustomW3cJsonLdSignCredentialOptions = Omit & { + [key: string]: unknown +} diff --git a/src/routes/routes.ts b/src/routes/routes.ts index 4566e855..68fbc8c9 100644 --- a/src/routes/routes.ts +++ b/src/routes/routes.ts @@ -693,6 +693,202 @@ const models: TsoaRoute.Models = { "type": {"dataType":"nestedObjectLiteral","nestedProperties":{"content":{"dataType":"string","required":true}},"validators":{}}, }, // WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa + "VerifyDataOptions": { + "dataType": "refAlias", + "type": {"dataType":"nestedObjectLiteral","nestedProperties":{"signature":{"dataType":"string","required":true},"publicKeyBase58":{"dataType":"string","required":true},"keyType":{"ref":"KeyType","required":true},"data":{"dataType":"string","required":true}},"validators":{}}, + }, + // WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa + "W3cCredentialRecord": { + "dataType": "refAlias", + "type": {"ref":"Record_string.unknown_","validators":{}}, + }, + // WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa + "W3cIssuer": { + "dataType": "refObject", + "properties": { + "id": {"dataType":"string","required":true}, + }, + "additionalProperties": false, + }, + // WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa + "W3cCredentialSubject": { + "dataType": "refObject", + "properties": { + "id": {"dataType":"string"}, + "claims": {"ref":"Record_string.unknown_"}, + }, + "additionalProperties": false, + }, + // WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa + "SingleOrArray_W3cCredentialSubject_": { + "dataType": "refAlias", + "type": {"dataType":"union","subSchemas":[{"ref":"W3cCredentialSubject"},{"dataType":"array","array":{"dataType":"refObject","ref":"W3cCredentialSubject"}}],"validators":{}}, + }, + // WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa + "W3cCredentialSchema": { + "dataType": "refObject", + "properties": { + "id": {"dataType":"string","required":true}, + "type": {"dataType":"string","required":true}, + }, + "additionalProperties": false, + }, + // WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa + "SingleOrArray_W3cCredentialSchema_": { + "dataType": "refAlias", + "type": {"dataType":"union","subSchemas":[{"ref":"W3cCredentialSchema"},{"dataType":"array","array":{"dataType":"refObject","ref":"W3cCredentialSchema"}}],"validators":{}}, + }, + // WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa + "W3cCredentialStatus": { + "dataType": "refObject", + "properties": { + "id": {"dataType":"string","required":true}, + "type": {"dataType":"string","required":true}, + }, + "additionalProperties": false, + }, + // WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa + "W3cCredential": { + "dataType": "refObject", + "properties": { + "context": {"dataType":"array","array":{"dataType":"union","subSchemas":[{"dataType":"string"},{"ref":"JsonObject"}]},"required":true}, + "id": {"dataType":"string"}, + "type": {"dataType":"array","array":{"dataType":"string"},"required":true}, + "issuer": {"dataType":"union","subSchemas":[{"dataType":"string"},{"ref":"W3cIssuer"}],"required":true}, + "issuanceDate": {"dataType":"string","required":true}, + "expirationDate": {"dataType":"string"}, + "credentialSubject": {"ref":"SingleOrArray_W3cCredentialSubject_","required":true}, + "credentialSchema": {"ref":"SingleOrArray_W3cCredentialSchema_"}, + "credentialStatus": {"ref":"W3cCredentialStatus"}, + }, + "additionalProperties": false, + }, + // WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa + "Pick_W3cJsonLdSignCredentialOptions.Exclude_keyofW3cJsonLdSignCredentialOptions.format__": { + "dataType": "refAlias", + "type": {"dataType":"nestedObjectLiteral","nestedProperties":{"credential":{"ref":"W3cCredential","required":true},"proofType":{"dataType":"string","required":true},"proofPurpose":{"dataType":"any"},"created":{"dataType":"string"},"verificationMethod":{"dataType":"string","required":true}},"validators":{}}, + }, + // WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa + "Omit_W3cJsonLdSignCredentialOptions.format_": { + "dataType": "refAlias", + "type": {"ref":"Pick_W3cJsonLdSignCredentialOptions.Exclude_keyofW3cJsonLdSignCredentialOptions.format__","validators":{}}, + }, + // WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa + "CustomW3cJsonLdSignCredentialOptions": { + "dataType": "refAlias", + "type": {"dataType":"intersection","subSchemas":[{"ref":"Omit_W3cJsonLdSignCredentialOptions.format_"},{"dataType":"nestedObjectLiteral","nestedProperties":{},"additionalProperties":{"dataType":"any"}}],"validators":{}}, + }, + // WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa + "SignDataOptions": { + "dataType": "refAlias", + "type": {"dataType":"nestedObjectLiteral","nestedProperties":{"method":{"dataType":"string"},"did":{"dataType":"string"},"publicKeyBase58":{"dataType":"string","required":true},"keyType":{"ref":"KeyType","required":true},"data":{"dataType":"string","required":true}},"validators":{}}, + }, + // WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa + "Pick_LinkedDataProofOptions.Exclude_keyofLinkedDataProofOptions.cryptosuite__": { + "dataType": "refAlias", + "type": {"dataType":"nestedObjectLiteral","nestedProperties":{"proofPurpose":{"dataType":"string","required":true},"created":{"dataType":"string","required":true},"verificationMethod":{"dataType":"string","required":true},"type":{"dataType":"string","required":true},"domain":{"dataType":"string"},"challenge":{"dataType":"string"},"jws":{"dataType":"string"},"proofValue":{"dataType":"string"},"nonce":{"dataType":"string"}},"validators":{}}, + }, + // WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa + "Omit_LinkedDataProofOptions.cryptosuite_": { + "dataType": "refAlias", + "type": {"ref":"Pick_LinkedDataProofOptions.Exclude_keyofLinkedDataProofOptions.cryptosuite__","validators":{}}, + }, + // WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa + "DataIntegrityProofOptions": { + "dataType": "refObject", + "properties": { + "type": {"dataType":"string","required":true}, + "cryptosuite": {"dataType":"string","required":true}, + "verificationMethod": {"dataType":"string","required":true}, + "proofPurpose": {"dataType":"string","required":true}, + "domain": {"dataType":"string"}, + "challenge": {"dataType":"string"}, + "nonce": {"dataType":"string"}, + "created": {"dataType":"string"}, + "expires": {"dataType":"string"}, + "proofValue": {"dataType":"string"}, + "previousProof": {"dataType":"string"}, + }, + "additionalProperties": false, + }, + // WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa + "SingleOrArray_Omit_LinkedDataProofOptions.cryptosuite_-or-DataIntegrityProofOptions_": { + "dataType": "refAlias", + "type": {"dataType":"union","subSchemas":[{"dataType":"union","subSchemas":[{"ref":"Omit_LinkedDataProofOptions.cryptosuite_"},{"ref":"DataIntegrityProofOptions"}]},{"dataType":"array","array":{"dataType":"union","subSchemas":[{"ref":"Omit_LinkedDataProofOptions.cryptosuite_"},{"ref":"DataIntegrityProofOptions"}]}}],"validators":{}}, + }, + // WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa + "LinkedDataProof": { + "dataType": "refObject", + "properties": { + "type": {"dataType":"string","required":true}, + "proofPurpose": {"dataType":"string","required":true}, + "verificationMethod": {"dataType":"string","required":true}, + "created": {"dataType":"string","required":true}, + "domain": {"dataType":"string"}, + "challenge": {"dataType":"string"}, + "jws": {"dataType":"string"}, + "proofValue": {"dataType":"string"}, + "nonce": {"dataType":"string"}, + }, + "additionalProperties": false, + }, + // WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa + "DataIntegrityProof": { + "dataType": "refObject", + "properties": { + "type": {"dataType":"string","required":true}, + "cryptosuite": {"dataType":"string","required":true}, + "proofPurpose": {"dataType":"string","required":true}, + "verificationMethod": {"dataType":"string","required":true}, + "domain": {"dataType":"string"}, + "challenge": {"dataType":"string"}, + "nonce": {"dataType":"string"}, + "created": {"dataType":"string"}, + "expires": {"dataType":"string"}, + "proofValue": {"dataType":"string"}, + "previousProof": {"dataType":"string"}, + }, + "additionalProperties": false, + }, + // WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa + "SingleOrArray_LinkedDataProof-or-DataIntegrityProof_": { + "dataType": "refAlias", + "type": {"dataType":"union","subSchemas":[{"dataType":"union","subSchemas":[{"ref":"LinkedDataProof"},{"ref":"DataIntegrityProof"}]},{"dataType":"array","array":{"dataType":"union","subSchemas":[{"ref":"LinkedDataProof"},{"ref":"DataIntegrityProof"}]}}],"validators":{}}, + }, + // WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa + "W3cJsonLdVerifiableCredential": { + "dataType": "refObject", + "properties": { + "context": {"dataType":"array","array":{"dataType":"union","subSchemas":[{"dataType":"string"},{"ref":"JsonObject"}]},"required":true}, + "id": {"dataType":"string"}, + "type": {"dataType":"array","array":{"dataType":"string"},"required":true}, + "issuer": {"dataType":"union","subSchemas":[{"dataType":"string"},{"ref":"W3cIssuer"}],"required":true}, + "issuanceDate": {"dataType":"string","required":true}, + "expirationDate": {"dataType":"string"}, + "credentialSubject": {"ref":"SingleOrArray_W3cCredentialSubject_","required":true}, + "credentialSchema": {"ref":"SingleOrArray_W3cCredentialSchema_"}, + "credentialStatus": {"ref":"W3cCredentialStatus"}, + "proof": {"ref":"SingleOrArray_LinkedDataProof-or-DataIntegrityProof_","required":true}, + }, + "additionalProperties": false, + }, + // WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa + "ProofPurpose": { + "dataType": "refAlias", + "type": {"dataType":"any","validators":{}}, + }, + // WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa + "SafeW3cJsonLdVerifyCredentialOptions": { + "dataType": "refObject", + "properties": { + "credential": {"ref":"W3cJsonLdVerifiableCredential","required":true}, + "verifyCredentialStatus": {"dataType":"boolean"}, + "proofPurpose": {"ref":"ProofPurpose"}, + "proof": {"ref":"SingleOrArray_Omit_LinkedDataProofOptions.cryptosuite_-or-DataIntegrityProofOptions_","required":true}, + }, + "additionalProperties": false, + }, + // WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa "DidRegistrationSecretOptions": { "dataType": "refAlias", "type": {"ref":"Record_string.unknown_","validators":{}}, @@ -971,11 +1167,6 @@ const models: TsoaRoute.Models = { "enums": ["issuer","holder"], }, // WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa - "W3cCredentialRecord": { - "dataType": "refAlias", - "type": {"ref":"Record_string.unknown_","validators":{}}, - }, - // WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa "CredentialExchangeRecord": { "dataType": "refAlias", "type": {"ref":"Record_string.unknown_","validators":{}}, @@ -3546,6 +3737,119 @@ export function RegisterRoutes(app: Router) { } }); // WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa + app.post('/multi-tenancy/verify/:tenantId', + authenticateMiddleware([{"apiKey":[]}]), + ...(fetchMiddlewares(MultiTenancyController)), + ...(fetchMiddlewares(MultiTenancyController.prototype.verify)), + + async function MultiTenancyController_verify(request: ExRequest, response: ExResponse, next: any) { + const args: Record = { + tenantId: {"in":"path","name":"tenantId","required":true,"dataType":"string"}, + request: {"in":"body","name":"request","required":true,"ref":"VerifyDataOptions"}, + }; + + // WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa + + let validatedArgs: any[] = []; + try { + validatedArgs = templateService.getValidatedArgs({ args, request, response }); + + const container: IocContainer = typeof iocContainer === 'function' ? (iocContainer as IocContainerFactory)(request) : iocContainer; + + const controller: any = await container.get(MultiTenancyController); + if (typeof controller['setStatus'] === 'function') { + controller.setStatus(undefined); + } + + await templateService.apiHandler({ + methodName: 'verify', + controller, + response, + next, + validatedArgs, + successStatus: undefined, + }); + } catch (err) { + return next(err); + } + }); + // WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa + app.post('/multi-tenancy/credential/sign/:tenantId', + authenticateMiddleware([{"apiKey":[]}]), + ...(fetchMiddlewares(MultiTenancyController)), + ...(fetchMiddlewares(MultiTenancyController.prototype.signCredential)), + + async function MultiTenancyController_signCredential(request: ExRequest, response: ExResponse, next: any) { + const args: Record = { + tenantId: {"in":"path","name":"tenantId","required":true,"dataType":"string"}, + storeCredential: {"in":"query","name":"storeCredential","required":true,"dataType":"boolean"}, + dataTypeToSign: {"in":"query","name":"dataTypeToSign","required":true,"dataType":"union","subSchemas":[{"dataType":"enum","enums":["rawData"]},{"dataType":"enum","enums":["jsonLd"]}]}, + data: {"in":"body","name":"data","required":true,"dataType":"union","subSchemas":[{"ref":"CustomW3cJsonLdSignCredentialOptions"},{"ref":"SignDataOptions"},{"dataType":"any"}]}, + }; + + // WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa + + let validatedArgs: any[] = []; + try { + validatedArgs = templateService.getValidatedArgs({ args, request, response }); + + const container: IocContainer = typeof iocContainer === 'function' ? (iocContainer as IocContainerFactory)(request) : iocContainer; + + const controller: any = await container.get(MultiTenancyController); + if (typeof controller['setStatus'] === 'function') { + controller.setStatus(undefined); + } + + await templateService.apiHandler({ + methodName: 'signCredential', + controller, + response, + next, + validatedArgs, + successStatus: undefined, + }); + } catch (err) { + return next(err); + } + }); + // WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa + app.post('/multi-tenancy/credential/verify/:tenantId', + authenticateMiddleware([{"apiKey":[]}]), + ...(fetchMiddlewares(MultiTenancyController)), + ...(fetchMiddlewares(MultiTenancyController.prototype.verifyCredential)), + + async function MultiTenancyController_verifyCredential(request: ExRequest, response: ExResponse, next: any) { + const args: Record = { + tenantId: {"in":"path","name":"tenantId","required":true,"dataType":"string"}, + credentialToVerify: {"in":"body","name":"credentialToVerify","required":true,"dataType":"union","subSchemas":[{"ref":"SafeW3cJsonLdVerifyCredentialOptions"},{"dataType":"any"}]}, + }; + + // WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa + + let validatedArgs: any[] = []; + try { + validatedArgs = templateService.getValidatedArgs({ args, request, response }); + + const container: IocContainer = typeof iocContainer === 'function' ? (iocContainer as IocContainerFactory)(request) : iocContainer; + + const controller: any = await container.get(MultiTenancyController); + if (typeof controller['setStatus'] === 'function') { + controller.setStatus(undefined); + } + + await templateService.apiHandler({ + methodName: 'verifyCredential', + controller, + response, + next, + validatedArgs, + successStatus: undefined, + }); + } catch (err) { + return next(err); + } + }); + // WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa app.post('/transactions/endorse', authenticateMiddleware([{"apiKey":[]}]), ...(fetchMiddlewares(EndorserTransactionController)), diff --git a/src/routes/swagger.json b/src/routes/swagger.json index 8eea6fe5..d22382dd 100644 --- a/src/routes/swagger.json +++ b/src/routes/swagger.json @@ -1625,6 +1625,558 @@ "type": "object", "description": "Construct a type with a set of properties K of type T" }, + "VerifyDataOptions": { + "properties": { + "signature": { + "type": "string" + }, + "publicKeyBase58": { + "type": "string" + }, + "keyType": { + "$ref": "#/components/schemas/KeyType" + }, + "data": { + "type": "string" + } + }, + "required": [ + "signature", + "publicKeyBase58", + "keyType", + "data" + ], + "type": "object" + }, + "W3cCredentialRecord": { + "$ref": "#/components/schemas/Record_string.unknown_" + }, + "W3cIssuer": { + "properties": { + "id": { + "type": "string" + } + }, + "required": [ + "id" + ], + "type": "object", + "additionalProperties": false + }, + "W3cCredentialSubject": { + "properties": { + "id": { + "type": "string" + }, + "claims": { + "$ref": "#/components/schemas/Record_string.unknown_" + } + }, + "type": "object", + "additionalProperties": false + }, + "SingleOrArray_W3cCredentialSubject_": { + "anyOf": [ + { + "$ref": "#/components/schemas/W3cCredentialSubject" + }, + { + "items": { + "$ref": "#/components/schemas/W3cCredentialSubject" + }, + "type": "array" + } + ] + }, + "W3cCredentialSchema": { + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "required": [ + "id", + "type" + ], + "type": "object", + "additionalProperties": false + }, + "SingleOrArray_W3cCredentialSchema_": { + "anyOf": [ + { + "$ref": "#/components/schemas/W3cCredentialSchema" + }, + { + "items": { + "$ref": "#/components/schemas/W3cCredentialSchema" + }, + "type": "array" + } + ] + }, + "W3cCredentialStatus": { + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "required": [ + "id", + "type" + ], + "type": "object", + "additionalProperties": false + }, + "W3cCredential": { + "properties": { + "context": { + "items": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/components/schemas/JsonObject" + } + ] + }, + "type": "array" + }, + "id": { + "type": "string" + }, + "type": { + "items": { + "type": "string" + }, + "type": "array" + }, + "issuer": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/components/schemas/W3cIssuer" + } + ] + }, + "issuanceDate": { + "type": "string" + }, + "expirationDate": { + "type": "string" + }, + "credentialSubject": { + "$ref": "#/components/schemas/SingleOrArray_W3cCredentialSubject_" + }, + "credentialSchema": { + "$ref": "#/components/schemas/SingleOrArray_W3cCredentialSchema_" + }, + "credentialStatus": { + "$ref": "#/components/schemas/W3cCredentialStatus" + } + }, + "required": [ + "context", + "type", + "issuer", + "issuanceDate", + "credentialSubject" + ], + "type": "object", + "additionalProperties": false + }, + "Pick_W3cJsonLdSignCredentialOptions.Exclude_keyofW3cJsonLdSignCredentialOptions.format__": { + "properties": { + "credential": { + "$ref": "#/components/schemas/W3cCredential", + "description": "The credential to be signed." + }, + "proofType": { + "type": "string", + "description": "The proofType to be used for signing the credential.\n\nMust be a valid Linked Data Signature suite." + }, + "proofPurpose": {}, + "created": { + "type": "string" + }, + "verificationMethod": { + "type": "string", + "description": "URI of the verificationMethod to be used for signing the credential.\n\nMust be a valid did url pointing to a key." + } + }, + "required": [ + "credential", + "proofType", + "verificationMethod" + ], + "type": "object", + "description": "From T, pick a set of properties whose keys are in the union K" + }, + "Omit_W3cJsonLdSignCredentialOptions.format_": { + "$ref": "#/components/schemas/Pick_W3cJsonLdSignCredentialOptions.Exclude_keyofW3cJsonLdSignCredentialOptions.format__", + "description": "Construct a type with the properties of T except for those in type K." + }, + "CustomW3cJsonLdSignCredentialOptions": { + "allOf": [ + { + "$ref": "#/components/schemas/Omit_W3cJsonLdSignCredentialOptions.format_" + }, + { + "properties": {}, + "additionalProperties": {}, + "type": "object" + } + ] + }, + "SignDataOptions": { + "properties": { + "method": { + "type": "string" + }, + "did": { + "type": "string" + }, + "publicKeyBase58": { + "type": "string" + }, + "keyType": { + "$ref": "#/components/schemas/KeyType" + }, + "data": { + "type": "string" + } + }, + "required": [ + "publicKeyBase58", + "keyType", + "data" + ], + "type": "object" + }, + "Pick_LinkedDataProofOptions.Exclude_keyofLinkedDataProofOptions.cryptosuite__": { + "properties": { + "proofPurpose": { + "type": "string" + }, + "created": { + "type": "string" + }, + "verificationMethod": { + "type": "string" + }, + "type": { + "type": "string" + }, + "domain": { + "type": "string" + }, + "challenge": { + "type": "string" + }, + "jws": { + "type": "string" + }, + "proofValue": { + "type": "string" + }, + "nonce": { + "type": "string" + } + }, + "required": [ + "proofPurpose", + "created", + "verificationMethod", + "type" + ], + "type": "object", + "description": "From T, pick a set of properties whose keys are in the union K" + }, + "Omit_LinkedDataProofOptions.cryptosuite_": { + "$ref": "#/components/schemas/Pick_LinkedDataProofOptions.Exclude_keyofLinkedDataProofOptions.cryptosuite__", + "description": "Construct a type with the properties of T except for those in type K." + }, + "DataIntegrityProofOptions": { + "properties": { + "type": { + "type": "string" + }, + "cryptosuite": { + "type": "string" + }, + "verificationMethod": { + "type": "string" + }, + "proofPurpose": { + "type": "string" + }, + "domain": { + "type": "string" + }, + "challenge": { + "type": "string" + }, + "nonce": { + "type": "string" + }, + "created": { + "type": "string" + }, + "expires": { + "type": "string" + }, + "proofValue": { + "type": "string" + }, + "previousProof": { + "type": "string" + } + }, + "required": [ + "type", + "cryptosuite", + "verificationMethod", + "proofPurpose" + ], + "type": "object", + "additionalProperties": false + }, + "SingleOrArray_Omit_LinkedDataProofOptions.cryptosuite_-or-DataIntegrityProofOptions_": { + "anyOf": [ + { + "anyOf": [ + { + "$ref": "#/components/schemas/Omit_LinkedDataProofOptions.cryptosuite_" + }, + { + "$ref": "#/components/schemas/DataIntegrityProofOptions" + } + ] + }, + { + "items": { + "anyOf": [ + { + "$ref": "#/components/schemas/Omit_LinkedDataProofOptions.cryptosuite_" + }, + { + "$ref": "#/components/schemas/DataIntegrityProofOptions" + } + ] + }, + "type": "array" + } + ] + }, + "LinkedDataProof": { + "description": "Linked Data Proof", + "properties": { + "type": { + "type": "string" + }, + "proofPurpose": { + "type": "string" + }, + "verificationMethod": { + "type": "string" + }, + "created": { + "type": "string" + }, + "domain": { + "type": "string" + }, + "challenge": { + "type": "string" + }, + "jws": { + "type": "string" + }, + "proofValue": { + "type": "string" + }, + "nonce": { + "type": "string" + } + }, + "required": [ + "type", + "proofPurpose", + "verificationMethod", + "created" + ], + "type": "object", + "additionalProperties": false + }, + "DataIntegrityProof": { + "description": "Linked Data Proof", + "properties": { + "type": { + "type": "string" + }, + "cryptosuite": { + "type": "string" + }, + "proofPurpose": { + "type": "string" + }, + "verificationMethod": { + "type": "string" + }, + "domain": { + "type": "string" + }, + "challenge": { + "type": "string" + }, + "nonce": { + "type": "string" + }, + "created": { + "type": "string" + }, + "expires": { + "type": "string" + }, + "proofValue": { + "type": "string" + }, + "previousProof": { + "type": "string" + } + }, + "required": [ + "type", + "cryptosuite", + "proofPurpose", + "verificationMethod" + ], + "type": "object", + "additionalProperties": false + }, + "SingleOrArray_LinkedDataProof-or-DataIntegrityProof_": { + "anyOf": [ + { + "anyOf": [ + { + "$ref": "#/components/schemas/LinkedDataProof" + }, + { + "$ref": "#/components/schemas/DataIntegrityProof" + } + ] + }, + { + "items": { + "anyOf": [ + { + "$ref": "#/components/schemas/LinkedDataProof" + }, + { + "$ref": "#/components/schemas/DataIntegrityProof" + } + ] + }, + "type": "array" + } + ] + }, + "W3cJsonLdVerifiableCredential": { + "properties": { + "context": { + "items": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/components/schemas/JsonObject" + } + ] + }, + "type": "array" + }, + "id": { + "type": "string" + }, + "type": { + "items": { + "type": "string" + }, + "type": "array" + }, + "issuer": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/components/schemas/W3cIssuer" + } + ] + }, + "issuanceDate": { + "type": "string" + }, + "expirationDate": { + "type": "string" + }, + "credentialSubject": { + "$ref": "#/components/schemas/SingleOrArray_W3cCredentialSubject_" + }, + "credentialSchema": { + "$ref": "#/components/schemas/SingleOrArray_W3cCredentialSchema_" + }, + "credentialStatus": { + "$ref": "#/components/schemas/W3cCredentialStatus" + }, + "proof": { + "$ref": "#/components/schemas/SingleOrArray_LinkedDataProof-or-DataIntegrityProof_" + } + }, + "required": [ + "context", + "type", + "issuer", + "issuanceDate", + "credentialSubject", + "proof" + ], + "type": "object", + "additionalProperties": false + }, + "ProofPurpose": {}, + "SafeW3cJsonLdVerifyCredentialOptions": { + "properties": { + "credential": { + "$ref": "#/components/schemas/W3cJsonLdVerifiableCredential" + }, + "verifyCredentialStatus": { + "type": "boolean", + "description": "Whether to verify the credentialStatus, if present." + }, + "proofPurpose": { + "$ref": "#/components/schemas/ProofPurpose" + }, + "proof": { + "$ref": "#/components/schemas/SingleOrArray_Omit_LinkedDataProofOptions.cryptosuite_-or-DataIntegrityProofOptions_" + } + }, + "required": [ + "credential", + "proof" + ], + "type": "object", + "additionalProperties": false + }, "DidRegistrationSecretOptions": { "$ref": "#/components/schemas/Record_string.unknown_" }, @@ -2270,9 +2822,6 @@ ], "type": "string" }, - "W3cCredentialRecord": { - "$ref": "#/components/schemas/Record_string.unknown_" - }, "CredentialExchangeRecord": { "$ref": "#/components/schemas/Record_string.unknown_" }, @@ -6336,6 +6885,186 @@ } } }, + "/multi-tenancy/verify/{tenantId}": { + "post": { + "operationId": "Verify", + "responses": { + "200": { + "description": "isValidSignature - true if signature is valid, false otherwise", + "content": { + "application/json": { + "schema": { + "type": "boolean" + } + } + } + } + }, + "description": "Verify data using a key", + "tags": [ + "MultiTenancy" + ], + "security": [ + { + "apiKey": [] + } + ], + "parameters": [ + { + "description": "Tenant identifier", + "in": "path", + "name": "tenantId", + "required": true, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "description": "Verify options\ndata - Data has to be in base64 format\npublicKeyBase58 - Public key in base58 format\nsignature - Signature in base64 format", + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/VerifyDataOptions", + "description": "Verify options\ndata - Data has to be in base64 format\npublicKeyBase58 - Public key in base58 format\nsignature - Signature in base64 format" + } + } + } + } + } + }, + "/multi-tenancy/credential/sign/{tenantId}": { + "post": { + "operationId": "SignCredential", + "responses": { + "200": { + "description": "Ok", + "content": { + "application/json": { + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/components/schemas/Record_string.any_" + }, + { + "$ref": "#/components/schemas/W3cCredentialRecord" + } + ] + } + } + } + } + }, + "tags": [ + "MultiTenancy" + ], + "security": [ + { + "apiKey": [] + } + ], + "parameters": [ + { + "in": "path", + "name": "tenantId", + "required": true, + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "storeCredential", + "required": true, + "schema": { + "type": "boolean" + } + }, + { + "in": "query", + "name": "dataTypeToSign", + "required": true, + "schema": { + "type": "string", + "enum": [ + "rawData", + "jsonLd" + ] + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "anyOf": [ + { + "$ref": "#/components/schemas/CustomW3cJsonLdSignCredentialOptions" + }, + { + "$ref": "#/components/schemas/SignDataOptions" + }, + {} + ] + } + } + } + } + } + }, + "/multi-tenancy/credential/verify/{tenantId}": { + "post": { + "operationId": "VerifyCredential", + "responses": { + "200": { + "description": "Ok", + "content": { + "application/json": { + "schema": {} + } + } + } + }, + "tags": [ + "MultiTenancy" + ], + "security": [ + { + "apiKey": [] + } + ], + "parameters": [ + { + "in": "path", + "name": "tenantId", + "required": true, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "anyOf": [ + { + "$ref": "#/components/schemas/SafeW3cJsonLdVerifyCredentialOptions" + }, + {} + ] + } + } + } + } + } + }, "/transactions/endorse": { "post": { "operationId": "EndorserTransaction",