From fcc78ce04836e7352137d5647b84f1eaf2432429 Mon Sep 17 00:00:00 2001 From: kkmanos Date: Thu, 28 Mar 2024 11:38:44 +0200 Subject: [PATCH] exposed HandleOutboudRequestError --- src/routers/communicationHandler.router.ts | 7 +++++-- src/services/OpenidForPresentationService.ts | 19 +++++++++++-------- src/services/interfaces.ts | 5 ++++- 3 files changed, 20 insertions(+), 11 deletions(-) diff --git a/src/routers/communicationHandler.router.ts b/src/routers/communicationHandler.router.ts index 7fcbc9e..e0490e0 100644 --- a/src/routers/communicationHandler.router.ts +++ b/src/routers/communicationHandler.router.ts @@ -3,7 +3,7 @@ import express, { Router } from 'express'; import { AuthMiddleware } from '../middlewares/auth.middleware'; import _ from 'lodash'; import { appContainer } from '../services/inversify.config'; -import { IssuanceErr, OpenidCredentialReceiving, OutboundCommunication } from '../services/interfaces'; +import { HandleOutboundRequestError, IssuanceErr, OpenidCredentialReceiving, OutboundCommunication } from '../services/interfaces'; import { TYPES } from '../services/types'; import * as z from 'zod'; @@ -107,7 +107,10 @@ communicationHandlerRouter.post('/handle', async (req, res) => { try { const outboundRequestResult = await openidForPresentationService.handleRequest(req.user.did, url, camera_was_used); if (!outboundRequestResult.ok) { - throw new Error("handling SIOP request failed"); + if (outboundRequestResult.val == HandleOutboundRequestError.INSUFFICIENT_CREDENTIALS) { + return res.send({ error: HandleOutboundRequestError.INSUFFICIENT_CREDENTIALS }); + } + throw new Error("Failed to handle outbound request") } const outboundRequest = outboundRequestResult.val; console.log("Outbound request = ", outboundRequest) diff --git a/src/services/OpenidForPresentationService.ts b/src/services/OpenidForPresentationService.ts index 35ffae6..749de6a 100644 --- a/src/services/OpenidForPresentationService.ts +++ b/src/services/OpenidForPresentationService.ts @@ -8,7 +8,7 @@ import { z } from 'zod'; import { Err, Ok, Result } from "ts-results"; import { InputDescriptorType, Verify } from "@wwwallet/ssi-sdk"; -import { OpenidCredentialReceiving, OutboundCommunication, WalletKeystore, WalletKeystoreErr } from "./interfaces"; +import { HandleOutboundRequestError, OpenidCredentialReceiving, OutboundCommunication, WalletKeystore, WalletKeystoreErr } from "./interfaces"; import { TYPES } from "./types"; import { OutboundRequest } from "./types/OutboundRequest"; import { getAllVerifiableCredentials } from "../entities/VerifiableCredential.entity"; @@ -32,6 +32,7 @@ type PresentationDefinition = { } + const authorizationRequestSchema = z.object({ client_id: z.string(), response_type: z.string(), @@ -110,7 +111,7 @@ export class OpenidForPresentationService implements OutboundCommunication { return { redirect_to: url.toString() }; } - async handleRequest(userDid: string, requestURL: string, camera_was_used: boolean): Promise> { + async handleRequest(userDid: string, requestURL: string, camera_was_used: boolean): Promise> { try { return await this.parseIdTokenRequest(userDid, requestURL); } @@ -125,7 +126,11 @@ export class OpenidForPresentationService implements OutboundCommunication { const jsonParams = Object.fromEntries(paramEntries); authorizationRequestSchema.parse(jsonParams); // will throw error if input is not conforming to the schema this.states.set(userDid, { camera_was_used: camera_was_used }) - const { conformantCredentialsMap, verifierDomainName } = await this.parseAuthorizationRequest(userDid, requestURL); + const result = await this.parseAuthorizationRequest(userDid, requestURL); + if (result.err) { + return Err(result.val); + } + const { conformantCredentialsMap, verifierDomainName } = result.unwrap(); console.log("Handle VP Req = " , { conformantCredentialsMap, verifierDomainName }) return Ok({ conformantCredentialsMap: conformantCredentialsMap, @@ -254,7 +259,7 @@ export class OpenidForPresentationService implements OutboundCommunication { * @param authorizationRequestURL * @returns */ - private async parseAuthorizationRequest(userDid: string, authorizationRequestURL: string): Promise<{conformantCredentialsMap: Map, verifierDomainName: string}> { + private async parseAuthorizationRequest(userDid: string, authorizationRequestURL: string): Promise, verifierDomainName: string}, HandleOutboundRequestError>> { console.log("parseAuthorizationRequest userDid = ", userDid) const { did } = (await getUserByDID(userDid)).unwrap(); let client_id: string, @@ -339,9 +344,7 @@ export class OpenidForPresentationService implements OutboundCommunication { } } if (conformingVcList.length == 0) { - // throw "No conformant credential was found for at least one descriptor"; - console.log("No conformant credentials were found"); - continue; + return Err(HandleOutboundRequestError.INSUFFICIENT_CREDENTIALS); } const requestedFieldNames = descriptor.constraints.fields .map((field) => field.path) @@ -358,7 +361,7 @@ export class OpenidForPresentationService implements OutboundCommunication { throw new Error("Credentials don't satisfy any descriptor"); } console.log("Mapping = ", mapping) - return { conformantCredentialsMap: mapping, verifierDomainName: verifierDomainName } + return Ok({ conformantCredentialsMap: mapping, verifierDomainName: verifierDomainName }) } catch(error) { throw new Error(`Error verifying credentials meeting requirements from input_descriptors: ${error}`) diff --git a/src/services/interfaces.ts b/src/services/interfaces.ts index 1a3d375..7a15810 100644 --- a/src/services/interfaces.ts +++ b/src/services/interfaces.ts @@ -22,6 +22,9 @@ export enum IssuanceErr { STATE_NOT_FOUND = "STATE_NOT_FOUND", } +export enum HandleOutboundRequestError { + INSUFFICIENT_CREDENTIALS = "INSUFFICIENT_CREDENTIALS", +} export type AdditionalKeystoreParameters = { @@ -62,7 +65,7 @@ export enum WalletKeystoreErr { export interface OutboundCommunication { initiateVerificationFlow(username: string, verifierId: number, scopeName: string): Promise<{ redirect_to?: string }>; - handleRequest(userDid: string, requestURL: string, camera_was_used: boolean): Promise>; + handleRequest(userDid: string, requestURL: string, camera_was_used: boolean): Promise>; /** *