[INJIMOB-3550] | [INJIMOB-3551] : refactor: replace OVP shareVerifiablePresentation with sendAuthorizationResponseToVerifier (#2104)

* [INJIMOB-3550] refactor: update ovp java module to use sendAuthorizationResponse instead of shareVerifiablePresentation

Signed-off-by: KiruthikaJeyashankar <kiruthikavjshankar@gmail.com>

* [INJIMOB-3551] refactor: modify ovp swift native module

Signed-off-by: KiruthikaJeyashankar <kiruthikavjshankar@gmail.com>

* [INJIMOB-3550] refactor: modify sendError to verifier as fire and forget call

Signed-off-by: KiruthikaJeyashankar <kiruthikavjshankar@gmail.com>

* [INJIMOB-3550] refactor: modify error's verifier response param from native module

Signed-off-by: KiruthikaJeyashankar <kiruthikavjshankar@gmail.com>

* [INJIMOB-3550] refactor: modiy error message for verifier returning non 200 response

Signed-off-by: KiruthikaJeyashankar <kiruthikavjshankar@gmail.com>

* [INJIMOB-3550] fix: app stuck on loading - trusted verifiers api failure

Signed-off-by: KiruthikaJeyashankar <kiruthikavjshankar@gmail.com>

* [INJIMOB-3550] refactor: modify verifier response parsing

Signed-off-by: KiruthikaJeyashankar <kiruthikavjshankar@gmail.com>

* [INJIMOB-3551] chore: update inji-openid4vp-ios-swift lib version

Signed-off-by: KiruthikaJeyashankar <kiruthikavjshankar@gmail.com>

* [INJIMOB-3534] chore: update inji-openid4vp-ios-swift version

Signed-off-by: KiruthikaJeyashankar <kiruthikavjshankar@gmail.com>

---------

Signed-off-by: KiruthikaJeyashankar <kiruthikavjshankar@gmail.com>
This commit is contained in:
KiruthikaJeyashankar
2025-10-15 15:49:21 +05:30
committed by GitHub
parent 066833d3c7
commit dad7417fdb
15 changed files with 120 additions and 41 deletions

View File

@@ -1,10 +1,12 @@
package io.mosip.residentapp;
import static io.mosip.openID4VP.authorizationResponse.AuthorizationResponseUtilsKt.toJsonString;
import static io.mosip.openID4VP.common.OpenID4VPErrorCodes.ACCESS_DENIED;
import static io.mosip.openID4VP.common.OpenID4VPErrorCodes.INVALID_TRANSACTION_DATA;
import static io.mosip.openID4VP.constants.FormatType.DC_SD_JWT;
import static io.mosip.openID4VP.constants.FormatType.LDP_VC;
import static io.mosip.openID4VP.constants.FormatType.MSO_MDOC;
import static io.mosip.openID4VP.constants.FormatType.VC_SD_JWT;
import static io.mosip.openID4VP.constants.FormatType.DC_SD_JWT;
import android.annotation.SuppressLint;
import android.util.Log;
@@ -26,31 +28,17 @@ import com.google.gson.FieldNamingPolicy;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import io.mosip.openID4VP.authorizationRequest.clientMetadata.ClientMetadata;
import io.mosip.openID4VP.authorizationRequest.clientMetadata.ClientMetadataSerializer;
import io.mosip.openID4VP.authorizationRequest.clientMetadata.Jwks;
import io.mosip.openID4VP.constants.ClientIdScheme;
import io.mosip.openID4VP.constants.ContentEncryptionAlgorithm;
import io.mosip.openID4VP.constants.KeyManagementAlgorithm;
import io.mosip.openID4VP.constants.RequestSigningAlgorithm;
import io.mosip.openID4VP.constants.ResponseType;
import io.mosip.openID4VP.constants.VPFormatType;
import io.mosip.openID4VP.exceptions.OpenID4VPExceptions;
import static io.mosip.openID4VP.common.OpenID4VPErrorCodes.ACCESS_DENIED;
import static io.mosip.openID4VP.common.OpenID4VPErrorCodes.INVALID_TRANSACTION_DATA;
import org.json.JSONArray;
import org.json.JSONObject;
import java.util.ArrayList;
import java.util.Collections;
import java.util.EnumMap;
import java.util.function.Function;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.Function;
import io.mosip.openID4VP.OpenID4VP;
import io.mosip.openID4VP.authorizationRequest.AuthorizationRequest;
@@ -63,9 +51,15 @@ import io.mosip.openID4VP.authorizationResponse.vpTokenSigningResult.types.ldp.L
import io.mosip.openID4VP.authorizationResponse.vpTokenSigningResult.types.mdoc.DeviceAuthentication;
import io.mosip.openID4VP.authorizationResponse.vpTokenSigningResult.types.mdoc.MdocVPTokenSigningResult;
import io.mosip.openID4VP.authorizationResponse.vpTokenSigningResult.types.sdJwt.SdJwtVPTokenSigningResult;
import io.mosip.openID4VP.constants.ClientIdScheme;
import io.mosip.openID4VP.constants.ContentEncryptionAlgorithm;
import io.mosip.openID4VP.constants.FormatType;
import io.mosip.openID4VP.constants.KeyManagementAlgorithm;
import io.mosip.openID4VP.constants.RequestSigningAlgorithm;
import io.mosip.openID4VP.constants.ResponseType;
import io.mosip.openID4VP.constants.VPFormatType;
import io.mosip.openID4VP.exceptions.OpenID4VPExceptions;
import io.mosip.openID4VP.networkManager.NetworkResponse;
import kotlinx.serialization.json.Json;
public class InjiOpenID4VPModule extends ReactContextBaseJavaModule {
private static final String TAG = "InjiOpenID4VPModule";
@@ -135,20 +129,22 @@ public class InjiOpenID4VPModule extends ReactContextBaseJavaModule {
public void shareVerifiablePresentation(ReadableMap vpTokenSigningResultMap, Promise promise) {
try {
Map<FormatType, VPTokenSigningResult> authContainer = parseVPTokenSigningResult(vpTokenSigningResultMap);
String response = openID4VP.shareVerifiablePresentation(authContainer);
promise.resolve(response);
NetworkResponse verifierResponse = openID4VP.sendAuthorizationResponseToVerifier(authContainer);
String verifierResponseJson = gson.toJson(verifierResponse, NetworkResponse.class);
promise.resolve(verifierResponseJson);
} catch (Exception e) {
rejectWithOpenID4VPExceptions(e, promise);
}
}
@ReactMethod
private static void rejectWithOpenID4VPExceptions(Exception e, Promise promise) {
private void rejectWithOpenID4VPExceptions(Exception e, Promise promise) {
if (e instanceof OpenID4VPExceptions exception) {
WritableMap errorMap = Arguments.createMap();
errorMap.putString("errorCode", exception.getErrorCode());
errorMap.putString("message", exception.getMessage());
errorMap.putString("response", exception.getResponse());
errorMap.putString("response", gson.toJson(exception.getNetworkResponse()));
promise.reject(exception.getErrorCode(), exception.getMessage(), exception, errorMap);
} else {
@@ -173,8 +169,10 @@ public class InjiOpenID4VPModule extends ReactContextBaseJavaModule {
break;
}
String verifierResponse = openID4VP.sendErrorResponseToVerifier(exception);
promise.resolve(verifierResponse);
NetworkResponse verifierResponse = openID4VP.sendErrorResponseToVerifier(exception);
String verifierResponseJson = gson.toJson(verifierResponse, NetworkResponse.class);
promise.resolve(verifierResponseJson);
} catch (Exception exception) {
rejectWithOpenID4VPExceptions(exception, promise);
}

View File

@@ -79,7 +79,7 @@
"location" : "https://github.com/mosip/inji-openid4vp-ios-swift.git",
"state" : {
"branch" : "develop",
"revision" : "9a2551d1a936c53e80e4ade6122543d606a99504"
"revision" : "01fa8c01f5b9ee16b5377073f061ca0186288df4"
}
},
{

View File

@@ -161,8 +161,8 @@ class RNOpenId4VpModule: NSObject, RCTBridgeModule {
}
}
let response = try await openID4VP?.shareVerifiablePresentation(vpTokenSigningResults: formattedVPTokenSigningResults)
resolve(response)
let verifierResponse = try await openID4VP?.sendAuthorizationResponseToVerifier(vpTokenSigningResults: formattedVPTokenSigningResults)
try resolveToJsonData(verifierResponse, resolver: resolve, rejecter: reject)
} catch {
rejectWithOpenID4VPError(error, reject: reject)
}
@@ -187,7 +187,7 @@ class RNOpenId4VpModule: NSObject, RCTBridgeModule {
do {
let verifierResponse = try await openID4VP?.sendErrorResponseToVerifier(error: exception)
resolve(verifierResponse)
try resolveToJsonData(verifierResponse, resolver: resolve, rejecter: reject)
} catch {
rejectWithOpenID4VPError(error, reject: reject)
}
@@ -231,7 +231,7 @@ class RNOpenId4VpModule: NSObject, RCTBridgeModule {
let errorMap: [String: Any] = [
"errorCode": openidError.errorCode,
"message": openidError.message,
"response": openidError.response ?? ""
"response": Inji.toJsonString(openidError.networkResponse) ?? ""
]
let nsError = NSError(
domain: "OPENID4VP",
@@ -313,3 +313,28 @@ func mapStringsToEnum<T: RawRepresentable>(
return match
}
}
fileprivate func resolveToJsonData(_ response: NetworkResponse?,resolver resolve: @escaping RCTPromiseResolveBlock,
rejecter reject: @escaping RCTPromiseRejectBlock) throws {
let jsonData = try toJsonData(response)
if let jsonObject = try JSONSerialization.jsonObject(with: jsonData, options: []) as? [String: Any] {
resolve(jsonObject)
} else {
reject("ERROR", "Failed to serialize JSON", nil)
}
}
fileprivate func toJsonString<T>(_ input: T) -> String? where T: Encodable {
if let jsonData = try? toJsonData(input),
let jsonString = String(data: jsonData, encoding: .utf8) {
return jsonString
}
return nil
}
fileprivate func toJsonData<T>(_ input: T) throws -> Data where T: Encodable {
let encoder = JSONEncoder()
encoder.keyEncodingStrategy = .convertToSnakeCase
return try encoder.encode(input)
}

View File

@@ -921,6 +921,10 @@
"title": "حدث خطأ ما",
"message": "حدثت مشكلة فنية أثناء مشاركة بطاقتك. انقر على \"إعادة المحاولة\" للمحاولة مرة أخرى أو ارجع إلى \"الرئيسية\"."
},
"verifierResponseError": {
"title": "تعذر على المحقق معالجة الاعتماد",
"message": "حدثت مشكلة أثناء معالجة المحقق لاعتمادك."
},
"noImage": {
"title": "حدث خطأ!",
"message": "يتطلب التحقق من الوجه صورة في بيانات الاعتماد المحددة. الرجاء استخدام خيار المشاركة أو تحديد بيانات اعتماد تتضمن صورة."

View File

@@ -933,6 +933,10 @@
"title": "Something Went Wrong",
"message": "There was a technical issue while sharing your card. Tap \"Retry\" to try again or go back to \"Home\"."
},
"verifierResponseError": {
"title": "Verifier could not process the credential",
"message": "There was an issue while the verifier was processing your credential."
},
"noImage": {
"title": "An Error Occured!",
"message": "Face verification requires a photo in the selected credential(s). Please use the Share option or select a credential that includes an image."

View File

@@ -924,6 +924,10 @@
"title": "May Nangyaring Mali",
"message": "Nagkaroon ng teknikal na problema habang ibinabahagi ang iyong card. Pindutin ang \"Subukang Muli\" para subukang muli o bumalik sa \"Home\"."
},
"verifierResponseError": {
"title": "Hindi maproseso ng tagapagsuri ang kredensyal",
"message": "May naging isyu habang pinoproseso ng tagapagsuri ang iyong kredensyal."
},
"noImage": {
"title": "Isang Error ang Naganap!",
"message": "Ang pag-verify ng mukha ay nangangailangan ng larawan sa napiling (mga) kredensyal. Pakigamit ang opsyong Ibahagi o pumili ng kredensyal na may kasamang larawan."
@@ -1131,4 +1135,4 @@
"verifierConfirm": "Oo, pinagkakatiwalaan ko ang verifier na ito",
"cancel": "Hindi, Ibalik Mo Ako"
}
}
}

View File

@@ -927,6 +927,10 @@
"title": "कुछ गलत हो गया",
"message": "आपका कार्ड साझा करते समय एक तकनीकी समस्या हुई। फिर से प्रयास करने के लिए \"पुनः प्रयास करें\" टैप करें या \"होम\" पर वापस जाएं।"
},
"verifierResponseError": {
"title": "सत्यापनकर्ता क्रेडेंशियल को प्रोसेस नहीं कर सका",
"message": "सत्यापनकर्ता द्वारा आपके क्रेडेंशियल को प्रोसेस करते समय एक समस्या आई।"
},
"noImage": {
"title": "एक त्रुटि हुई!",
"message": "चेहरे के सत्यापन के लिए चयनित क्रेडेंशियल में एक फोटो की आवश्यकता होती है। कृपया शेयर विकल्प का उपयोग करें या एक क्रेडेंशियल चुनें जिसमें एक छवि शामिल हो।"
@@ -1132,4 +1136,5 @@
"verifierConfirm": "हाँ, मुझे इस सत्यापनकर्ता पर भरोसा है",
"cancel": "नहीं, मुझे वापस ले चलें"
}
}
}

