Skip to content
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
10 changes: 10 additions & 0 deletions src/controllers/openid4vc/holder/holder.Controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,16 @@ export class HolderController {
return await this.holderService.getMdocCredentials(this.agent)
}

/**
* Decode mso mdoc credential in wallet
*/
@Post('/mdoc-vcs/decode')
public async decodeMdocCredential(@Body() body:{
base64Url: string
}) {
return await this.holderService.decodeMdocCredential(this.agent, body)
}

/**
* Resolve a credential offer
*/
Expand Down
13 changes: 13 additions & 0 deletions src/controllers/openid4vc/holder/holder.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,19 @@ export class HolderService {
return await agent.mdoc.getAll()
}

public async decodeMdocCredential(agent: Agent, options: {
base64Url: string
}) {

const credential = Mdoc.fromBase64Url(options.base64Url)
return {
namespace: credential.issuerSignedNamespaces,
docType: credential.docType,
validityInfo: credential.validityInfo,
issuerSignedCertificateChain: credential.issuerSignedCertificateChain
} as any
}

// public async resolveCredentialOffer(agent: Agent, body: ResolveCredentialOfferBody) {
// return await agent.modules.openId4VcHolderModule.resolveCredentialOffer(body.credentialOfferUri)
// }
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { OpenId4VcIssuanceSessionsCreateOffer } from '../types/issuer.types'
import type { OpenId4VcIssuanceSessionState } from '@credo-ts/openid4vc'
import { OpenId4VciCredentialFormatProfile, type OpenId4VcIssuanceSessionState } from '@credo-ts/openid4vc'
import type { Request as Req } from 'express'

import { OpenId4VcIssuanceSessionRepository } from '@credo-ts/openid4vc/build/openid4vc-issuer/repository'
Expand Down Expand Up @@ -43,14 +43,14 @@ class IssuanceSessionsService {
)
}

const currentVct = cred.payload && 'vct' in cred.payload ? cred.payload.vct : undefined;
return {
...cred,
payload: {
...cred.payload,
vct: cred.payload?.vct ?? (typeof supported.vct === 'string' ? supported.vct : undefined),
},
}
// format: c.format as OpenId4VciCredentialFormatProfile, TODO: fix this type
...cred,
payload: {
...cred.payload,
vct: currentVct ?? (typeof supported.vct === 'string' ? supported.vct : undefined),
},
}
})

options.issuanceMetadata ||= {}
Expand Down
39 changes: 33 additions & 6 deletions src/controllers/openid4vc/types/issuer.types.ts
Original file line number Diff line number Diff line change
@@ -1,28 +1,55 @@
import { OpenId4VciCredentialFormatProfile } from "@credo-ts/openid4vc"
import { MdocNameSpaces, W3cCredential } from "@credo-ts/core"
import { OpenId4VciCreateCredentialOfferOptions, OpenId4VciCredentialFormatProfile, OpenId4VciSignCredentials } from "@credo-ts/openid4vc"

export enum SignerMethod {
Did = 'did',
X5c = 'x5c',
}

