From 5ccb87c1edae6ced9ba3d067c222ebc7f8f963ce Mon Sep 17 00:00:00 2001 From: Sadjad Khoshkhou Date: Thu, 19 Sep 2024 12:07:26 +0200 Subject: [PATCH] fix: small fixes for siop-oid4vp package --- .../authorization-request/AuthorizationRequest.ts | 12 ++++++++---- packages/siop-oid4vp/lib/helpers/Metadata.ts | 14 +++++--------- .../lib/request-object/RequestObject.ts | 12 ++++++------ packages/siop-oid4vp/lib/rp/Opts.ts | 5 +++-- 4 files changed, 22 insertions(+), 21 deletions(-) diff --git a/packages/siop-oid4vp/lib/authorization-request/AuthorizationRequest.ts b/packages/siop-oid4vp/lib/authorization-request/AuthorizationRequest.ts index 79972996..89201ea8 100644 --- a/packages/siop-oid4vp/lib/authorization-request/AuthorizationRequest.ts +++ b/packages/siop-oid4vp/lib/authorization-request/AuthorizationRequest.ts @@ -192,7 +192,7 @@ export class AuthorizationRequest { // TODO: we need to verify somewhere that if response_mode is direct_post, that the response_uri may be present, // BUT not both redirect_uri and response_uri. What is the best place to do this? - const presentationDefinitions = await PresentationExchange.findValidPresentationDefinitions(mergedPayload, await this.getSupportedVersion()) + const presentationDefinitions: PresentationDefinitionWithLocation[] = await PresentationExchange.findValidPresentationDefinitions(mergedPayload, await this.getSupportedVersion()) return { jwt, payload: parsedJwt?.payload, @@ -211,7 +211,7 @@ export class AuthorizationRequest { } } - static async verify(requestOrUri: string, verifyOpts: VerifyAuthorizationRequestOpts) { + static async verify(requestOrUri: string, verifyOpts: VerifyAuthorizationRequestOpts): Promise { assertValidVerifyAuthorizationRequestOpts(verifyOpts) const authorizationRequest = await AuthorizationRequest.fromUriOrJwt(requestOrUri) return await authorizationRequest.verify(verifyOpts) @@ -263,10 +263,14 @@ export class AuthorizationRequest { } public async mergedPayloads(): Promise { - return { ...this.payload, ...(this.requestObject && (await this.requestObject.getPayload())) } + const requestObjectPayload = { ...this.payload, ...(this.requestObject && (await this.requestObject.getPayload())) } + if (typeof requestObjectPayload.scope !== 'string') { + throw new Error('Invalid scope value') + } + return requestObjectPayload as RequestObjectPayload } - public async getPresentationDefinitions(version?: SupportedVersion): Promise { + public async getPresentationDefinitions(version?: SupportedVersion): Promise { return await PresentationExchange.findValidPresentationDefinitions(await this.mergedPayloads(), version) } } diff --git a/packages/siop-oid4vp/lib/helpers/Metadata.ts b/packages/siop-oid4vp/lib/helpers/Metadata.ts index c27f2624..30368657 100644 --- a/packages/siop-oid4vp/lib/helpers/Metadata.ts +++ b/packages/siop-oid4vp/lib/helpers/Metadata.ts @@ -86,18 +86,14 @@ function supportedSubjectSyntaxTypes(rpMethods: string[] | string, opMethods: st export function collectAlgValues(o: any): string[] { const algValues: string[] = []; - for (const value of Object.values(o)) { - if (value) { + for (const key of Object.keys(o)) { // Check if the object has an 'alg' property that's an array of strings - if (Array.isArray((value as any).alg)) { - algValues.push(...(value as any).alg); + if (key === 'alg' && Array.isArray(o.alg)) { + algValues.push(...o.alg); } - - // Check for the special case 'sd-jwt_alg_values' - if (Array.isArray((value as any)['sd-jwt_alg_values'])) { - algValues.push(...(value as any)['sd-jwt_alg_values']); + else if (key === 'sd-jwt_alg_values' && Array.isArray(o['sd-jwt_alg_values'])) { + algValues.push(...o['sd-jwt_alg_values']); } - } } return algValues; diff --git a/packages/siop-oid4vp/lib/request-object/RequestObject.ts b/packages/siop-oid4vp/lib/request-object/RequestObject.ts index fba9bcb1..bd9ecbae 100644 --- a/packages/siop-oid4vp/lib/request-object/RequestObject.ts +++ b/packages/siop-oid4vp/lib/request-object/RequestObject.ts @@ -37,11 +37,11 @@ export class RequestObject { * part of the URI and which become part of the Request Object. If you generate a URI based upon the result of this class, * the URI will be constructed based on the Request Object only! */ - public static async fromOpts(authorizationRequestOpts: CreateAuthorizationRequestOpts) { + public static async fromOpts(authorizationRequestOpts: CreateAuthorizationRequestOpts): Promise { assertValidAuthorizationRequestOpts(authorizationRequestOpts) const createJwtCallback = authorizationRequestOpts.requestObject.createJwtCallback // We copy the signature separately as it can contain a function, which would be removed in the merge function below - const jwtIssuer = authorizationRequestOpts.requestObject.jwtIssuer // We copy the signature separately as it can contain a function, which would be removed in the merge function below - const requestObjectOpts = RequestObject.mergeOAuth2AndOpenIdProperties(authorizationRequestOpts) + const jwtIssuer: JwtIssuer = authorizationRequestOpts.requestObject.jwtIssuer // We copy the signature separately as it can contain a function, which would be removed in the merge function below + const requestObjectOpts: RequestObjectOpts = RequestObject.mergeOAuth2AndOpenIdProperties(authorizationRequestOpts) const mergedOpts = { ...authorizationRequestOpts, requestObject: { ...authorizationRequestOpts.requestObject, ...requestObjectOpts, createJwtCallback, jwtIssuer }, @@ -49,17 +49,17 @@ export class RequestObject { return new RequestObject(mergedOpts, await createRequestObjectPayload(mergedOpts)) } - public static async fromJwt(requestObjectJwt: RequestObjectJwt) { + public static async fromJwt(requestObjectJwt: RequestObjectJwt): Promise { return requestObjectJwt ? new RequestObject(undefined, undefined, requestObjectJwt) : undefined } - public static async fromPayload(requestObjectPayload: RequestObjectPayload, authorizationRequestOpts: CreateAuthorizationRequestOpts) { + public static async fromPayload(requestObjectPayload: RequestObjectPayload, authorizationRequestOpts: CreateAuthorizationRequestOpts): Promise { return new RequestObject(authorizationRequestOpts, requestObjectPayload) } public static async fromAuthorizationRequestPayload(payload: AuthorizationRequestPayload): Promise { const requestObjectJwt = - payload.request || payload.request_uri ? await fetchByReferenceOrUseByValue(payload.request_uri, payload.request, true) : undefined + payload.request ?? payload.request_uri ? await fetchByReferenceOrUseByValue(payload.request_uri as string, payload.request, true) : undefined return requestObjectJwt ? await RequestObject.fromJwt(requestObjectJwt) : undefined } diff --git a/packages/siop-oid4vp/lib/rp/Opts.ts b/packages/siop-oid4vp/lib/rp/Opts.ts index 952bcddd..b1a34e0e 100644 --- a/packages/siop-oid4vp/lib/rp/Opts.ts +++ b/packages/siop-oid4vp/lib/rp/Opts.ts @@ -1,4 +1,4 @@ -import { defaultHasher } from '@sphereon/oid4vc-common' +import { defaultHasher, uuidv4 } from '@sphereon/oid4vc-common' import { CreateAuthorizationRequestOpts, PropertyTarget, PropertyTargets, RequestPropertyWithTargets } from '../authorization-request' import { VerifyAuthorizationResponseOpts } from '../authorization-response' @@ -48,10 +48,11 @@ export const createRequestOptsFromBuilderOrExistingOpts = (opts: { builder?: RPB return createRequestOpts } -export const createVerifyResponseOptsFromBuilderOrExistingOpts = (opts: { builder?: RPBuilder; verifyOpts?: VerifyAuthorizationResponseOpts }) => { +export const createVerifyResponseOptsFromBuilderOrExistingOpts = (opts: { builder?: RPBuilder; verifyOpts?: VerifyAuthorizationResponseOpts }):VerifyAuthorizationResponseOpts => { return opts.builder ? { hasher: opts.builder.hasher ?? defaultHasher, + correlationId: uuidv4(), verifyJwtCallback: opts.builder.verifyJwtCallback, verification: { presentationVerificationCallback: opts.builder.presentationVerificationCallback,