From e572faf30b9dd8228d6f6970ed5476e47d69d53f Mon Sep 17 00:00:00 2001 From: PuBHARGAVI <46226958+PuBHARGAVI@users.noreply.github.com> Date: Fri, 13 Dec 2024 11:30:44 +0530 Subject: [PATCH] [INJIMOB-2538] fetch the openid4vp sharing flow client validation property from inji default properties file and pass it to library (#1739) * [INJIMOB-2538] fetch whether we should do client validation or not in VP sharing flow based on the value assigned in inji config default properties file Signed-off-by: PuBHARGAVI <46226958+PuBHARGAVI@users.noreply.github.com> * [INJIMOB-2538] convert clientValidation property from string to boolean before passing it to library Signed-off-by: PuBHARGAVI <46226958+PuBHARGAVI@users.noreply.github.com> * [INJIMOB-2538] change the logic of checking the value of clientValidation property Signed-off-by: PuBHARGAVI <46226958+PuBHARGAVI@users.noreply.github.com> * [INJIMOB-2538] rename clientValidation variable to shouldValiateClient and call verifiers api only if validation is required Signed-off-by: PuBHARGAVI <46226958+PuBHARGAVI@users.noreply.github.com> * [INJIMOB-2538] check if client validation is needed or not as part of service instead of action Signed-off-by: PuBHARGAVI <46226958+PuBHARGAVI@users.noreply.github.com> * [INJIMOB-2538] update Package.resolved Signed-off-by: Abhishek Paul --------- Signed-off-by: PuBHARGAVI <46226958+PuBHARGAVI@users.noreply.github.com> Signed-off-by: Abhishek Paul Co-authored-by: Abhishek Paul --- .../residentapp/InjiOpenID4VPModule.java | 3 ++- .../xcshareddata/swiftpm/Package.resolved | 13 ++++++++-- ios/RNOpenID4VPModule.m | 1 + ios/RNOpenID4VPModule.swift | 3 ++- machines/openID4VP/openID4VPGuards.ts | 3 +++ machines/openID4VP/openID4VPMachine.ts | 24 ++++++++++++++----- .../openID4VP/openID4VPMachine.typegen.ts | 23 ++++++++++++++---- machines/openID4VP/openID4VPServices.ts | 5 ++++ shared/openID4VP/OpenID4VP.ts | 9 +++++++ 9 files changed, 69 insertions(+), 15 deletions(-) diff --git a/android/app/src/main/java/io/mosip/residentapp/InjiOpenID4VPModule.java b/android/app/src/main/java/io/mosip/residentapp/InjiOpenID4VPModule.java index a4d3f9ac10..22817704ae 100644 --- a/android/app/src/main/java/io/mosip/residentapp/InjiOpenID4VPModule.java +++ b/android/app/src/main/java/io/mosip/residentapp/InjiOpenID4VPModule.java @@ -51,10 +51,11 @@ public void init(String appId) { @ReactMethod public void authenticateVerifier(String encodedAuthorizationRequest, ReadableArray trustedVerifiers, + Boolean shouldValidateClient, Promise promise) { try { AuthorizationRequest authenticationResponse = openID4VP.authenticateVerifier(encodedAuthorizationRequest, - convertReadableArrayToVerifierArray(trustedVerifiers)); + convertReadableArrayToVerifierArray(trustedVerifiers), shouldValidateClient); String authenticationResponseAsJson = gson.toJson(authenticationResponse, AuthorizationRequest.class); promise.resolve(authenticationResponseAsJson); } catch (Exception exception) { diff --git a/ios/Inji.xcworkspace/xcshareddata/swiftpm/Package.resolved b/ios/Inji.xcworkspace/xcshareddata/swiftpm/Package.resolved index f5e06df08d..d1e192305b 100644 --- a/ios/Inji.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/ios/Inji.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -1,5 +1,5 @@ { - "originHash" : "6b82a714050e22d309e029aaffac33f021c04aac740f661a9879441a7d414f4f", + "originHash" : "178f6c7c607eeb08b99a4966015d08339500de64791888a2e79d6b7afae53659", "pins" : [ { "identity" : "base45-swift", @@ -34,7 +34,7 @@ "location" : "https://github.com/mosip/inji-openid4vp-ios-swift", "state" : { "branch" : "develop", - "revision" : "20c1a6c314b73d303ce7c5f2b6ba94235dcb68ad" + "revision" : "10c161f4e7414e8a7b0dc2d52d3f4d8faf19b8d7" } }, { @@ -81,6 +81,15 @@ "branch" : "develop", "revision" : "96bc662cd07df051cf2357691469bba57b0217e8" } + }, + { + "identity" : "zipfoundation", + "kind" : "remoteSourceControl", + "location" : "https://github.com/weichsel/ZIPFoundation.git", + "state" : { + "revision" : "02b6abe5f6eef7e3cbd5f247c5cc24e246efcfe0", + "version" : "0.9.19" + } } ], "version" : 2 diff --git a/ios/RNOpenID4VPModule.m b/ios/RNOpenID4VPModule.m index 3d491ff41c..3186ef917f 100644 --- a/ios/RNOpenID4VPModule.m +++ b/ios/RNOpenID4VPModule.m @@ -7,6 +7,7 @@ @interface RCT_EXTERN_MODULE(InjiOpenID4VP, NSObject) RCT_EXTERN_METHOD(authenticateVerifier:(NSString *)encodedAuthorizationRequest trustedVerifierJSON:(id)trustedVerifierJSON + shouldValidateClient:(BOOL)shouldValidateClient resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) diff --git a/ios/RNOpenID4VPModule.swift b/ios/RNOpenID4VPModule.swift index b07390da99..daaaa2996d 100644 --- a/ios/RNOpenID4VPModule.swift +++ b/ios/RNOpenID4VPModule.swift @@ -19,6 +19,7 @@ class RNOpenId4VpModule: NSObject, RCTBridgeModule { @objc func authenticateVerifier(_ encodedAuthorizationRequest: String, trustedVerifierJSON: AnyObject, + shouldValidateClient: Bool, resolver resolve: @escaping RCTPromiseResolveBlock, rejecter reject: @escaping RCTPromiseRejectBlock) { Task { @@ -36,7 +37,7 @@ class RNOpenId4VpModule: NSObject, RCTBridgeModule { return Verifier(clientId: clientId, responseUris: responseUris) } - let authenticationResponse: AuthorizationRequest = try await openID4VP!.authenticateVerifier(encodedAuthorizationRequest: encodedAuthorizationRequest, trustedVerifierJSON: trustedVerifiersList) + let authenticationResponse: AuthorizationRequest = try await openID4VP!.authenticateVerifier(encodedAuthorizationRequest: encodedAuthorizationRequest, trustedVerifierJSON: trustedVerifiersList, shouldValidateClient: shouldValidateClient) let response = try toJsonString(jsonObject: authenticationResponse) resolve(response) diff --git a/machines/openID4VP/openID4VPGuards.ts b/machines/openID4VP/openID4VPGuards.ts index 8e4c4a571e..85113ac45e 100644 --- a/machines/openID4VP/openID4VPGuards.ts +++ b/machines/openID4VP/openID4VPGuards.ts @@ -1,3 +1,4 @@ +import {isClientValidationRequired} from '../../shared/openID4VP/OpenID4VP'; import {VCShareFlowType} from '../../shared/Utils'; export const openID4VPGuards = () => { @@ -32,5 +33,7 @@ export const openID4VPGuards = () => { isFaceVerificationRetryAttempt: (context: any) => context.isFaceVerificationRetryAttempt, + + isClientValidationRequred: (_, event) => event.data, }; }; diff --git a/machines/openID4VP/openID4VPMachine.ts b/machines/openID4VP/openID4VPMachine.ts index f2f47f4a1c..21eae89f60 100644 --- a/machines/openID4VP/openID4VPMachine.ts +++ b/machines/openID4VP/openID4VPMachine.ts @@ -52,16 +52,28 @@ export const openID4VPMachine = model.createMachine( }, }, checkFaceAuthConsent: { - entry: 'getFaceAuthConsent', + entry: ['setIsShowLoadingScreen', 'getFaceAuthConsent'], on: { - STORE_RESPONSE: { - actions: 'updateShowFaceAuthConsent', - target: 'getTrustedVerifiersList', - }, + STORE_RESPONSE: {target: 'checkIfClientValidationIsRequired'}, + }, + }, + checkIfClientValidationIsRequired: { + invoke: { + src: 'shouldValidateClient', + onDone: [ + { + cond: 'isClientValidationRequred', + actions: 'updateShowFaceAuthConsent', + target: 'getTrustedVerifiersList', + }, + { + actions: 'updateShowFaceAuthConsent', + target: 'getKeyPairFromKeystore', + }, + ], }, }, getTrustedVerifiersList: { - entry: 'setIsShowLoadingScreen', invoke: { src: 'fetchTrustedVerifiers', onDone: { diff --git a/machines/openID4VP/openID4VPMachine.typegen.ts b/machines/openID4VP/openID4VPMachine.typegen.ts index 6c43e9ebff..5b256cbd07 100644 --- a/machines/openID4VP/openID4VPMachine.typegen.ts +++ b/machines/openID4VP/openID4VPMachine.typegen.ts @@ -8,6 +8,11 @@ export interface Typegen0 { data: unknown; __tip: 'See the XState TS docs to learn how to strongly type this.'; }; + 'done.invoke.OpenID4VP.checkIfClientValidationIsRequired:invocation[0]': { + type: 'done.invoke.OpenID4VP.checkIfClientValidationIsRequired:invocation[0]'; + data: unknown; + __tip: 'See the XState TS docs to learn how to strongly type this.'; + }; 'done.invoke.OpenID4VP.checkKeyPair:invocation[0]': { type: 'done.invoke.OpenID4VP.checkKeyPair:invocation[0]'; data: unknown; @@ -57,6 +62,7 @@ export interface Typegen0 { getKeyPair: 'done.invoke.OpenID4VP.getKeyPairFromKeystore:invocation[0]'; getSelectedKey: 'done.invoke.OpenID4VP.checkKeyPair:invocation[0]'; sendVP: 'done.invoke.OpenID4VP.sendingVP:invocation[0]'; + shouldValidateClient: 'done.invoke.OpenID4VP.checkIfClientValidationIsRequired:invocation[0]'; }; missingImplementations: { actions: @@ -96,6 +102,7 @@ export interface Typegen0 { guards: | 'hasKeyPair' | 'isAnyVCHasImage' + | 'isClientValidationRequred' | 'isFaceVerificationRetryAttempt' | 'isSelectedVCMatchingRequest' | 'isShareWithSelfie' @@ -106,7 +113,8 @@ export interface Typegen0 { | 'getAuthenticationResponse' | 'getKeyPair' | 'getSelectedKey' - | 'sendVP'; + | 'sendVP' + | 'shouldValidateClient'; }; eventsCausingActions: { compareAndStoreSelectedVC: 'SET_SELECTED_VC'; @@ -135,7 +143,7 @@ export interface Typegen0 { setFlowType: 'AUTHENTICATE'; setIsFaceVerificationRetryAttempt: 'FACE_INVALID'; setIsShareWithSelfie: 'AUTHENTICATE'; - setIsShowLoadingScreen: 'STORE_RESPONSE'; + setIsShowLoadingScreen: 'AUTHENTICATE'; setMiniViewShareSelectedVC: 'AUTHENTICATE'; setSelectedVCs: 'ACCEPT_REQUEST' | 'VERIFY_AND_ACCEPT_REQUEST'; setSendVPShareError: 'error.platform.OpenID4VP.sendingVP:invocation[0]'; @@ -146,7 +154,7 @@ export interface Typegen0 { shareDeclineStatus: 'CONFIRM'; storeShowFaceAuthConsent: 'FACE_VERIFICATION_CONSENT'; updateFaceCaptureBannerStatus: 'FACE_VALID'; - updateShowFaceAuthConsent: 'STORE_RESPONSE'; + updateShowFaceAuthConsent: 'done.invoke.OpenID4VP.checkIfClientValidationIsRequired:invocation[0]'; }; eventsCausingDelays: { SHARING_TIMEOUT: 'CONFIRM' | 'FACE_VALID' | 'RETRY'; @@ -156,6 +164,7 @@ export interface Typegen0 { | 'FACE_VALID' | 'done.invoke.OpenID4VP.checkKeyPair:invocation[0]'; isAnyVCHasImage: 'CHECK_FOR_IMAGE'; + isClientValidationRequred: 'done.invoke.OpenID4VP.checkIfClientValidationIsRequired:invocation[0]'; isFaceVerificationRetryAttempt: 'FACE_INVALID'; isSelectedVCMatchingRequest: 'CHECK_SELECTED_VC'; isShareWithSelfie: @@ -170,18 +179,22 @@ export interface Typegen0 { showFaceAuthConsentScreen: 'CONFIRM'; }; eventsCausingServices: { - fetchTrustedVerifiers: 'STORE_RESPONSE'; + fetchTrustedVerifiers: 'done.invoke.OpenID4VP.checkIfClientValidationIsRequired:invocation[0]'; getAuthenticationResponse: 'done.invoke.OpenID4VP.checkKeyPair:invocation[0]'; - getKeyPair: 'done.invoke.OpenID4VP.getTrustedVerifiersList:invocation[0]'; + getKeyPair: + | 'done.invoke.OpenID4VP.checkIfClientValidationIsRequired:invocation[0]' + | 'done.invoke.OpenID4VP.getTrustedVerifiersList:invocation[0]'; getSelectedKey: | 'FACE_VALID' | 'done.invoke.OpenID4VP.getKeyPairFromKeystore:invocation[0]'; sendVP: 'CONFIRM' | 'FACE_VALID' | 'RETRY'; + shouldValidateClient: 'STORE_RESPONSE'; }; matchesStates: | 'authenticateVerifier' | 'checkFaceAuthConsent' | 'checkIfAnySelectedVCHasImage' + | 'checkIfClientValidationIsRequired' | 'checkIfMatchingVCsHasSelectedVC' | 'checkKeyPair' | 'faceVerificationConsent' diff --git a/machines/openID4VP/openID4VPServices.ts b/machines/openID4VP/openID4VPServices.ts index 31dae30927..8234880e9c 100644 --- a/machines/openID4VP/openID4VPServices.ts +++ b/machines/openID4VP/openID4VPServices.ts @@ -3,6 +3,7 @@ import {fetchKeyPair} from '../../shared/cryptoutil/cryptoUtil'; import {hasKeyPair} from '../../shared/openId4VCI/Utils'; import { constructProofJWT, + isClientValidationRequired, OpenID4VP, OpenID4VP_Domain, OpenID4VP_Proof_Algo_Type, @@ -14,6 +15,10 @@ export const openID4VPServices = () => { return await CACHED_API.fetchTrustedVerifiersList(); }, + shouldValidateClient: async () => { + return await isClientValidationRequired(); + }, + getAuthenticationResponse: (context: any) => async () => { OpenID4VP.initialize(); const serviceRes = await OpenID4VP.authenticateVerifier( diff --git a/shared/openID4VP/OpenID4VP.ts b/shared/openID4VP/OpenID4VP.ts index e5501dbde8..6005d3eb41 100644 --- a/shared/openID4VP/OpenID4VP.ts +++ b/shared/openID4VP/OpenID4VP.ts @@ -3,6 +3,7 @@ import {__AppId} from '../GlobalVariables'; import {VC} from '../../machines/VerifiableCredential/VCMetaMachine/vc'; import {getJWT} from '../cryptoutil/cryptoUtil'; import {getJWK} from '../openId4VCI/Utils'; +import getAllConfigurations from '../api'; export const OpenID4VP_Key_Ref = 'OpenID4VP_KeyPair'; export const OpenID4VP_Proof_Algo_Type = 'RsaSignature2018'; @@ -19,10 +20,13 @@ export class OpenID4VP { encodedAuthorizationRequest: string, trustedVerifiersList: any, ) { + const shouldValidateClient = await isClientValidationRequired(); + const authenticationResponse = await OpenID4VP.InjiOpenID4VP.authenticateVerifier( encodedAuthorizationRequest, trustedVerifiersList, + shouldValidateClient, ); return JSON.parse(authenticationResponse); } @@ -89,3 +93,8 @@ function createJwtPayload(vpToken: {[key: string]: any}) { holder, }; } + +export async function isClientValidationRequired() { + const config = await getAllConfigurations(); + return config.openid4vpClientValidation === 'true'; +}