export interface OpenId4VcIssuanceSessionCredentialOptions {
credentialSupportedId: string
export interface OpenId4VciOfferCredentials {
credentialSupportedId: string
format: OpenId4VciCredentialFormatProfile,
signerOptions: {
method: SignerMethod
did?: string
x5c?: string[]
}
format: OpenId4VciCredentialFormatProfile
}

export interface OpenId4VciOfferSdJwtCredential extends OpenId4VciOfferCredentials {

payload: {
vct?: string
[key: string]: unknown
}
disclosureFrame?: Record<string, boolean | Record<string, boolean>>
}
export interface ValidityInfo {
signed: Date;
validFrom: Date;
validUntil: Date;
expectedUpdate?: Date;
}

export interface OpenId4VciOfferMdocCredential extends OpenId4VciOfferCredentials {
payload: {
docType: 'org.iso.18013.5.1.mDL' | (string & {})
validityInfo?: Partial<ValidityInfo>,
namespaces: MdocNameSpaces
}
}

export interface OpenId4VciOfferW3cCredential extends OpenId4VciOfferCredentials {
payload: {
verificationMethod: string;
credential: W3cCredential;
}
}


export interface OpenId4VcIssuanceSessionsCreateOffer {
export interface OpenId4VcIssuanceSessionsCreateOffer {//extends OpenId4VciCreateCredentialOfferOptions {
publicIssuerId: string
credentials: Array<OpenId4VcIssuanceSessionCredentialOptions>
credentials: Array<OpenId4VciOfferSdJwtCredential | OpenId4VciOfferMdocCredential | OpenId4VciOfferW3cCredential>
authorizationCodeFlowConfig?: {
authorizationServerUrl: string
requirePresentationDuringIssuance?: boolean
Expand Down
133 changes: 122 additions & 11 deletions src/routes/routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1463,34 +1463,71 @@ const models: TsoaRoute.Models = {
"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
"SignerMethod": {
"dataType": "refEnum",
"enums": ["did","x5c"],
"Record_string.boolean_": {
"dataType": "refAlias",
"type": {"dataType":"nestedObjectLiteral","nestedProperties":{},"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
"Record_string.boolean-or-Record_string.boolean__": {
"dataType": "refAlias",
"type": {"dataType":"nestedObjectLiteral","nestedProperties":{},"additionalProperties":{"dataType":"union","subSchemas":[{"dataType":"boolean"},{"ref":"Record_string.boolean_"}]},"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
"OpenId4VciCredentialFormatProfile": {
"dataType": "refEnum",
"enums": ["jwt_vc_json","jwt_vc_json-ld","ldp_vc","vc+sd-jwt","mso_mdoc"],
},
// 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
"Record_string.boolean_": {
"SignerMethod": {
"dataType": "refEnum",
"enums": ["did","x5c"],
},
// 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
"OpenId4VciOfferSdJwtCredential": {
"dataType": "refObject",
"properties": {
"credentialSupportedId": {"dataType":"string","required":true},
"format": {"ref":"OpenId4VciCredentialFormatProfile","required":true},
"signerOptions": {"dataType":"nestedObjectLiteral","nestedProperties":{"x5c":{"dataType":"array","array":{"dataType":"string"}},"did":{"dataType":"string"},"method":{"ref":"SignerMethod","required":true}},"required":true},
"payload": {"dataType":"nestedObjectLiteral","nestedProperties":{"vct":{"dataType":"string"}},"additionalProperties":{"dataType":"any"},"required":true},
"disclosureFrame": {"ref":"Record_string.boolean-or-Record_string.boolean__"},
},
"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
"Partial_ValidityInfo_": {
"dataType": "refAlias",
"type": {"dataType":"nestedObjectLiteral","nestedProperties":{},"validators":{}},
"type": {"dataType":"nestedObjectLiteral","nestedProperties":{"signed":{"dataType":"datetime"},"validFrom":{"dataType":"datetime"},"validUntil":{"dataType":"datetime"},"expectedUpdate":{"dataType":"datetime"}},"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
"Record_string.boolean-or-Record_string.boolean__": {
"Record_string.Record_string.unknown__": {
"dataType": "refAlias",
"type": {"dataType":"nestedObjectLiteral","nestedProperties":{},"additionalProperties":{"dataType":"union","subSchemas":[{"dataType":"boolean"},{"ref":"Record_string.boolean_"}]},"validators":{}},
"type": {"dataType":"nestedObjectLiteral","nestedProperties":{},"additionalProperties":{"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
"MdocNameSpaces": {
"dataType": "refAlias",
"type": {"ref":"Record_string.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
"OpenId4VcIssuanceSessionCredentialOptions": {
"OpenId4VciOfferMdocCredential": {
"dataType": "refObject",
"properties": {
"credentialSupportedId": {"dataType":"string","required":true},
"format": {"ref":"OpenId4VciCredentialFormatProfile","required":true},
"signerOptions": {"dataType":"nestedObjectLiteral","nestedProperties":{"x5c":{"dataType":"array","array":{"dataType":"string"}},"did":{"dataType":"string"},"method":{"ref":"SignerMethod","required":true}},"required":true},
"payload": {"dataType":"nestedObjectLiteral","nestedProperties":{"namespaces":{"ref":"MdocNameSpaces","required":true},"validityInfo":{"ref":"Partial_ValidityInfo_"},"docType":{"dataType":"union","subSchemas":[{"dataType":"enum","enums":["org.iso.18013.5.1.mDL"]},{"dataType":"intersection","subSchemas":[{"dataType":"string"},{"dataType":"nestedObjectLiteral","nestedProperties":{}}]}],"required":true}},"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
"OpenId4VciOfferW3cCredential": {
"dataType": "refObject",
"properties": {
"credentialSupportedId": {"dataType":"string","required":true},
"format": {"ref":"OpenId4VciCredentialFormatProfile","required":true},
"payload": {"dataType":"nestedObjectLiteral","nestedProperties":{"vct":{"dataType":"string"}},"additionalProperties":{"dataType":"any"},"required":true},
"disclosureFrame": {"ref":"Record_string.boolean-or-Record_string.boolean__"},
"signerOptions": {"dataType":"nestedObjectLiteral","nestedProperties":{"x5c":{"dataType":"array","array":{"dataType":"string"}},"did":{"dataType":"string"},"method":{"ref":"SignerMethod","required":true}},"required":true},
"payload": {"dataType":"nestedObjectLiteral","nestedProperties":{"credential":{"ref":"W3cCredential","required":true},"verificationMethod":{"dataType":"string","required":true}},"required":true},
},
"additionalProperties": false,
},
Expand All @@ -1499,7 +1536,7 @@ const models: TsoaRoute.Models = {
"dataType": "refObject",
"properties": {
"publicIssuerId": {"dataType":"string","required":true},
"credentials": {"dataType":"array","array":{"dataType":"refObject","ref":"OpenId4VcIssuanceSessionCredentialOptions"},"required":true},
"credentials": {"dataType":"array","array":{"dataType":"union","subSchemas":[{"ref":"OpenId4VciOfferSdJwtCredential"},{"ref":"OpenId4VciOfferMdocCredential"},{"ref":"OpenId4VciOfferW3cCredential"}]},"required":true},
"authorizationCodeFlowConfig": {"dataType":"nestedObjectLiteral","nestedProperties":{"issuerState":{"dataType":"string"},"requirePresentationDuringIssuance":{"dataType":"boolean"},"authorizationServerUrl":{"dataType":"string","required":true}}},
"preAuthorizedCodeFlowConfig": {"dataType":"nestedObjectLiteral","nestedProperties":{"authorizationServerUrl":{"dataType":"string","required":true},"txCode":{"dataType":"nestedObjectLiteral","nestedProperties":{"input_mode":{"dataType":"union","subSchemas":[{"dataType":"enum","enums":["numeric"]},{"dataType":"enum","enums":["text"]}]},"length":{"dataType":"double"},"description":{"dataType":"string"}}},"preAuthorizedCode":{"dataType":"string"}}},
"issuanceMetadata": {"ref":"Record_string.unknown_"},
Expand Down Expand Up @@ -4168,6 +4205,44 @@ 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
const argsMultiTenancyController_getTenants: Record<string, TsoaRoute.ParameterSchema> = {
request: {"in":"request","name":"request","required":true,"dataType":"object"},
notFoundError: {"in":"res","name":"404","required":true,"dataType":"nestedObjectLiteral","nestedProperties":{"reason":{"dataType":"string","required":true}}},
internalServerError: {"in":"res","name":"500","required":true,"dataType":"nestedObjectLiteral","nestedProperties":{"message":{"dataType":"string","required":true}}},
};
app.get('/multi-tenancy',
authenticateMiddleware([{"jwt":["Basewallet"]}]),
...(fetchMiddlewares<RequestHandler>(MultiTenancyController)),
...(fetchMiddlewares<RequestHandler>(MultiTenancyController.prototype.getTenants)),

async function MultiTenancyController_getTenants(request: ExRequest, response: ExResponse, next: 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: argsMultiTenancyController_getTenants, request, response });

const container: IocContainer = typeof iocContainer === 'function' ? (iocContainer as IocContainerFactory)(request) : iocContainer;

const controller: any = await container.get<MultiTenancyController>(MultiTenancyController);
if (typeof controller['setStatus'] === 'function') {
controller.setStatus(undefined);
}

await templateService.apiHandler({
methodName: 'getTenants',
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
const argsMultiTenancyController_deleteTenantById: Record<string, TsoaRoute.ParameterSchema> = {
request: {"in":"request","name":"request","required":true,"dataType":"object"},
tenantId: {"in":"path","name":"tenantId","required":true,"dataType":"string"},
Expand Down Expand Up @@ -4468,6 +4543,42 @@ 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
const argsHolderController_decodeMdocCredential: Record<string, TsoaRoute.ParameterSchema> = {
body: {"in":"body","name":"body","required":true,"dataType":"nestedObjectLiteral","nestedProperties":{"base64Url":{"dataType":"string","required":true}}},
};
app.post('/openid4vc/holder/mdoc-vcs/decode',
authenticateMiddleware([{"apiKey":[]}]),
...(fetchMiddlewares<RequestHandler>(HolderController)),
...(fetchMiddlewares<RequestHandler>(HolderController.prototype.decodeMdocCredential)),

async function HolderController_decodeMdocCredential(request: ExRequest, response: ExResponse, next: 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: argsHolderController_decodeMdocCredential, request, response });

const container: IocContainer = typeof iocContainer === 'function' ? (iocContainer as IocContainerFactory)(request) : iocContainer;

const controller: any = await container.get<HolderController>(HolderController);
if (typeof controller['setStatus'] === 'function') {
controller.setStatus(undefined);
}

await templateService.apiHandler({
methodName: 'decodeMdocCredential',
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
const argsHolderController_requestAuthorizationForCredential: Record<string, TsoaRoute.ParameterSchema> = {
body: {"in":"body","name":"body","required":true,"ref":"AuthorizeRequestCredentialOffer"},
};
Expand Down
Loading