View File

@@ -925,6 +925,10 @@
"title": "ಏನೋ ತಪ್ಪು ಸಂಭವಿಸಿದೆ",
"message": "ನಿಮ್ಮ ಕಾರ್ಡ್ ಹಂಚಿಕೊಳ್ಳುವಾಗ ತಾಂತ್ರಿಕ ಸಮಸ್ಯೆ ಸಂಭವಿಸಿದೆ. ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಲು \"ಮರುಪ್ರಯತ್ನಿಸಿ\" ಒತ್ತಿರಿ ಅಥವಾ \"ಮುಖಪುಟ\" ಗೆ ಹಿಂದಿರುಗಿ."
},
"verifierResponseError": {
"title": "ಪರಿಶೀಲಕನು ರುಜುವಾತು ಪ್ರಕ್ರಿಯೆಗೊಳಿಸಲು ಸಾಧ್ಯವಾಗಲಿಲ್ಲ",
"message": "ಪರಿಶೀಲಕನು ನಿಮ್ಮ ರುಜುವಾತು ಪ್ರಕ್ರಿಯೆಗೊಳಿಸುವಾಗ ಸಮಸ್ಯೆ ಉಂಟಾಯಿತು."
},
"noImage": {
"title": "ಒಂದು ದೋಷ ಸಂಭವಿಸಿದೆ!",
"message": "ಮುಖ ಪರಿಶೀಲನೆಗೆ ಆಯ್ಕೆಮಾಡಿದ ರುಜುವಾತು(ಗಳಲ್ಲಿ) ಫೋಟೋ ಅಗತ್ಯವಿದೆ. ದಯವಿಟ್ಟು ಹಂಚಿಕೆ ಆಯ್ಕೆಯನ್ನು ಬಳಸಿ ಅಥವಾ ಚಿತ್ರವನ್ನು ಒಳಗೊಂಡಿರುವ ರುಜುವಾತುಗಳನ್ನು ಆಯ್ಕೆಮಾಡಿ."

View File

@@ -925,6 +925,10 @@
"title": "ஏதோ தவறு நடந்துவிட்டது",
"message": "உங்கள் கார்டைப் பகிரும்போது தொழில்நுட்ப சிக்கல் ஏற்பட்டது. மீண்டும் முயற்சிக்க \"மீண்டும் முயற்சி செய்\" என்பதைத் தட்டவும் அல்லது \"முகப்பு\" பக்கம் திரும்பவும்."
},
"verifierResponseError": {
"title": "சான்றிதழை சரிபார்ப்பவர் செயலாக்க முடியவில்லை",
"message": "சான்றிதழை செயலாக்கும் போது சரிபார்ப்பவருக்கு சிக்கல் ஏற்பட்டது."
},
"noImage": {
"title": "ஒரு பிழை ஏற்பட்டது!",
"message": "முகம் சரிபார்ப்புக்கு தேர்ந்தெடுக்கப்பட்ட நற்சான்றிதழில்(களில்) ஒரு புகைப்படம் தேவை. பகிர் விருப்பத்தைப் பயன்படுத்தவும் அல்லது படத்தை உள்ளடக்கிய நற்சான்றிதழைத் தேர்ந்தெடுக்கவும்."

View File

@@ -157,7 +157,7 @@ export const openID4VPActions = (model: any) => {
error: (_, event) => {
console.error(
'Error occurred during the authenticateVerifier call :',
event.data.userInfo,
event.data.userInfo,
);
return event.data.code;
},
@@ -165,7 +165,7 @@ export const openID4VPActions = (model: any) => {
setTrustedVerifiersApiCallError: model.assign({
error: (_, event) => {
console.error('Error:', event.data.message);
console.error('Error while fetching trusted verifiers:', event.data);
return 'api error - ' + event.data.message;
},
}),

View File

@@ -82,7 +82,10 @@ export const openID4VPMachine = model.createMachine(
target: 'getKeyPairFromKeystore',
},
onError: {
actions: 'setTrustedVerifiersApiCallError',
actions: [
'setTrustedVerifiersApiCallError',
'resetIsShowLoadingScreen',
],
},
},
},
@@ -442,6 +445,11 @@ export const openID4VPMachine = model.createMachine(
shareVPDeclineStatusToVerifier: {
invoke: {
src: 'shareDeclineStatus',
onError: (_, event) =>
console.error(
'Failed to send decline status to verifier - ',
event.data,
),
},
after: {
200: {

View File

@@ -218,9 +218,17 @@ export const openID4VPServices = () => {
vpTokenSigningResultMap[formatType] = uuidToSignature;
}
}
return await OpenID4VP.shareVerifiablePresentation(
const verifierResponse = await OpenID4VP.shareVerifiablePresentation(
vpTokenSigningResultMap,
);
if (verifierResponse['status_code'] !== 200) {
console.error(
'Error response from verifier during sharing the VP :',
verifierResponse,
);
throw new Error('VERIFIER_RESPONSE_ERROR');
}
return verifierResponse;
},
};
};

View File

@@ -68,7 +68,8 @@ export const SendVPScreen: React.FC<ScanLayoutProps> = props => {
if (errorModal.show && controller.isOVPViaDeepLink) {
const timeout = setTimeout(
async () => {
await OpenID4VP.sendErrorToVerifier(
// Send error to verifier is initiated and its response is not listened to here.
void OpenID4VP.sendErrorToVerifier(
OVP_ERROR_MESSAGES.NO_MATCHING_VCS,
OVP_ERROR_CODE.NO_MATCHING_VCS,
);
@@ -132,7 +133,8 @@ export const SendVPScreen: React.FC<ScanLayoutProps> = props => {
};
const handleDismiss = async () => {
await OpenID4VP.sendErrorToVerifier(
// Send error to verifier is initiated and its response is not listened to here.
void OpenID4VP.sendErrorToVerifier(
OVP_ERROR_MESSAGES.DECLINED,
OVP_ERROR_CODE.DECLINED,
);
@@ -147,7 +149,8 @@ export const SendVPScreen: React.FC<ScanLayoutProps> = props => {
};
const handleRejectButtonEvent = async () => {
await OpenID4VP.sendErrorToVerifier(
// Send error to verifier is initiated and its response is not listened to here.
void OpenID4VP.sendErrorToVerifier(
OVP_ERROR_MESSAGES.DECLINED,
OVP_ERROR_CODE.DECLINED,
);
@@ -234,7 +237,8 @@ export const SendVPScreen: React.FC<ScanLayoutProps> = props => {
const getPrimaryButtonEvent = () => {
if (controller.showConfirmationPopup && controller.isOVPViaDeepLink) {
return async () => {
await OpenID4VP.sendErrorToVerifier(
// Send error to verifier is initiated and its response is not listened to here.
void OpenID4VP.sendErrorToVerifier(
OVP_ERROR_MESSAGES.DECLINED,
OVP_ERROR_CODE.DECLINED,
);

View File

@@ -147,6 +147,15 @@ export function useOvpErrorModal({
showRetryButton: false,
});
generateAndStoreLogMessage('REQUEST_COULD_NOT_BE_PROCESSED');
} else if (error.includes('VERIFIER_RESPONSE_ERROR')) {
setErrorModal({
show: true,
title: t('errors.verifierResponseError.title'),
message: t('errors.verifierResponseError.message'),
additionalMessage,
showRetryButton: false,
});
generateAndStoreLogMessage('SEND_VP_ERROR');
} else if (error.startsWith('send vp')) {
setErrorModal({
show: true,

View File

@@ -71,9 +71,11 @@ class OpenID4VP {
) {
const openID4VP = await OpenID4VP.getInstance();
return await openID4VP.InjiOpenID4VP.shareVerifiablePresentation(
vpTokenSigningResultMap,
);
const verifierResponse =
await openID4VP.InjiOpenID4VP.shareVerifiablePresentation(
vpTokenSigningResultMap,
);
return parseJSON(verifierResponse);
}
static async sendErrorToVerifier(errorMessage: string, errorCode: string) {