mirror of
https://github.com/mosip/inji-wallet.git
synced 2026-01-09 13:38:01 -05:00
Merge branch 'INJIMOB-3365' into develop
Signed-off-by: Swati Goel <meet2swati@gmail.com>
This commit is contained in:
@@ -341,7 +341,7 @@ fileignoreconfig:
|
||||
- filename: android/app/src/main/java/io/mosip/residentapp/InjiVciClientModule.java
|
||||
checksum: 17f55840bab193bc353034445ba4fce53e1ce466e95f616c15a1351f8d2f23bc
|
||||
- filename: ios/Inji.xcworkspace/xcshareddata/swiftpm/Package.resolved
|
||||
checksum: 785f2a3390ffd7b93974f449132008c7c1b8b6d1e8deaba7b1d0737be1b5f2f4
|
||||
checksum: 81d8398a4f4b052c3fb10d92f0e0af398d09095d9f882cc35335c43630c6c371
|
||||
- filename: injitest/src/main/resources/Vids.json
|
||||
checksum: 8bcffed7a6dd565ae695e1b29de0655e10bd5c5420af2718defd593a687b8817
|
||||
- filename: injitest/src/main/java/inji/utils/UpdateNetworkSettings.java
|
||||
@@ -398,7 +398,8 @@ fileignoreconfig:
|
||||
checksum: 6600a3d75033af4d702dd8c9663e12ad7c2c096a529bac2771bb856cc75a5ed0
|
||||
- filename: machines/openID4VP/openID4VPModel.ts
|
||||
checksum: 5d1ed430f84852d6c85bc439c47641cfb5b19cbd1a03faf8918429685db51e07
|
||||
version: ""
|
||||
- filename: shared/hooks/useOvpErrorModal.ts
|
||||
checksum: dc83cf9d688fda587cfb10e738b966694794181f233dd1b6f5cf3f818dae412d
|
||||
- filename: shared/openID4VP/OpenID4VPHelper.ts
|
||||
checksum: 2ab5f935ea3d1ec4d109d8614c2246f40e284594288566338f185611470e6928
|
||||
- filename: components/VC/common/VCUtils.tsx
|
||||
|
||||
1
App.tsx
1
App.tsx
@@ -1,3 +1,4 @@
|
||||
import 'react-native-get-random-values';
|
||||
import React, {useContext, useEffect, useState} from 'react';
|
||||
import {AppLayout} from './screens/AppLayout';
|
||||
import {useFont} from './shared/hooks/useFont';
|
||||
|
||||
@@ -280,7 +280,7 @@ dependencies {
|
||||
implementation("io.mosip:pixelpass-aar:0.7.0-SNAPSHOT")
|
||||
implementation("io.mosip:secure-keystore:0.3.0")
|
||||
implementation("io.mosip:tuvali:0.5.2")
|
||||
implementation("io.mosip:inji-vci-client:0.4.0-SNAPSHOT")
|
||||
implementation("io.mosip:inji-vci-client-aar:0.4.0-SNAPSHOT")
|
||||
implementation("com.google.code.gson:gson:2.10.1")
|
||||
implementation("io.mosip:vcverifier-aar:1.3.0-SNAPSHOT") {
|
||||
exclude group: 'org.bouncycastle', module: 'bcpkix-jdk15on'
|
||||
|
||||
@@ -4,6 +4,7 @@ import static io.mosip.openID4VP.authorizationResponse.AuthorizationResponseUtil
|
||||
import static io.mosip.openID4VP.constants.FormatType.LDP_VC;
|
||||
import static io.mosip.openID4VP.constants.FormatType.MSO_MDOC;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
@@ -20,20 +21,23 @@ import com.google.gson.FieldNamingPolicy;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
|
||||
import io.mosip.openID4VP.constants.ClientIdScheme;
|
||||
import io.mosip.openID4VP.constants.ContentEncrytionAlgorithm;
|
||||
import io.mosip.openID4VP.constants.KeyManagementAlgorithm;
|
||||
import io.mosip.openID4VP.constants.RequestSigningAlgorithm;
|
||||
import io.mosip.openID4VP.exceptions.OpenID4VPExceptions;
|
||||
import io.mosip.openID4VP.exceptions.OpenID4VPExceptions.AccessDenied;
|
||||
import io.mosip.openID4VP.exceptions.OpenID4VPExceptions.InvalidTransactionData;
|
||||
|
||||
import static io.mosip.openID4VP.common.OpenID4VPErrorCodes.ACCESS_DENIED;
|
||||
import static io.mosip.openID4VP.common.OpenID4VPErrorCodes.INVALID_TRANSACTION_DATA;
|
||||
|
||||
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.Optional;
|
||||
|
||||
import io.mosip.openID4VP.OpenID4VP;
|
||||
import io.mosip.openID4VP.authorizationRequest.AuthorizationRequest;
|
||||
@@ -64,10 +68,14 @@ public class InjiOpenID4VPModule extends ReactContextBaseJavaModule {
|
||||
return MODULE_NAME;
|
||||
}
|
||||
|
||||
@SuppressLint("LogNotTimber")
|
||||
@ReactMethod
|
||||
public void init(String appId) {
|
||||
public void initSdk(String appId, ReadableMap walletMetadata ) {
|
||||
Log.d(TAG, "Initializing InjiOpenID4VPModule with " + appId);
|
||||
openID4VP = new OpenID4VP(appId);
|
||||
|
||||
WalletMetadata metadata = parseWalletMetadata(walletMetadata);
|
||||
|
||||
openID4VP = new OpenID4VP(appId, metadata);
|
||||
gson = new GsonBuilder()
|
||||
.setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES)
|
||||
.disableHtmlEscaping()
|
||||
@@ -77,29 +85,21 @@ public class InjiOpenID4VPModule extends ReactContextBaseJavaModule {
|
||||
@ReactMethod
|
||||
public void authenticateVerifier(String urlEncodedAuthorizationRequest,
|
||||
ReadableArray trustedVerifiers,
|
||||
ReadableMap walletMetadata,
|
||||
Boolean shouldValidateClient,
|
||||
Promise promise) {
|
||||
try {
|
||||
WalletMetadata walletMetadataObj = parseWalletMetadata(walletMetadata);
|
||||
List<Verifier> verifierList = parseVerifiers(trustedVerifiers);
|
||||
|
||||
AuthorizationRequest authRequest = openID4VP.authenticateVerifier(
|
||||
urlEncodedAuthorizationRequest,
|
||||
verifierList,
|
||||
shouldValidateClient,
|
||||
walletMetadataObj
|
||||
shouldValidateClient
|
||||
);
|
||||
|
||||
String authRequestJson = gson.toJson(authRequest, AuthorizationRequest.class);
|
||||
promise.resolve(authRequestJson);
|
||||
} catch (Exception e) {
|
||||
if (e instanceof OpenID4VPExceptions) {
|
||||
OpenID4VPExceptions ex = (OpenID4VPExceptions) e;
|
||||
promise.reject(ex.getErrorCode(), ex.getMessage());
|
||||
} else {
|
||||
promise.reject(e);
|
||||
}
|
||||
rejectWithOpenID4VPExceptions(e, promise);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -110,12 +110,7 @@ public class InjiOpenID4VPModule extends ReactContextBaseJavaModule {
|
||||
Map<FormatType, UnsignedVPToken> vpTokens = openID4VP.constructUnsignedVPToken(selectedVCsMap, holderId, signatureSuite);
|
||||
promise.resolve(toJsonString(vpTokens));
|
||||
} catch (Exception e) {
|
||||
if (e instanceof OpenID4VPExceptions) {
|
||||
OpenID4VPExceptions ex = (OpenID4VPExceptions) e;
|
||||
promise.reject(ex.getErrorCode(), ex.getMessage());
|
||||
} else {
|
||||
promise.reject(e);
|
||||
}
|
||||
rejectWithOpenID4VPExceptions(e, promise);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -126,12 +121,17 @@ public class InjiOpenID4VPModule extends ReactContextBaseJavaModule {
|
||||
String response = openID4VP.shareVerifiablePresentation(authContainer);
|
||||
promise.resolve(response);
|
||||
} catch (Exception e) {
|
||||
if (e instanceof OpenID4VPExceptions) {
|
||||
OpenID4VPExceptions ex = (OpenID4VPExceptions) e;
|
||||
promise.reject(ex.getErrorCode(), ex.getMessage());
|
||||
} else {
|
||||
promise.reject(e);
|
||||
}
|
||||
rejectWithOpenID4VPExceptions(e, promise);
|
||||
}
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
private static void rejectWithOpenID4VPExceptions(Exception e, Promise promise) {
|
||||
if (e instanceof OpenID4VPExceptions) {
|
||||
OpenID4VPExceptions ex = (OpenID4VPExceptions) e;
|
||||
promise.reject(ex.getErrorCode(), ex.getMessage(), ex);
|
||||
} else {
|
||||
promise.reject("ERR_UNKNOWN", e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -159,30 +159,58 @@ public class InjiOpenID4VPModule extends ReactContextBaseJavaModule {
|
||||
? walletMetadata.getBoolean("presentation_definition_uri_supported")
|
||||
: null;
|
||||
|
||||
Map<String, VPFormatSupported> vpFormatsSupportedMap = new HashMap<>();
|
||||
if (walletMetadata.hasKey("vp_formats_supported")) {
|
||||
ReadableMap vpFormatsMap = walletMetadata.getMap("vp_formats_supported");
|
||||
if (vpFormatsMap != null && vpFormatsMap.hasKey("ldp_vc")) {
|
||||
ReadableMap ldpVc = vpFormatsMap.getMap("ldp_vc");
|
||||
if (ldpVc != null && ldpVc.hasKey("alg_values_supported")) {
|
||||
ReadableArray ldpVcAlgArray = ldpVc.getArray("alg_values_supported");
|
||||
List<String> algValuesList = ldpVcAlgArray != null
|
||||
? convertReadableArrayToList(ldpVcAlgArray)
|
||||
: null;
|
||||
vpFormatsSupportedMap.put("ldp_vc", new VPFormatSupported(algValuesList));
|
||||
}
|
||||
}
|
||||
}
|
||||
return new WalletMetadata(
|
||||
Map<FormatType, VPFormatSupported> vpFormatsSupportedMap = parseVpFormatsSupported(walletMetadata);
|
||||
|
||||
ContentEncrytionAlgorithm algorithm = ContentEncrytionAlgorithm.Companion.fromValue("value");
|
||||
WalletMetadata walletMetadata1 = new WalletMetadata(
|
||||
presentationDefinitionUriSupported,
|
||||
vpFormatsSupportedMap,
|
||||
extractStringListOrNull(walletMetadata, "client_id_schemes_supported"),
|
||||
extractStringListOrNull(walletMetadata, "request_object_signing_alg_values_supported"),
|
||||
extractStringListOrNull(walletMetadata, "authorization_encryption_alg_values_supported"),
|
||||
extractStringListOrNull(walletMetadata, "authorization_encryption_enc_values_supported")
|
||||
convertReadableArrayToEnumList(walletMetadata, "client_id_schemes_supported", ClientIdScheme.Companion::fromValue),
|
||||
convertReadableArrayToEnumList(walletMetadata, "request_object_signing_alg_values_supported", RequestSigningAlgorithm.Companion::fromValue),
|
||||
convertReadableArrayToEnumList(walletMetadata, "authorization_encryption_alg_values_supported", KeyManagementAlgorithm.Companion::fromValue),
|
||||
convertReadableArrayToEnumList(walletMetadata, "authorization_encryption_enc_values_supported", ContentEncrytionAlgorithm.Companion::fromValue)
|
||||
);
|
||||
System.out.println("Wallet Metadata: " + walletMetadata1);
|
||||
return walletMetadata1;
|
||||
}
|
||||
|
||||
private Map<FormatType, VPFormatSupported> parseVpFormatsSupported(ReadableMap walletMetadata) {
|
||||
Map<FormatType, VPFormatSupported> vpFormatsSupportedMap = new HashMap<>();
|
||||
if (walletMetadata.hasKey("vp_formats_supported")) {
|
||||
ReadableMap vpFormatsMap = walletMetadata.getMap("vp_formats_supported");
|
||||
if (vpFormatsMap != null) {
|
||||
addVpFormatSupported(vpFormatsMap, "ldp_vc", vpFormatsSupportedMap);
|
||||
addVpFormatSupported(vpFormatsMap, "mso_mdoc", vpFormatsSupportedMap);
|
||||
}
|
||||
}
|
||||
return vpFormatsSupportedMap;
|
||||
}
|
||||
|
||||
private <T> List<T> convertReadableArrayToEnumList(ReadableMap readableMap, String key, Function<String, T> converter) {
|
||||
if (!readableMap.hasKey(key)) return null;
|
||||
ReadableArray readableArray = readableMap.getArray(key);
|
||||
List<T> list = new ArrayList<>();
|
||||
for (int i = 0; i < Objects.requireNonNull(readableArray).size(); i++) {
|
||||
list.add(converter.apply(readableArray.getString(i)));
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
|
||||
private void addVpFormatSupported(ReadableMap vpFormatsMap, String key, Map<FormatType, VPFormatSupported> vpFormatsSupportedMap) {
|
||||
if (vpFormatsMap.hasKey(key)) {
|
||||
ReadableMap formatMap = vpFormatsMap.getMap(key);
|
||||
if (formatMap != null && formatMap.hasKey("alg_values_supported")) {
|
||||
ReadableArray algArray = formatMap.getArray("alg_values_supported");
|
||||
List<String> algValuesList = algArray != null ? convertReadableArrayToList(algArray) : null;
|
||||
|
||||
vpFormatsSupportedMap.put(FormatType.Companion.fromValue(key), new VPFormatSupported(algValuesList));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
private List<Verifier> parseVerifiers(ReadableArray verifiersArray) {
|
||||
List<Verifier> verifiers = new ArrayList<>();
|
||||
|
||||
@@ -316,14 +344,7 @@ public class InjiOpenID4VPModule extends ReactContextBaseJavaModule {
|
||||
} else if (MSO_MDOC.getValue().equals(formatStr)) {
|
||||
return MSO_MDOC;
|
||||
}
|
||||
throw new UnsupportedOperationException("Credential format not supported: " + formatStr);
|
||||
}
|
||||
|
||||
private List<String> extractStringListOrNull(ReadableMap readableMap, String key) {
|
||||
return Optional.ofNullable(readableMap.getArray(key))
|
||||
.map(this::convertReadableArrayToList)
|
||||
.filter(list -> !list.isEmpty())
|
||||
.orElse(null);
|
||||
throw new UnsupportedOperationException("Credential format '" + formatStr + "' is not supported");
|
||||
}
|
||||
|
||||
private List<String> convertReadableArrayToList(ReadableArray readableArray) {
|
||||
|
||||
@@ -4,6 +4,7 @@ import com.facebook.react.bridge.Arguments
|
||||
import com.facebook.react.bridge.ReactApplicationContext
|
||||
import com.facebook.react.modules.core.DeviceEventManagerModule
|
||||
import com.google.gson.Gson
|
||||
import io.mosip.vciclient.token.TokenResponse
|
||||
import kotlinx.coroutines.CompletableDeferred
|
||||
|
||||
object VCIClientCallbackBridge {
|
||||
@@ -11,6 +12,7 @@ object VCIClientCallbackBridge {
|
||||
private var deferredAuthCode: CompletableDeferred<String>? = null
|
||||
private var deferredTxCode: CompletableDeferred<String>? = null
|
||||
private var deferredIssuerTrustResponse: CompletableDeferred<Boolean>? = null
|
||||
private var deferredTokenResponse: CompletableDeferred<TokenResponse>? = null
|
||||
|
||||
fun createProofDeferred(): CompletableDeferred<String> {
|
||||
deferredProof = CompletableDeferred()
|
||||
@@ -22,72 +24,86 @@ object VCIClientCallbackBridge {
|
||||
return deferredAuthCode!!
|
||||
}
|
||||
|
||||
fun createTokenResponseDeferred(): CompletableDeferred<TokenResponse> {
|
||||
deferredTokenResponse = CompletableDeferred()
|
||||
return deferredTokenResponse!!
|
||||
}
|
||||
|
||||
fun createTxCodeDeferred(): CompletableDeferred<String> {
|
||||
deferredTxCode = CompletableDeferred()
|
||||
return deferredTxCode!!
|
||||
}
|
||||
|
||||
fun createIsuerTrustResponseDeferred(): CompletableDeferred<Boolean> {
|
||||
fun createIssuerTrustResponseDeferred(): CompletableDeferred<Boolean> {
|
||||
deferredIssuerTrustResponse = CompletableDeferred()
|
||||
return deferredIssuerTrustResponse!!
|
||||
}
|
||||
|
||||
fun emitRequestProof(
|
||||
context: ReactApplicationContext,
|
||||
accessToken: String,
|
||||
cNonce: String?,
|
||||
issuerMetadata: Map<String, *>? = null,
|
||||
credentialConfigurationId: String? = null
|
||||
context: ReactApplicationContext,
|
||||
credentialIssuer: String,
|
||||
cNonce: String?,
|
||||
proofSigningAlgorithmsSupported: List<String>,
|
||||
) {
|
||||
val params =
|
||||
Arguments.createMap().apply {
|
||||
putString("accessToken", accessToken)
|
||||
if (cNonce != null) putString("cNonce", cNonce)
|
||||
if (issuerMetadata != null) {
|
||||
val json = Gson().toJson(issuerMetadata)
|
||||
putString("issuerMetadata", json)
|
||||
}
|
||||
if (credentialConfigurationId != null) {
|
||||
putString("credentialConfigurationId", credentialConfigurationId)
|
||||
}
|
||||
}
|
||||
Arguments.createMap().apply {
|
||||
putString("credentialIssuer", credentialIssuer)
|
||||
if (cNonce != null) putString("cNonce", cNonce)
|
||||
val json = Gson().toJson(proofSigningAlgorithmsSupported)
|
||||
putString("proofSigningAlgorithmsSupported", json)
|
||||
}
|
||||
context.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
|
||||
.emit("onRequestProof", params)
|
||||
.emit("onRequestProof", params)
|
||||
}
|
||||
|
||||
fun emitRequestAuthCode(context: ReactApplicationContext, authorizationEndpoint: String) {
|
||||
val params =
|
||||
Arguments.createMap().apply {
|
||||
putString("authorizationEndpoint", authorizationEndpoint)
|
||||
}
|
||||
Arguments.createMap().apply {
|
||||
putString("authorizationUrl", authorizationEndpoint)
|
||||
}
|
||||
context.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
|
||||
.emit("onRequestAuthCode", params)
|
||||
.emit("onRequestAuthCode", params)
|
||||
}
|
||||
|
||||
fun emitTokenRequest(
|
||||
context: ReactApplicationContext,
|
||||
payload: Map<String, Any?>
|
||||
) {
|
||||
val params =
|
||||
Arguments.createMap().apply {
|
||||
putString("tokenRequest", Gson().toJson(payload))
|
||||
}
|
||||
context.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
|
||||
.emit("onRequestTokenResponse", params)
|
||||
}
|
||||
|
||||
fun emitRequestTxCode(
|
||||
context: ReactApplicationContext,
|
||||
inputMode: String?,
|
||||
description: String?,
|
||||
length: Int?
|
||||
context: ReactApplicationContext,
|
||||
inputMode: String?,
|
||||
description: String?,
|
||||
length: Int?
|
||||
) {
|
||||
val params =
|
||||
Arguments.createMap().apply {
|
||||
putString("inputMode", inputMode)
|
||||
putString("description", description)
|
||||
if( length != null)
|
||||
Arguments.createMap().apply {
|
||||
putString("inputMode", inputMode)
|
||||
putString("description", description)
|
||||
if (length != null)
|
||||
putInt("length", length)
|
||||
}
|
||||
}
|
||||
context.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
|
||||
.emit("onRequestTxCode", params)
|
||||
.emit("onRequestTxCode", params)
|
||||
}
|
||||
fun emitRequestIssuerTrust(context: ReactApplicationContext, issuerMetadata: Map<String, *>) {
|
||||
|
||||
fun emitRequestIssuerTrust(context: ReactApplicationContext, credentialIssuer: String, issuerDisplay: List<Map<String, Any>>) {
|
||||
val params =
|
||||
Arguments.createMap().apply {
|
||||
putString("issuerMetadata", Gson().toJson(issuerMetadata))
|
||||
}
|
||||
Arguments.createMap().apply {
|
||||
//TODO: Convert Gson construction to singleton pattern
|
||||
putString("credentialIssuer", credentialIssuer)
|
||||
putString("issuerDisplay", Gson().toJson(issuerDisplay))
|
||||
}
|
||||
|
||||
context.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
|
||||
.emit("onCheckIssuerTrust", params)
|
||||
.emit("onCheckIssuerTrust", params)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
@@ -95,16 +111,25 @@ object VCIClientCallbackBridge {
|
||||
deferredProof?.complete(jwt)
|
||||
deferredProof = null
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun completeAuthCode(code: String) {
|
||||
deferredAuthCode?.complete(code)
|
||||
deferredAuthCode = null
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun completeTxCode(code: String) {
|
||||
deferredTxCode?.complete(code)
|
||||
deferredTxCode = null
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun completeTokenResponse(tokenResponse: TokenResponse) {
|
||||
deferredTokenResponse?.complete(tokenResponse)
|
||||
deferredTokenResponse = null
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun completeIssuerTrustResponse(trusted: Boolean) {
|
||||
deferredIssuerTrustResponse?.complete(trusted)
|
||||
@@ -117,7 +142,12 @@ object VCIClientCallbackBridge {
|
||||
|
||||
suspend fun awaitAuthCode(): String {
|
||||
return deferredAuthCode?.await()
|
||||
?: throw IllegalStateException("No auth code callback was set")
|
||||
?: throw IllegalStateException("No auth code callback was set")
|
||||
}
|
||||
|
||||
suspend fun awaitTokenResponse(): TokenResponse {
|
||||
return deferredTokenResponse?.await()
|
||||
?: throw IllegalStateException("No TokenResponse callback was set")
|
||||
}
|
||||
|
||||
suspend fun awaitTxCode(): String {
|
||||
@@ -126,6 +156,6 @@ object VCIClientCallbackBridge {
|
||||
|
||||
suspend fun awaitIssuerTrustResponse(): Boolean {
|
||||
return deferredIssuerTrustResponse?.await()
|
||||
?: throw IllegalStateException("No issuer trust response callback was set")
|
||||
?: throw IllegalStateException("No issuer trust response callback was set")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,22 +9,14 @@ import com.facebook.react.bridge.Promise;
|
||||
import com.facebook.react.bridge.ReactApplicationContext;
|
||||
import com.facebook.react.bridge.ReactContextBaseJavaModule;
|
||||
import com.facebook.react.bridge.ReactMethod;
|
||||
import com.facebook.react.bridge.ReadableArray;
|
||||
import com.facebook.react.bridge.ReadableMap;
|
||||
import com.google.gson.Gson;
|
||||
import java.util.Objects;
|
||||
import io.mosip.residentapp.VCIClientCallbackBridge;
|
||||
import io.mosip.residentapp.VCIClientBridge;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import io.mosip.vciclient.VCIClient;
|
||||
import io.mosip.vciclient.constants.CredentialFormat;
|
||||
import io.mosip.vciclient.credentialOffer.CredentialOffer;
|
||||
import io.mosip.vciclient.credentialOffer.CredentialOfferService;
|
||||
import io.mosip.vciclient.credentialResponse.CredentialResponse;
|
||||
import io.mosip.vciclient.proof.jwt.JWTProof;
|
||||
import io.mosip.vciclient.proof.Proof;
|
||||
import io.mosip.vciclient.issuerMetadata.IssuerMetadata;
|
||||
import io.mosip.vciclient.clientMetadata.ClientMetadata;
|
||||
import io.mosip.vciclient.authorizationCodeFlow.clientMetadata.ClientMetadata;
|
||||
import io.mosip.vciclient.credential.response.CredentialResponse;
|
||||
import io.mosip.vciclient.token.TokenResponse;
|
||||
|
||||
public class InjiVciClientModule extends ReactContextBaseJavaModule {
|
||||
private VCIClient vciClient;
|
||||
@@ -69,6 +61,29 @@ public class InjiVciClientModule extends ReactContextBaseJavaModule {
|
||||
VCIClientCallbackBridge.completeIssuerTrustResponse(trusted);
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void sendTokenResponseFromJS(String tokenResponseJson) {
|
||||
TokenResponse tokenResponse = new Gson().fromJson(tokenResponseJson, TokenResponse.class);
|
||||
VCIClientCallbackBridge.completeTokenResponse(tokenResponse);
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void getIssuerMetadata(String credentialIssuer, Promise promise) {
|
||||
new Thread(() -> {
|
||||
try {
|
||||
Map<String, Object> issuerMetadata = vciClient.getIssuerMetadata(credentialIssuer);
|
||||
reactContext.runOnUiQueueThread(() -> {
|
||||
String json = new Gson().toJson(issuerMetadata, Map.class);
|
||||
promise.resolve(json);
|
||||
});
|
||||
} catch (Exception e) {
|
||||
reactContext.runOnUiQueueThread(() -> {
|
||||
promise.reject("GET_ISSUER_METADATA_FAILED", e.getMessage(), e);
|
||||
});
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void requestCredentialByOffer(String credentialOffer,String clientMetadataJson, Promise promise) {
|
||||
new Thread(() -> {
|
||||
@@ -88,15 +103,13 @@ public class InjiVciClientModule extends ReactContextBaseJavaModule {
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void requestCredentialFromTrustedIssuer(String resolvedIssuerMetaJson, String clientMetadataJson, Promise promise) {
|
||||
public void requestCredentialFromTrustedIssuer(String credentialIssuer, String credentialConfigurationId, String clientMetadataJson, Promise promise) {
|
||||
new Thread(() -> {
|
||||
try {
|
||||
IssuerMetadata issuerMetaData = new Gson().fromJson(
|
||||
resolvedIssuerMetaJson, IssuerMetadata.class);
|
||||
ClientMetadata clientMetadata= new Gson().fromJson(
|
||||
clientMetadataJson, ClientMetadata.class);
|
||||
|
||||
CredentialResponse response = VCIClientBridge.requestCredentialFromTrustedIssuerSync(vciClient, issuerMetaData,clientMetadata);
|
||||
CredentialResponse response = VCIClientBridge.requestCredentialFromTrustedIssuerSync(vciClient, credentialIssuer, credentialConfigurationId,clientMetadata);
|
||||
|
||||
reactContext.runOnUiQueueThread(() -> {
|
||||
promise.resolve(response != null ? response.toJsonString() : null);
|
||||
|
||||
@@ -2,10 +2,12 @@ package io.mosip.residentapp
|
||||
|
||||
import com.facebook.react.bridge.ReactApplicationContext
|
||||
import io.mosip.vciclient.VCIClient
|
||||
import io.mosip.vciclient.clientMetadata.ClientMetadata
|
||||
import io.mosip.vciclient.credentialResponse.CredentialResponse
|
||||
import io.mosip.vciclient.issuerMetadata.IssuerMetadata
|
||||
import io.mosip.residentapp.VCIClientBridge
|
||||
import io.mosip.vciclient.authorizationCodeFlow.clientMetadata.ClientMetadata
|
||||
import io.mosip.vciclient.credential.response.CredentialResponse
|
||||
import io.mosip.vciclient.token.TokenRequest
|
||||
import io.mosip.vciclient.token.TokenResponse
|
||||
import io.mosip.vciclient.constants.AuthorizeUserCallback
|
||||
import io.mosip.vciclient.constants.ProofJwtCallback
|
||||
import kotlinx.coroutines.runBlocking
|
||||
|
||||
object VCIClientBridge {
|
||||
@@ -18,62 +20,94 @@ object VCIClientBridge {
|
||||
client: VCIClient,
|
||||
offer: String,
|
||||
clientMetaData: ClientMetadata
|
||||
): CredentialResponse? = runBlocking {
|
||||
): CredentialResponse = runBlocking {
|
||||
client.requestCredentialByCredentialOffer(
|
||||
credentialOffer = offer,
|
||||
clientMetadata = clientMetaData,
|
||||
getTxCode = { inputMode, description, length ->
|
||||
VCIClientCallbackBridge.createTxCodeDeferred()
|
||||
VCIClientCallbackBridge.emitRequestTxCode(VCIClientBridge.reactContext,
|
||||
inputMode,
|
||||
description,
|
||||
length
|
||||
)
|
||||
VCIClientCallbackBridge.awaitTxCode()
|
||||
},
|
||||
getProofJwt = { accessToken, cNonce, issuerMetadata, credentialConfigurationId ->
|
||||
VCIClientCallbackBridge.createProofDeferred()
|
||||
VCIClientCallbackBridge.emitRequestProof(
|
||||
VCIClientBridge.reactContext,
|
||||
accessToken,
|
||||
cNonce,
|
||||
issuerMetadata,
|
||||
credentialConfigurationId
|
||||
)
|
||||
VCIClientCallbackBridge.awaitProof()
|
||||
},
|
||||
getAuthCode = { endpoint ->
|
||||
VCIClientCallbackBridge.createAuthCodeDeferred()
|
||||
VCIClientCallbackBridge.emitRequestAuthCode(VCIClientBridge.reactContext, endpoint)
|
||||
VCIClientCallbackBridge.awaitAuthCode()
|
||||
},
|
||||
onCheckIssuerTrust = { issuerMetadata ->
|
||||
VCIClientCallbackBridge.createIsuerTrustResponseDeferred()
|
||||
VCIClientCallbackBridge.emitRequestIssuerTrust(reactContext, issuerMetadata)
|
||||
VCIClientCallbackBridge.awaitIssuerTrustResponse()
|
||||
}
|
||||
getTxCode = getTxCodeCallback(),
|
||||
authorizeUser = authorizeUserCallback(),
|
||||
getTokenResponse = getTokenResponseCallback(),
|
||||
getProofJwt = getProofJwtCallback(),
|
||||
onCheckIssuerTrust = onCheckIssuerTrustCallback()
|
||||
)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun requestCredentialFromTrustedIssuerSync(
|
||||
client: VCIClient,
|
||||
resolvedIssuerMetaData: IssuerMetadata,
|
||||
credentialIssuer: String,
|
||||
credentialConfigurationId: String,
|
||||
clientMetaData: ClientMetadata
|
||||
): CredentialResponse? = runBlocking {
|
||||
): CredentialResponse = runBlocking {
|
||||
client.requestCredentialFromTrustedIssuer(
|
||||
issuerMetadata = resolvedIssuerMetaData,
|
||||
clientMetadata = clientMetaData,
|
||||
getProofJwt = { accessToken, cNonce, _, _ ->
|
||||
VCIClientCallbackBridge.createProofDeferred()
|
||||
VCIClientCallbackBridge.emitRequestProof(reactContext, accessToken, cNonce)
|
||||
VCIClientCallbackBridge.awaitProof()
|
||||
},
|
||||
getAuthCode = { authorizationEndpoint ->
|
||||
VCIClientCallbackBridge.createAuthCodeDeferred()
|
||||
VCIClientCallbackBridge.emitRequestAuthCode(reactContext, authorizationEndpoint)
|
||||
VCIClientCallbackBridge.awaitAuthCode()
|
||||
}
|
||||
credentialIssuer,
|
||||
credentialConfigurationId,
|
||||
clientMetaData,
|
||||
authorizeUser = authorizeUserCallback(),
|
||||
getTokenResponse = getTokenResponseCallback(),
|
||||
getProofJwt = getProofJwtCallback(),
|
||||
)
|
||||
}
|
||||
|
||||
private fun authorizeUserCallback(): AuthorizeUserCallback = { endpoint ->
|
||||
VCIClientCallbackBridge.createAuthCodeDeferred()
|
||||
VCIClientCallbackBridge.emitRequestAuthCode(reactContext, endpoint)
|
||||
VCIClientCallbackBridge.awaitAuthCode()
|
||||
}
|
||||
|
||||
private fun getProofJwtCallback(): ProofJwtCallback =
|
||||
{
|
||||
credentialIssuer: String,
|
||||
cNonce: String?,
|
||||
proofSigningAlgorithmsSupported: List<String> ->
|
||||
VCIClientCallbackBridge.createProofDeferred()
|
||||
VCIClientCallbackBridge.emitRequestProof(
|
||||
reactContext,
|
||||
credentialIssuer,
|
||||
cNonce,
|
||||
proofSigningAlgorithmsSupported
|
||||
)
|
||||
VCIClientCallbackBridge.awaitProof()
|
||||
}
|
||||
|
||||
private fun getTokenResponseCallback(): suspend (tokenRequest: TokenRequest) -> TokenResponse =
|
||||
{ tokenRequest ->
|
||||
val payload: Map<String, Any?> =
|
||||
mapOf(
|
||||
"grantType" to tokenRequest.grantType.value,
|
||||
"tokenEndpoint" to tokenRequest.tokenEndpoint,
|
||||
"authCode" to tokenRequest.authCode,
|
||||
"preAuthCode" to tokenRequest.preAuthCode,
|
||||
"txCode" to tokenRequest.txCode,
|
||||
"clientId" to tokenRequest.clientId,
|
||||
"redirectUri" to tokenRequest.redirectUri,
|
||||
"codeVerifier" to tokenRequest.codeVerifier
|
||||
)
|
||||
VCIClientCallbackBridge.createTokenResponseDeferred()
|
||||
VCIClientCallbackBridge.emitTokenRequest(reactContext, payload)
|
||||
VCIClientCallbackBridge.awaitTokenResponse()
|
||||
}
|
||||
|
||||
private fun getTxCodeCallback(): suspend (String?, String?, Int?) -> String =
|
||||
{ inputMode, description, length ->
|
||||
VCIClientCallbackBridge.createTxCodeDeferred()
|
||||
VCIClientCallbackBridge.emitRequestTxCode(
|
||||
reactContext,
|
||||
inputMode,
|
||||
description,
|
||||
length
|
||||
)
|
||||
VCIClientCallbackBridge.awaitTxCode()
|
||||
}
|
||||
|
||||
private fun onCheckIssuerTrustCallback(): suspend (String, List<Map<String, Any>>) -> Boolean =
|
||||
{ credentialIssuer, issuerDisplay ->
|
||||
VCIClientCallbackBridge.createIssuerTrustResponseDeferred()
|
||||
VCIClientCallbackBridge.emitRequestIssuerTrust(
|
||||
reactContext,
|
||||
credentialIssuer,
|
||||
issuerDisplay
|
||||
)
|
||||
VCIClientCallbackBridge.awaitIssuerTrustResponse()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,11 +19,9 @@ import {VCProcessor} from '../common/VCProcessor';
|
||||
|
||||
export const VCCardView: React.FC<VCItemProps> = ({
|
||||
vcMetadata,
|
||||
margin,
|
||||
selectable,
|
||||
selected,
|
||||
onPress,
|
||||
onShow,
|
||||
isDownloading,
|
||||
isPinned,
|
||||
flow,
|
||||
@@ -58,7 +56,7 @@ export const VCCardView: React.FC<VCItemProps> = ({
|
||||
setVc(processedData);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
loadVc();
|
||||
}, [isDownloading, controller.credential]);
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ This document provides a comprehensive overview of the process for downloading a
|
||||
- vc+sd-jwt/dc+sd-jwt credential format for SD-JWT. All non-normative examples are referred for `vc+sd-jwt` format.
|
||||
- Cryptographic Key Binding - JWK is being used for cryptographic key binding in SD-JWT VC.
|
||||
|
||||
|
||||
### Actors involved
|
||||
1. Inji Wallet
|
||||
2. Issuing authority
|
||||
@@ -124,6 +125,7 @@ Note:
|
||||
- getProofJwt is a callback function to create the proof JWT for the credential request.
|
||||
````
|
||||
|
||||
|
||||
##### 6. Authorize user for credential request and get authorization code and access token
|
||||
_inji-vci-client_ uses `authorizeUser` callback function to authorize the user for the credential request.
|
||||
This typically involves redirecting the user to an authorization server where they can log in and grant permission
|
||||
@@ -169,8 +171,8 @@ Once the response is received in _inji-vci-client_, it is returned to the Wallet
|
||||
"credentialConfigurationId": "SD_JWT_VC_example_in_OpenID4VCI"
|
||||
}
|
||||
````
|
||||
##### 11. Perform vc verification
|
||||
|
||||
##### 11. Perform vc verification
|
||||
After obtaining the credential from the issuing authority through the _inji-vci-client_ library, a verification process ensures that the issued Verifiable Credential (VC) remains unaltered through _vc-verifier_ library.
|
||||
|
||||
_vc-verifier_ will use `CredentialVerifierFactory` and create `SdJwtVerifiableCredential` to perform validation and verification of the credential.
|
||||
|
||||
@@ -32,10 +32,10 @@
|
||||
9C4850532C3E59E2002ECBD5 /* RNEventEmitterProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9C4850522C3E59E2002ECBD5 /* RNEventEmitterProtocol.swift */; };
|
||||
9C7CDF3E2C7CBEDE00243A9A /* RNSecureKeystoreModule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9C7CDF3D2C7CBEDE00243A9A /* RNSecureKeystoreModule.swift */; };
|
||||
9C7CDF432C7CC13500243A9A /* RNSecureKeystoreModule.m in Sources */ = {isa = PBXBuildFile; fileRef = 9C7CDF422C7CC13500243A9A /* RNSecureKeystoreModule.m */; };
|
||||
9CAE74EE2E2E38F800C2532C /* pixelpass in Frameworks */ = {isa = PBXBuildFile; productRef = 9CAE74ED2E2E38F800C2532C /* pixelpass */; };
|
||||
9CCCA19E2CF87A8400D5A461 /* securekeystore in Frameworks */ = {isa = PBXBuildFile; productRef = 9CCCA19D2CF87A8400D5A461 /* securekeystore */; };
|
||||
9CD470CE2DFFF86600C207F9 /* OpenID4VP in Frameworks */ = {isa = PBXBuildFile; productRef = 9CD470CD2DFFF86600C207F9 /* OpenID4VP */; };
|
||||
9CD470D12DFFF89C00C207F9 /* VCIClient in Frameworks */ = {isa = PBXBuildFile; productRef = 9CD470D02DFFF89C00C207F9 /* VCIClient */; };
|
||||
9CFB37492DDDC9A000C199A8 /* pixelpass in Frameworks */ = {isa = PBXBuildFile; productRef = 9CFB37482DDDC9A000C199A8 /* pixelpass */; };
|
||||
9CDFD3102E28CA7B00505CEF /* VCIClient in Frameworks */ = {isa = PBXBuildFile; productRef = 9CDFD30F2E28CA7B00505CEF /* VCIClient */; };
|
||||
B18059E884C0ABDD17F3DC3D /* ExpoModulesProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAC715A2D49A985799AEE119 /* ExpoModulesProvider.swift */; };
|
||||
BB2F792D24A3F905000567C9 /* Expo.plist in Resources */ = {isa = PBXBuildFile; fileRef = BB2F792C24A3F905000567C9 /* Expo.plist */; };
|
||||
E86208152C0335C5007C3E24 /* RNVCIClientModule.swift in Sources */ = {isa = PBXBuildFile; fileRef = E86208142C0335C5007C3E24 /* RNVCIClientModule.swift */; };
|
||||
@@ -123,10 +123,10 @@
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
9CD470D12DFFF89C00C207F9 /* VCIClient in Frameworks */,
|
||||
9CDFD3102E28CA7B00505CEF /* VCIClient in Frameworks */,
|
||||
9C4850432C3E5873002ECBD5 /* ios-tuvali-library in Frameworks */,
|
||||
9CAE74EE2E2E38F800C2532C /* pixelpass in Frameworks */,
|
||||
9CCCA19E2CF87A8400D5A461 /* securekeystore in Frameworks */,
|
||||
9CFB37492DDDC9A000C199A8 /* pixelpass in Frameworks */,
|
||||
9CD470CE2DFFF86600C207F9 /* OpenID4VP in Frameworks */,
|
||||
96905EF65AED1B983A6B3ABC /* libPods-Inji.a in Frameworks */,
|
||||
);
|
||||
@@ -305,6 +305,7 @@
|
||||
00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */,
|
||||
800E24972A6A228C8D4807E9 /* [CP] Copy Pods Resources */,
|
||||
D11A8C363B4A5B625DB10379 /* [CP] Embed Pods Frameworks */,
|
||||
9CDFD3112E2A2F7900505CEF /* ShellScript */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
@@ -314,9 +315,9 @@
|
||||
packageProductDependencies = (
|
||||
9C4850422C3E5873002ECBD5 /* ios-tuvali-library */,
|
||||
9CCCA19D2CF87A8400D5A461 /* securekeystore */,
|
||||
9CFB37482DDDC9A000C199A8 /* pixelpass */,
|
||||
9CD470CD2DFFF86600C207F9 /* OpenID4VP */,
|
||||
9CD470D02DFFF89C00C207F9 /* VCIClient */,
|
||||
9CDFD30F2E28CA7B00505CEF /* VCIClient */,
|
||||
9CAE74ED2E2E38F800C2532C /* pixelpass */,
|
||||
);
|
||||
productName = Inji;
|
||||
productReference = 13B07F961A680F5B00A75B9A /* Inji.app */;
|
||||
@@ -347,9 +348,9 @@
|
||||
packageReferences = (
|
||||
9C4850412C3E5873002ECBD5 /* XCRemoteSwiftPackageReference "tuvali-ios-swift" */,
|
||||
9CCCA19C2CF87A8400D5A461 /* XCRemoteSwiftPackageReference "secure-keystore-ios-swift" */,
|
||||
9CFB37472DDDC99F00C199A8 /* XCRemoteSwiftPackageReference "pixelpass-ios-swift" */,
|
||||
9CD470CC2DFFF86600C207F9 /* XCRemoteSwiftPackageReference "inji-openid4vp-ios-swift" */,
|
||||
9CD470CF2DFFF89C00C207F9 /* XCRemoteSwiftPackageReference "inji-vci-client-ios-swift" */,
|
||||
9CDFD30E2E28CA7B00505CEF /* XCRemoteSwiftPackageReference "inji-vci-client-ios-swift" */,
|
||||
9CAE74EC2E2E38F800C2532C /* XCRemoteSwiftPackageReference "pixelpass-ios-swift" */,
|
||||
);
|
||||
productRefGroup = 83CBBA001A601CBA00E9B192 /* Products */;
|
||||
projectDirPath = "";
|
||||
@@ -641,11 +642,11 @@
|
||||
CODE_SIGN_ENTITLEMENTS = Inji/InjiRelease.entitlements;
|
||||
CODE_SIGN_IDENTITY = "Apple Distribution";
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "Apple Distribution";
|
||||
CODE_SIGN_STYLE = Manual;
|
||||
CODE_SIGN_STYLE = Manual;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
DEFINES_MODULE = YES;
|
||||
DEVELOPMENT_TEAM = "";
|
||||
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = V2ABX7953Z;
|
||||
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = V2ABX7953Z;
|
||||
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = arm64;
|
||||
INFOPLIST_FILE = Inji/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
|
||||
@@ -663,7 +664,7 @@
|
||||
PRODUCT_BUNDLE_IDENTIFIER = io.mosip.inji.wallet.mobileid;
|
||||
PRODUCT_NAME = Inji;
|
||||
PROVISIONING_PROFILE_SPECIFIER = "match AppStore io.mosip.inji.wallet.mobileid";
|
||||
"PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "match AppStore io.mosip.inji.wallet.mobileid";
|
||||
"PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "match AppStore io.mosip.inji.wallet.mobileid";
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "";
|
||||
SWIFT_VERSION = 5.0;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
@@ -701,7 +702,7 @@
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
CXX = "";
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
@@ -833,6 +834,14 @@
|
||||
version = 0.5.0;
|
||||
};
|
||||
};
|
||||
9CAE74EC2E2E38F800C2532C /* XCRemoteSwiftPackageReference "pixelpass-ios-swift" */ = {
|
||||
isa = XCRemoteSwiftPackageReference;
|
||||
repositoryURL = "https://github.com/mosip/pixelpass-ios-swift/";
|
||||
requirement = {
|
||||
branch = "release-0.6.x";
|
||||
kind = branch;
|
||||
};
|
||||
};
|
||||
9CCCA19C2CF87A8400D5A461 /* XCRemoteSwiftPackageReference "secure-keystore-ios-swift" */ = {
|
||||
isa = XCRemoteSwiftPackageReference;
|
||||
repositoryURL = "https://github.com/mosip/secure-keystore-ios-swift";
|
||||
@@ -845,23 +854,15 @@
|
||||
isa = XCRemoteSwiftPackageReference;
|
||||
repositoryURL = "https://github.com/mosip/inji-openid4vp-ios-swift";
|
||||
requirement = {
|
||||
branch = "release-0.3.x";
|
||||
branch = develop;
|
||||
kind = branch;
|
||||
};
|
||||
};
|
||||
9CD470CF2DFFF89C00C207F9 /* XCRemoteSwiftPackageReference "inji-vci-client-ios-swift" */ = {
|
||||
9CDFD30E2E28CA7B00505CEF /* XCRemoteSwiftPackageReference "inji-vci-client-ios-swift" */ = {
|
||||
isa = XCRemoteSwiftPackageReference;
|
||||
repositoryURL = "https://github.com/mosip/inji-vci-client-ios-swift/";
|
||||
requirement = {
|
||||
branch = develop;
|
||||
kind = branch;
|
||||
};
|
||||
};
|
||||
9CFB37472DDDC99F00C199A8 /* XCRemoteSwiftPackageReference "pixelpass-ios-swift" */ = {
|
||||
isa = XCRemoteSwiftPackageReference;
|
||||
repositoryURL = "https://github.com/mosip/pixelpass-ios-swift/";
|
||||
requirement = {
|
||||
branch = develop;
|
||||
branch = "release-0.4.x";
|
||||
kind = branch;
|
||||
};
|
||||
};
|
||||
@@ -873,6 +874,11 @@
|
||||
package = 9C4850412C3E5873002ECBD5 /* XCRemoteSwiftPackageReference "tuvali-ios-swift" */;
|
||||
productName = "ios-tuvali-library";
|
||||
};
|
||||
9CAE74ED2E2E38F800C2532C /* pixelpass */ = {
|
||||
isa = XCSwiftPackageProductDependency;
|
||||
package = 9CAE74EC2E2E38F800C2532C /* XCRemoteSwiftPackageReference "pixelpass-ios-swift" */;
|
||||
productName = pixelpass;
|
||||
};
|
||||
9CCCA19D2CF87A8400D5A461 /* securekeystore */ = {
|
||||
isa = XCSwiftPackageProductDependency;
|
||||
package = 9CCCA19C2CF87A8400D5A461 /* XCRemoteSwiftPackageReference "secure-keystore-ios-swift" */;
|
||||
@@ -883,16 +889,11 @@
|
||||
package = 9CD470CC2DFFF86600C207F9 /* XCRemoteSwiftPackageReference "inji-openid4vp-ios-swift" */;
|
||||
productName = OpenID4VP;
|
||||
};
|
||||
9CD470D02DFFF89C00C207F9 /* VCIClient */ = {
|
||||
9CDFD30F2E28CA7B00505CEF /* VCIClient */ = {
|
||||
isa = XCSwiftPackageProductDependency;
|
||||
package = 9CD470CF2DFFF89C00C207F9 /* XCRemoteSwiftPackageReference "inji-vci-client-ios-swift" */;
|
||||
package = 9CDFD30E2E28CA7B00505CEF /* XCRemoteSwiftPackageReference "inji-vci-client-ios-swift" */;
|
||||
productName = VCIClient;
|
||||
};
|
||||
9CFB37482DDDC9A000C199A8 /* pixelpass */ = {
|
||||
isa = XCSwiftPackageProductDependency;
|
||||
package = 9CFB37472DDDC99F00C199A8 /* XCRemoteSwiftPackageReference "pixelpass-ios-swift" */;
|
||||
productName = pixelpass;
|
||||
};
|
||||
/* End XCSwiftPackageProductDependency section */
|
||||
};
|
||||
rootObject = 83CBB9F71A601CBA00E9B192 /* Project object */;
|
||||
|
||||
@@ -19,6 +19,24 @@
|
||||
"version" : "1.1.0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"identity" : "base58swift",
|
||||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/keefertaylor/Base58Swift.git",
|
||||
"state" : {
|
||||
"revision" : "ce8ba8aa893f7e209e9c99c35ee61d6f1235881d",
|
||||
"version" : "2.1.7"
|
||||
}
|
||||
},
|
||||
{
|
||||
"identity" : "bigint",
|
||||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/attaswift/BigInt.git",
|
||||
"state" : {
|
||||
"revision" : "018a5925f60f9e0523edd261de394a0898fe95b7",
|
||||
"version" : "3.1.0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"identity" : "crcswift",
|
||||
"kind" : "remoteSourceControl",
|
||||
@@ -51,8 +69,8 @@
|
||||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/mosip/inji-openid4vp-ios-swift",
|
||||
"state" : {
|
||||
"branch" : "release-0.3.x",
|
||||
"revision" : "3e963ec60e4beb77f020eb1230df019c45c74f56"
|
||||
"branch" : "develop",
|
||||
"revision" : "b93f78c94cd7632f2a80e869520788abd1378621"
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -60,8 +78,8 @@
|
||||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/mosip/inji-vci-client-ios-swift/",
|
||||
"state" : {
|
||||
"branch" : "develop",
|
||||
"revision" : "8a39bbf7805af4c615904090a027fa472e5f4534"
|
||||
"branch" : "release-0.4.x",
|
||||
"revision" : "56359149fbfa61e4fd334df21bf2116e05b4d02d"
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -78,8 +96,8 @@
|
||||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/mosip/pixelpass-ios-swift/",
|
||||
"state" : {
|
||||
"branch" : "develop",
|
||||
"revision" : "78a8b507f5bd0046e273e3ba962696b44aea0e33"
|
||||
"branch" : "release-0.6.x",
|
||||
"revision" : "78faea2ff48626ef9a6d198123bcf7b299acefd1"
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -100,12 +118,21 @@
|
||||
"version" : "0.3.0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"identity" : "siphash",
|
||||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/attaswift/SipHash",
|
||||
"state" : {
|
||||
"revision" : "e325083424688055363bbfcb7f1a440d7d7a1bae",
|
||||
"version" : "1.2.2"
|
||||
}
|
||||
},
|
||||
{
|
||||
"identity" : "swiftcbor",
|
||||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/valpackett/SwiftCBOR",
|
||||
"location" : "https://github.com/abhip2565/SwiftCBOR",
|
||||
"state" : {
|
||||
"revision" : "04ccff117f6549121d5721ec84fdf0162122b90e",
|
||||
"revision" : "cc4e195a0ea2dce88f2fd6c6d73b2504e3c884fd",
|
||||
"version" : "0.5.0"
|
||||
}
|
||||
},
|
||||
@@ -128,5 +155,5 @@
|
||||
}
|
||||
}
|
||||
],
|
||||
"version" : 2
|
||||
"version" : 3
|
||||
}
|
||||
|
||||
@@ -3,11 +3,13 @@
|
||||
|
||||
@interface RCT_EXTERN_MODULE(InjiOpenID4VP, NSObject)
|
||||
|
||||
RCT_EXTERN_METHOD(init:(NSString *)appId)
|
||||
RCT_EXTERN_METHOD(initSdk:(NSString *)appId
|
||||
walletMetadata:(id)walletMetadata
|
||||
resolver:(RCTPromiseResolveBlock)resolve
|
||||
rejecter:(RCTPromiseRejectBlock)reject)
|
||||
|
||||
RCT_EXTERN_METHOD(authenticateVerifier:(NSString *)urlEncodedAuthorizationRequest
|
||||
trustedVerifierJSON:(id)trustedVerifierJSON
|
||||
walletMetadata:(id)walletMetadata
|
||||
shouldValidateClient:(BOOL)shouldValidateClient
|
||||
resolver:(RCTPromiseResolveBlock)resolve
|
||||
rejecter:(RCTPromiseRejectBlock)reject)
|
||||
@@ -23,6 +25,7 @@ RCT_EXTERN_METHOD(shareVerifiablePresentation:(id)vpResponseMetadata
|
||||
rejecter:(RCTPromiseRejectBlock)reject)
|
||||
|
||||
RCT_EXTERN_METHOD(sendErrorToVerifier:(NSString *)error
|
||||
:(NSString *)errorCode
|
||||
resolver:(RCTPromiseResolveBlock)resolve
|
||||
rejecter:(RCTPromiseRejectBlock)reject)
|
||||
|
||||
|
||||
@@ -7,19 +7,25 @@ class RNOpenId4VpModule: NSObject, RCTBridgeModule {
|
||||
|
||||
private var openID4VP: OpenID4VP?
|
||||
|
||||
|
||||
static func moduleName() -> String {
|
||||
return "InjiOpenID4VP"
|
||||
}
|
||||
|
||||
@objc
|
||||
func `init`(_ appId: String) {
|
||||
openID4VP = OpenID4VP(traceabilityId: appId)
|
||||
func `initSdk`(_ appId: String, walletMetadata: AnyObject?,resolver resolve: @escaping RCTPromiseResolveBlock, rejecter reject: @escaping RCTPromiseRejectBlock) {
|
||||
do {
|
||||
let walletMetadataObject = try getWalletMetadataFromDict(walletMetadata, reject: reject)
|
||||
openID4VP = OpenID4VP(traceabilityId: appId, walletMetadata: walletMetadataObject)
|
||||
resolve(true)
|
||||
} catch {
|
||||
reject("OPENID4VP", error.localizedDescription, error)
|
||||
}
|
||||
}
|
||||
|
||||
@objc
|
||||
func authenticateVerifier(_ urlEncodedAuthorizationRequest: String,
|
||||
trustedVerifierJSON: AnyObject,
|
||||
walletMetadata: AnyObject?,
|
||||
shouldValidateClient: Bool,
|
||||
resolver resolve: @escaping RCTPromiseResolveBlock,
|
||||
rejecter reject: @escaping RCTPromiseRejectBlock) {
|
||||
@@ -38,18 +44,17 @@ class RNOpenId4VpModule: NSObject, RCTBridgeModule {
|
||||
return Verifier(clientId: clientId, responseUris: responseUris)
|
||||
}
|
||||
|
||||
let walletMetadataObject = try getWalletMetadataFromDict(walletMetadata as Any, reject: reject)
|
||||
|
||||
let authenticationResponse: AuthorizationRequest = try await openID4VP!.authenticateVerifier(
|
||||
urlEncodedAuthorizationRequest: urlEncodedAuthorizationRequest,
|
||||
trustedVerifierJSON: trustedVerifiersList,
|
||||
shouldValidateClient: shouldValidateClient, walletMetadata: walletMetadataObject
|
||||
shouldValidateClient: shouldValidateClient
|
||||
)
|
||||
|
||||
let response = try toJsonString(jsonObject: authenticationResponse)
|
||||
resolve(response)
|
||||
} catch {
|
||||
reject("OPENID4VP", error.localizedDescription, error)
|
||||
rejectWithOpenID4VPError(error, reject: reject)
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -97,7 +102,7 @@ class RNOpenId4VpModule: NSObject, RCTBridgeModule {
|
||||
reject("ERROR", "Failed to serialize JSON", nil)
|
||||
}
|
||||
} catch {
|
||||
reject("OPENID4VP", error.localizedDescription, error)
|
||||
rejectWithOpenID4VPError(error, reject: reject)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -140,7 +145,8 @@ class RNOpenId4VpModule: NSObject, RCTBridgeModule {
|
||||
formattedVPTokenSigningResults[.mso_mdoc] = MdocVPTokenSigningResult(docTypeToDeviceAuthentication: docTypeToDeviceAuthentication)
|
||||
|
||||
default:
|
||||
reject("OPENID4VP", "Credential format not supported", nil)
|
||||
let error = NSError(domain: "Credential format '\(credentialFormat)' is not supported", code: 0)
|
||||
rejectWithOpenID4VPError(error, reject: reject)
|
||||
return
|
||||
}
|
||||
}
|
||||
@@ -148,23 +154,32 @@ class RNOpenId4VpModule: NSObject, RCTBridgeModule {
|
||||
let response = try await openID4VP?.shareVerifiablePresentation(vpTokenSigningResults: formattedVPTokenSigningResults)
|
||||
resolve(response)
|
||||
} catch {
|
||||
reject("OPENID4VP", error.localizedDescription, error)
|
||||
rejectWithOpenID4VPError(error, reject: reject)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@objc
|
||||
func sendErrorToVerifier(_ error: String, _ errorCode: String,
|
||||
resolver resolve: @escaping RCTPromiseResolveBlock,
|
||||
rejecter reject: @escaping RCTPromiseRejectBlock) {
|
||||
@objc
|
||||
func sendErrorToVerifier(_ error: String, _ errorCode: String,
|
||||
resolver resolve: @escaping RCTPromiseResolveBlock,
|
||||
rejecter reject: @escaping RCTPromiseRejectBlock) {
|
||||
Task {
|
||||
enum VerifierError: Error {
|
||||
case customError(String)
|
||||
}
|
||||
await openID4VP?.sendErrorToVerifier(error: VerifierError.customError(error))
|
||||
resolve(true)
|
||||
let exception: OpenID4VPException = {
|
||||
switch errorCode {
|
||||
case OpenID4VPErrorCodes.accessDenied:
|
||||
return AccessDenied(message: error, className: Self.moduleName())
|
||||
case OpenID4VPErrorCodes.invalidTransactionData:
|
||||
return InvalidTransactionData(message: error, className: Self.moduleName())
|
||||
default:
|
||||
return GenericFailure(message: error, className: Self.moduleName())
|
||||
}
|
||||
}()
|
||||
|
||||
await openID4VP?.sendErrorToVerifier(error: exception)
|
||||
resolve(true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
func toJsonString(jsonObject: AuthorizationRequest) throws -> String {
|
||||
let encoder = JSONEncoder()
|
||||
@@ -180,6 +195,17 @@ class RNOpenId4VpModule: NSObject, RCTBridgeModule {
|
||||
static func requiresMainQueueSetup() -> Bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func rejectWithOpenID4VPError(_ error: Error, reject: RCTPromiseRejectBlock) {
|
||||
if let openidError = error as? OpenID4VPException {
|
||||
reject(openidError.errorCode, openidError.message, openidError)
|
||||
} else {
|
||||
let nsError = NSError(domain: error.localizedDescription, code: 0)
|
||||
reject("ERR_UNKNOWN", nsError.localizedDescription, nsError)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
struct EncodableWrapper: Encodable {
|
||||
@@ -205,22 +231,42 @@ func getWalletMetadataFromDict(_ walletMetadata: Any,
|
||||
throw NSError(domain: "", code: -1, userInfo: [NSLocalizedDescriptionKey: "Invalid Wallet Metadata"])
|
||||
}
|
||||
|
||||
var vpFormatsSupported: [String: VPFormatSupported] = [:]
|
||||
var vpFormatsSupported: [FormatType: VPFormatSupported] = [:]
|
||||
if let vpFormatsSupportedDict = metadata["vp_formats_supported"] as? [String: Any],
|
||||
let ldpVcDict = vpFormatsSupportedDict["ldp_vc"] as? [String: Any] {
|
||||
let algValuesSupported = ldpVcDict["alg_values_supported"] as? [String]
|
||||
vpFormatsSupported["ldp_vc"] = VPFormatSupported(algValuesSupported: algValuesSupported)
|
||||
vpFormatsSupported[.ldp_vc] = VPFormatSupported(algValuesSupported: algValuesSupported)
|
||||
if let mdocDict = vpFormatsSupportedDict["mso_mdoc"] as? [String: Any] {
|
||||
let mdocAlgValuesSupported = mdocDict["alg_values_supported"] as? [String]
|
||||
vpFormatsSupported[.mso_mdoc] = VPFormatSupported(algValuesSupported: mdocAlgValuesSupported)
|
||||
}
|
||||
} else {
|
||||
vpFormatsSupported["ldp_vc"] = VPFormatSupported(algValuesSupported: nil)
|
||||
vpFormatsSupported[.ldp_vc] = VPFormatSupported(algValuesSupported: nil)
|
||||
}
|
||||
|
||||
let walletMetadataObject = try WalletMetadata(
|
||||
presentationDefinitionURISupported: metadata["presentation_definition_uri_supported"] as? Bool,
|
||||
vpFormatsSupported: vpFormatsSupported,
|
||||
clientIdSchemesSupported: metadata["client_id_schemes_supported"] as? [String],
|
||||
requestObjectSigningAlgValuesSupported: metadata["request_object_signing_alg_values_supported"] as? [String],
|
||||
authorizationEncryptionAlgValuesSupported: metadata["authorization_encryption_alg_values_supported"] as? [String],
|
||||
authorizationEncryptionEncValuesSupported: metadata["authorization_encryption_enc_values_supported"] as? [String]
|
||||
clientIdSchemesSupported: mapStringsToEnum(metadata["client_id_schemes_supported"] as? [String] ?? [], using: ClientIdScheme.fromValue),
|
||||
requestObjectSigningAlgValuesSupported: mapStringsToEnum(metadata["request_object_signing_alg_values_supported"] as? [String] ?? [], using: RequestSigningAlgorithm.fromValue),
|
||||
authorizationEncryptionAlgValuesSupported: mapStringsToEnum(metadata["authorization_encryption_alg_values_supported"] as? [String] ?? [], using: KeyManagementAlgorithm.fromValue),
|
||||
authorizationEncryptionEncValuesSupported: mapStringsToEnum(metadata["authorization_encryption_enc_values_supported"] as? [String] ?? [], using: ContentEncryptionAlgorithm.fromValue)
|
||||
)
|
||||
return walletMetadataObject
|
||||
}
|
||||
|
||||
func mapStringsToEnum<T: RawRepresentable>(
|
||||
_ input: [String],
|
||||
using fromValue: (String) -> T?
|
||||
) throws -> [T] where T.RawValue == String {
|
||||
return try input.map { str in
|
||||
guard let match = fromValue(str) else {
|
||||
throw NSError(
|
||||
domain: "EnumMappingError",
|
||||
code: 1001,
|
||||
userInfo: [NSLocalizedDescriptionKey: "Invalid value '\(str)' for enum \(T.self)"]
|
||||
)
|
||||
}
|
||||
return match
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,12 +12,18 @@ RCT_EXTERN_METHOD(requestCredentialByOffer:(NSString *)credentialOffer
|
||||
resolver:(RCTPromiseResolveBlock)resolve
|
||||
rejecter:(RCTPromiseRejectBlock)reject)
|
||||
|
||||
// Requests a credential from a trusted issuer using issuer metadata and client metadata (both as JSON strings)
|
||||
RCT_EXTERN_METHOD(requestCredentialFromTrustedIssuer:(NSString *)issuerMetadata
|
||||
// Requests a credential from a trusted issuer using issuer URI, configuration ID, and client metadata (all as strings)
|
||||
RCT_EXTERN_METHOD(requestCredentialFromTrustedIssuer:(NSString *)credentialIssuer
|
||||
credentialConfigurationId:(NSString *)credentialConfigurationId
|
||||
clientMetadata:(NSString *)clientMetadata
|
||||
resolver:(RCTPromiseResolveBlock)resolve
|
||||
rejecter:(RCTPromiseRejectBlock)reject)
|
||||
|
||||
// Gets issuer metadata (discovery)
|
||||
RCT_EXTERN_METHOD(getIssuerMetadata:(NSString *)credentialIssuer
|
||||
resolver:(RCTPromiseResolveBlock)resolve
|
||||
rejecter:(RCTPromiseRejectBlock)reject)
|
||||
|
||||
// Sends proof JWT back to native side (in response to onRequestProof)
|
||||
RCT_EXTERN_METHOD(sendProofFromJS:(NSString *)jwtProof)
|
||||
|
||||
@@ -30,6 +36,9 @@ RCT_EXTERN_METHOD(sendTxCodeFromJS:(NSString *)txCode)
|
||||
// Sends issuer trust decision (true/false) back to native side (in response to onCheckIssuerTrust)
|
||||
RCT_EXTERN_METHOD(sendIssuerTrustResponseFromJS:(BOOL)isTrusted)
|
||||
|
||||
// Sends token response JSON back to native side (in response to onRequestTokenResponse)
|
||||
RCT_EXTERN_METHOD(sendTokenResponseFromJS:(NSString *)tokenResponseJson)
|
||||
|
||||
// Required by React Native
|
||||
RCT_EXTERN_METHOD(requiresMainQueueSetup:(BOOL)isRequired)
|
||||
|
||||
|
||||
@@ -4,10 +4,13 @@ import VCIClient
|
||||
|
||||
@objc(InjiVciClient)
|
||||
class RNVCIClientModule: NSObject, RCTBridgeModule {
|
||||
|
||||
private var vciClient: VCIClient?
|
||||
|
||||
private var pendingProofContinuation: ((String) -> Void)?
|
||||
private var pendingAuthCodeContinuation: ((String) -> Void)?
|
||||
private var pendingTxCodeContinuation: ((String) -> Void)?
|
||||
private var pendingTokenResponseContinuation: ((String) -> Void)?
|
||||
private var pendingIssuerTrustDecision: ((Bool) -> Void)?
|
||||
|
||||
static func moduleName() -> String {
|
||||
@@ -19,6 +22,8 @@ class RNVCIClientModule: NSObject, RCTBridgeModule {
|
||||
vciClient = VCIClient(traceabilityId: traceabilityId)
|
||||
}
|
||||
|
||||
// MARK: - Public API
|
||||
|
||||
@objc
|
||||
func requestCredentialByOffer(
|
||||
_ credentialOffer: String,
|
||||
@@ -45,19 +50,24 @@ class RNVCIClientModule: NSObject, RCTBridgeModule {
|
||||
length: length
|
||||
)
|
||||
},
|
||||
getProofJwt: { accessToken, cNonce, issuerMetadata, credentialConfigId in
|
||||
try await self.getProofContinuationHook(
|
||||
accessToken: accessToken,
|
||||
cNonce: cNonce,
|
||||
issuerMetadata: issuerMetadata,
|
||||
credentialConfigId: credentialConfigId
|
||||
)
|
||||
},
|
||||
getAuthCode: { authUrl in
|
||||
authorizeUser: { authUrl in
|
||||
try await self.getAuthCodeContinuationHook(authUrl: authUrl)
|
||||
},
|
||||
onCheckIssuerTrust: { issuerMetadata in
|
||||
try await self.getIssuerTrustDecisionHook(issuerMetadata: issuerMetadata)
|
||||
getTokenResponse: { tokenRequest in
|
||||
try await self.getTokenResponseHook(tokenRequest: tokenRequest)
|
||||
},
|
||||
getProofJwt: { credentialIssuer, cNonce, algos in
|
||||
try await self.getProofContinuationHook(
|
||||
credentialIssuer: credentialIssuer,
|
||||
cNonce: cNonce,
|
||||
proofSigningAlgorithmsSupported: algos
|
||||
)
|
||||
},
|
||||
onCheckIssuerTrust: { credentialIssuer, issuerDisplay in
|
||||
try await self.getIssuerTrustDecisionHook(
|
||||
credentialIssuer: credentialIssuer,
|
||||
issuerDisplay: issuerDisplay
|
||||
)
|
||||
}
|
||||
)
|
||||
|
||||
@@ -70,7 +80,8 @@ class RNVCIClientModule: NSObject, RCTBridgeModule {
|
||||
|
||||
@objc
|
||||
func requestCredentialFromTrustedIssuer(
|
||||
_ issuerMetadata: String,
|
||||
_ credentialIssuer: String,
|
||||
credentialConfigurationId: String,
|
||||
clientMetadata: String,
|
||||
resolver resolve: @escaping RCTPromiseResolveBlock,
|
||||
rejecter reject: @escaping RCTPromiseRejectBlock
|
||||
@@ -82,22 +93,24 @@ class RNVCIClientModule: NSObject, RCTBridgeModule {
|
||||
return
|
||||
}
|
||||
|
||||
let issuer = try parseIssuerMeta(from: issuerMetadata)
|
||||
let clientMeta = try parseClientMetadata(from: clientMetadata)
|
||||
|
||||
let response = try await vciClient.requestCredentialFromTrustedIssuer(
|
||||
issuerMetadata: issuer,
|
||||
credentialIssuer: credentialIssuer,
|
||||
credentialConfigurationId: credentialConfigurationId,
|
||||
clientMetadata: clientMeta,
|
||||
getProofJwt: { accessToken, cNonce, issuerMetadata, credentialConfigId in
|
||||
try await self.getProofContinuationHook(
|
||||
accessToken: accessToken,
|
||||
cNonce: cNonce,
|
||||
issuerMetadata: issuerMetadata,
|
||||
credentialConfigId: credentialConfigId
|
||||
)
|
||||
},
|
||||
getAuthCode: { authUrl in
|
||||
authorizeUser: { authUrl in
|
||||
try await self.getAuthCodeContinuationHook(authUrl: authUrl)
|
||||
},
|
||||
getTokenResponse: { tokenRequest in
|
||||
try await self.getTokenResponseHook(tokenRequest: tokenRequest)
|
||||
},
|
||||
getProofJwt: { credentialIssuer, cNonce, algos in
|
||||
try await self.getProofContinuationHook(
|
||||
credentialIssuer: credentialIssuer,
|
||||
cNonce: cNonce,
|
||||
proofSigningAlgorithmsSupported: algos
|
||||
)
|
||||
}
|
||||
)
|
||||
|
||||
@@ -107,54 +120,51 @@ class RNVCIClientModule: NSObject, RCTBridgeModule {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@objc
|
||||
func getIssuerMetadata(
|
||||
_ credentialIssuer: String,
|
||||
resolver resolve: @escaping RCTPromiseResolveBlock,
|
||||
rejecter reject: @escaping RCTPromiseRejectBlock
|
||||
) {
|
||||
Task {
|
||||
do {
|
||||
guard let vciClient = vciClient else {
|
||||
reject(nil, "VCIClient not initialized", nil)
|
||||
return
|
||||
}
|
||||
|
||||
private func getProofContinuationHook(
|
||||
accessToken: String,
|
||||
cNonce: String?,
|
||||
issuerMetadata: [String: Any]?,
|
||||
credentialConfigId: String?
|
||||
) async throws -> String {
|
||||
var issuerMetadataJson: String = ""
|
||||
let metadata = try await vciClient.getIssuerMetadata(credentialIssuer: credentialIssuer)
|
||||
|
||||
if let issuerMetadata = issuerMetadata {
|
||||
if let data = try? JSONSerialization.data(withJSONObject: issuerMetadata, options: []),
|
||||
let jsonString = String(data: data, encoding: .utf8) {
|
||||
issuerMetadataJson = jsonString
|
||||
let data = try JSONSerialization.data(withJSONObject: metadata, options: [])
|
||||
guard let jsonString = String(data: data, encoding: .utf8) else {
|
||||
throw NSError(domain: "JSONEncodingError", code: 0)
|
||||
}
|
||||
|
||||
resolve(jsonString)
|
||||
} catch {
|
||||
reject(nil, error.localizedDescription, nil)
|
||||
}
|
||||
}
|
||||
|
||||
if let bridge = RCTBridge.current() {
|
||||
let payload: [String: Any] = [
|
||||
"accessToken": accessToken,
|
||||
"cNonce": cNonce ?? NSNull(),
|
||||
"issuerMetadata": issuerMetadataJson,
|
||||
"credentialConfigurationId": credentialConfigId ?? NSNull(),
|
||||
]
|
||||
bridge.eventDispatcher().sendAppEvent(withName: "onRequestProof", body: payload)
|
||||
}
|
||||
|
||||
return try await withCheckedThrowingContinuation { continuation in
|
||||
self.pendingProofContinuation = { jwt in continuation.resume(returning: jwt) }
|
||||
}
|
||||
}
|
||||
|
||||
private func getAuthCodeContinuationHook(authUrl: String) async throws -> String {
|
||||
if let bridge = RCTBridge.current() {
|
||||
bridge.eventDispatcher().sendAppEvent(withName: "onRequestAuthCode", body: ["authorizationEndpoint": authUrl])
|
||||
}
|
||||
|
||||
return try await withCheckedThrowingContinuation { continuation in
|
||||
self.pendingAuthCodeContinuation = { code in continuation.resume(returning: code) }
|
||||
}
|
||||
}
|
||||
// MARK: - Callbacks to JS
|
||||
|
||||
private func getTxCodeHook(inputMode: String?, description: String?, length: Int? ) async throws -> String {
|
||||
private func getTxCodeHook(
|
||||
inputMode: String?,
|
||||
description: String?,
|
||||
length: Int?
|
||||
) async throws -> String {
|
||||
if let bridge = RCTBridge.current() {
|
||||
bridge.eventDispatcher().sendAppEvent(withName: "onRequestTxCode", body: [
|
||||
"inputMode": inputMode,
|
||||
"description": description,
|
||||
"length": length
|
||||
])
|
||||
bridge.eventDispatcher().sendAppEvent(
|
||||
withName: "onRequestTxCode",
|
||||
body: [
|
||||
"inputMode": inputMode,
|
||||
"description": description,
|
||||
"length": length
|
||||
]
|
||||
)
|
||||
}
|
||||
|
||||
return try await withCheckedThrowingContinuation { continuation in
|
||||
@@ -162,15 +172,87 @@ class RNVCIClientModule: NSObject, RCTBridgeModule {
|
||||
}
|
||||
}
|
||||
|
||||
private func getIssuerTrustDecisionHook(issuerMetadata: [String: Any]) async throws -> Bool {
|
||||
var metadataJson = ""
|
||||
if let data = try? JSONSerialization.data(withJSONObject: issuerMetadata, options: []),
|
||||
let string = String(data: data, encoding: .utf8) {
|
||||
metadataJson = string
|
||||
private func getAuthCodeContinuationHook(authUrl: String) async throws -> String {
|
||||
if let bridge = RCTBridge.current() {
|
||||
bridge.eventDispatcher().sendAppEvent(
|
||||
withName: "onRequestAuthCode",
|
||||
body: ["authorizationUrl": authUrl]
|
||||
)
|
||||
}
|
||||
|
||||
return try await withCheckedThrowingContinuation { continuation in
|
||||
self.pendingAuthCodeContinuation = { code in continuation.resume(returning: code) }
|
||||
}
|
||||
}
|
||||
|
||||
private func getProofContinuationHook(
|
||||
credentialIssuer: String,
|
||||
cNonce: String?,
|
||||
proofSigningAlgorithmsSupported: [String]
|
||||
) async throws -> String {
|
||||
let jsonData = try JSONSerialization.data(withJSONObject: proofSigningAlgorithmsSupported, options: [])
|
||||
let jsonString = String(data: jsonData, encoding: .utf8) ?? "{}"
|
||||
if let bridge = RCTBridge.current() {
|
||||
bridge.eventDispatcher().sendAppEvent(withName: "onCheckIssuerTrust", body: ["issuerMetadata": metadataJson])
|
||||
bridge.eventDispatcher().sendAppEvent(
|
||||
withName: "onRequestProof",
|
||||
body: [
|
||||
"credentialIssuer": credentialIssuer,
|
||||
"cNonce": cNonce,
|
||||
"proofSigningAlgorithmsSupported": jsonString
|
||||
]
|
||||
)
|
||||
}
|
||||
|
||||
return try await withCheckedThrowingContinuation { continuation in
|
||||
self.pendingProofContinuation = { jwt in continuation.resume(returning: jwt) }
|
||||
}
|
||||
}
|
||||
|
||||
private func getTokenResponseHook(tokenRequest: TokenRequest) async throws -> TokenResponse {
|
||||
if let bridge = RCTBridge.current() {
|
||||
let tokenRequest: [String: Any] = [
|
||||
"grantType": tokenRequest.grantType.rawValue,
|
||||
"tokenEndpoint": tokenRequest.tokenEndpoint,
|
||||
"authCode": tokenRequest.authCode ?? NSNull(),
|
||||
"preAuthCode": tokenRequest.preAuthCode ?? NSNull(),
|
||||
"txCode": tokenRequest.txCode ?? NSNull(),
|
||||
"clientId": tokenRequest.clientId ?? NSNull(),
|
||||
"redirectUri": tokenRequest.redirectUri ?? NSNull(),
|
||||
"codeVerifier": tokenRequest.codeVerifier ?? NSNull()
|
||||
]
|
||||
|
||||
bridge.eventDispatcher().sendAppEvent(
|
||||
withName: "onRequestTokenResponse",
|
||||
body: ["tokenRequest":tokenRequest]
|
||||
)
|
||||
}
|
||||
|
||||
let json = try await withCheckedThrowingContinuation { continuation in
|
||||
self.pendingTokenResponseContinuation = { json in continuation.resume(returning: json) }
|
||||
}
|
||||
|
||||
guard let data = json.data(using: .utf8) else {
|
||||
throw NSError(domain: "Invalid JSON", code: 0)
|
||||
}
|
||||
|
||||
return try JSONDecoder().decode(TokenResponse.self, from: data)
|
||||
}
|
||||
|
||||
private func getIssuerTrustDecisionHook(
|
||||
credentialIssuer: String,
|
||||
issuerDisplay: [[String: Any]]
|
||||
) async throws -> Bool {
|
||||
// Convert issuerDisplay to JSON string
|
||||
let jsonData = try JSONSerialization.data(withJSONObject: issuerDisplay, options: [])
|
||||
let jsonString = String(data: jsonData, encoding: .utf8) ?? "[]"
|
||||
if let bridge = RCTBridge.current() {
|
||||
bridge.eventDispatcher().sendAppEvent(
|
||||
withName: "onCheckIssuerTrust",
|
||||
body: [
|
||||
"credentialIssuer": credentialIssuer,
|
||||
"issuerDisplay": jsonString
|
||||
]
|
||||
)
|
||||
}
|
||||
|
||||
return try await withCheckedThrowingContinuation { continuation in
|
||||
@@ -178,6 +260,8 @@ class RNVCIClientModule: NSObject, RCTBridgeModule {
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Receivers from JS
|
||||
|
||||
@objc(sendProofFromJS:)
|
||||
func sendProofFromJS(_ jwt: String) {
|
||||
pendingProofContinuation?(jwt)
|
||||
@@ -196,24 +280,25 @@ class RNVCIClientModule: NSObject, RCTBridgeModule {
|
||||
pendingTxCodeContinuation = nil
|
||||
}
|
||||
|
||||
@objc(sendTokenResponseFromJS:)
|
||||
func sendTokenResponseFromJS(_ json: String) {
|
||||
pendingTokenResponseContinuation?(json)
|
||||
pendingTokenResponseContinuation = nil
|
||||
}
|
||||
|
||||
@objc(sendIssuerTrustResponseFromJS:)
|
||||
func sendIssuerTrustResponseFromJS(_ trusted: Bool) {
|
||||
pendingIssuerTrustDecision?(trusted)
|
||||
pendingIssuerTrustDecision = nil
|
||||
}
|
||||
|
||||
private func parseClientMetadata(from jsonString: String) throws -> ClientMetaData {
|
||||
// MARK: - JSON Parsing
|
||||
|
||||
private func parseClientMetadata(from jsonString: String) throws -> ClientMetadata {
|
||||
guard let data = jsonString.data(using: .utf8) else {
|
||||
throw NSError(domain: "Invalid JSON string for clientMetadata", code: 0)
|
||||
}
|
||||
return try JSONDecoder().decode(ClientMetaData.self, from: data)
|
||||
}
|
||||
|
||||
private func parseIssuerMeta(from jsonString: String) throws -> IssuerMetadata {
|
||||
guard let data = jsonString.data(using: .utf8) else {
|
||||
throw NSError(domain: "Invalid JSON string for issuerMetadata", code: 0)
|
||||
}
|
||||
return try JSONDecoder().decode(IssuerMetadata.self, from: data)
|
||||
return try JSONDecoder().decode(ClientMetadata.self, from: data)
|
||||
}
|
||||
|
||||
@objc static func requiresMainQueueSetup() -> Bool {
|
||||
|
||||
@@ -19,8 +19,7 @@
|
||||
"SHARED_SUCCESSFULLY": "تمت مشاركة العرض التقديمي لبيانات الاعتماد بنجاح.",
|
||||
"SHARED_WITH_FACE_VERIFIACTION": "تم التحقق من الوجه بنجاح، وتمت مشاركة العرض التقديمي لبيانات الاعتماد بنجاح.",
|
||||
"VERIFIER_AUTHENTICATION_FAILED": "فشلت مصادقة خدمة التحقق أثناء مشاركة VP.",
|
||||
"INVALID_AUTH_REQUEST": "يحتوي رمز الاستجابة السريعة على بيانات غير صالحة أو مفقودة. تحقق مع خدمة التحقق.",
|
||||
"USER_DECLINED_CONSENT": "رفض المستخدم الموافقة على مشاركة العرض التقديمي لبيانات الاعتماد.",
|
||||
"USER_DECLINED_CONSENT": "رفض المستخدم منح الموافقة لمشاركة عرض بيانات الاعتماد.",
|
||||
"SHARED_AFTER_RETRY": "تمت مشاركة العرض التقديمي لبيانات الاعتماد بنجاح بعد إعادة المحاولة.",
|
||||
"SHARED_WITH_FACE_VERIFICATION_AFTER_RETRY": "تم التحقق من الوجه بنجاح، وتمت مشاركة العرض التقديمي لبيانات الاعتماد بنجاح بعد إعادة المحاولة.",
|
||||
"SHARING_FAILED": "فشلت مشاركة العرض التقديمي لبيانات الاعتماد بسبب خطأ فني.",
|
||||
@@ -31,7 +30,13 @@
|
||||
"NO_SELECTED_VC_HAS_IMAGE": "فشلت مشاركة العرض التقديمي لبيانات الاعتماد لأن بيانات الاعتماد المحددة التي يمكن التحقق منها تفتقر إلى صورة الوجه.",
|
||||
"CREDENTIAL_MISMATCH_FROM_KEBAB": "حدث عدم تطابق في العرض التقديمي لبيانات الاعتماد أثناء المشاركة من القائمة، بناءً على المطالبات المطلوبة: {{info}}.",
|
||||
"NO_CREDENTIAL_MATCHING_REQUEST": "لم يتم العثور على بيانات اعتماد تطابق طلب خدمة التحقق بناءً على المطالبات المقدمة: {{info}}.",
|
||||
"TECHNICAL_ERROR": "تعذر متابعة مشاركة العرض التقديمي لبيانات الاعتماد بسبب خطأ فني."
|
||||
"TECHNICAL_ERROR": "حدث خطأ أثناء معالجة طلبك.",
|
||||
"INVALID_REQUEST_URI_METHOD": "لم تتم مشاركة الاعتماد — استخدم المُحقق طريقة غير مدعومة.",
|
||||
"INVALID_AUTH_REQUEST": "فشل مشاركة الاعتماد — الطلب يحتوي على معلومات مفقودة أو غير صحيحة.",
|
||||
"REQUEST_COULD_NOT_BE_PROCESSED": "لم تتم مشاركة الاعتماد — تعذر معالجة الطلب بسبب مشكلة فنية.",
|
||||
"INVALID_PRESENTATION_DEFINITION_URI": "لم تتم مشاركة الاعتماد — تحتوي طلب المحقق على تنسيق بيانات غير صحيح.",
|
||||
"SEND_VP_ERROR": "فشلت مشاركة الاعتماد بسبب مشكلة فنية."
|
||||
|
||||
}
|
||||
},
|
||||
"DeviceInfoList": {
|
||||
@@ -216,6 +221,10 @@
|
||||
"title": "لا يوجد اتصال بالإنترنت",
|
||||
"message": "الرجاء التحقق من اتصالك وإعادة المحاولة"
|
||||
},
|
||||
"networkRequestFailed": {
|
||||
"title": "فشل طلب الشبكة",
|
||||
"message": "لا يمكننا معالجة طلبك في الوقت الحالي."
|
||||
},
|
||||
"biometricsCancelled": {
|
||||
"title": "هل تريد إلغاء التنزيل؟",
|
||||
"message": "مطلوب تأكيد البيومترية لمواصلة تنزيل البطاقة."
|
||||
@@ -901,7 +910,7 @@
|
||||
},
|
||||
"sendVPError": {
|
||||
"title": "حدث خطأ ما",
|
||||
"message": "الرسالة: لم نتمكن من مشاركة بطاقتك بسبب مشكلة فنية. انقر فوق إعادة المحاولة للمحاولة مرة أخرى، أو انتقل إلى الصفحة الرئيسية للخروج."
|
||||
"message": "حدثت مشكلة فنية أثناء مشاركة بطاقتك. انقر على \"إعادة المحاولة\" للمحاولة مرة أخرى أو ارجع إلى \"الرئيسية\"."
|
||||
},
|
||||
"noImage": {
|
||||
"title": "حدث خطأ!",
|
||||
@@ -1098,4 +1107,4 @@
|
||||
"confirm": "نعم، أثق بهذا",
|
||||
"cancel": "لا، أعدني"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -19,8 +19,7 @@
|
||||
"SHARED_SUCCESSFULLY": "Credential Presentation is shared successfully.",
|
||||
"SHARED_WITH_FACE_VERIFIACTION": "Face verification is successful, and the Credential Presentation is shared successfully.",
|
||||
"VERIFIER_AUTHENTICATION_FAILED": "Failed to authenticate the Verification Service during VP sharing.",
|
||||
"INVALID_AUTH_REQUEST": "QR code has invalid or missing data. Check with the verification service.",
|
||||
"USER_DECLINED_CONSENT": "User declined consent for Credential Presentation sharing.",
|
||||
"USER_DECLINED_CONSENT": "User declined consent for credential presentation sharing.",
|
||||
"SHARED_AFTER_RETRY": "Credential Presentation is shared successfully after a retry.",
|
||||
"SHARED_WITH_FACE_VERIFICATION_AFTER_RETRY": "Face verification is successful, and the Credential Presentation is shared successfully after a retry.",
|
||||
"SHARING_FAILED": "Credential Presentation sharing failed due to technical error.",
|
||||
@@ -31,7 +30,12 @@
|
||||
"NO_SELECTED_VC_HAS_IMAGE": "Credential Presentation sharing failed as the selected verifiable credentials lack a face image.",
|
||||
"CREDENTIAL_MISMATCH_FROM_KEBAB": "Credentials Presentation mismatch occurred during sharing from the menu, based on requested claims: {{info}}.",
|
||||
"NO_CREDENTIAL_MATCHING_REQUEST": "No credentials were found that match the verification service's request based on the provided claims: {{info}}.",
|
||||
"TECHNICAL_ERROR": "Credential Presentation sharing could not proceed due to technical error."
|
||||
"TECHNICAL_ERROR": "Something went wrong while processing your request.",
|
||||
"INVALID_REQUEST_URI_METHOD": "Credential not shared— The verifier used a method that isn’t supported.",
|
||||
"INVALID_AUTH_REQUEST" : "Credential sharing failed — The request had missing or incorrect information.",
|
||||
"REQUEST_COULD_NOT_BE_PROCESSED" : "Credential not shared — Request couldn’t be processed due to a technical issue.",
|
||||
"INVALID_PRESENTATION_DEFINITION_URI": "Credential not shared — The verifier’s request had incorrect data format.",
|
||||
"SEND_VP_ERROR": "Credential sharing failed due to a technical issue."
|
||||
}
|
||||
},
|
||||
"DeviceInfoList": {
|
||||
@@ -217,6 +221,10 @@
|
||||
"title": "No internet connection",
|
||||
"message": "Please check your connection and retry"
|
||||
},
|
||||
"networkRequestFailed":{
|
||||
"title": "Network request failed",
|
||||
"message": "We are unable to precess your request at the moment."
|
||||
},
|
||||
"biometricsCancelled": {
|
||||
"title": "Do you want to cancel download?",
|
||||
"message": "Biometric confirmation is required to continue downloading the card."
|
||||
@@ -914,7 +922,7 @@
|
||||
},
|
||||
"sendVPError": {
|
||||
"title": "Something Went Wrong",
|
||||
"message": "Message: We couldn't share your card due to a technical issue. Click Retry to try again, or go to Home to exit."
|
||||
"message": "There was a technical issue while sharing your card. Tap \"Retry\" to try again or go back to \"Home\"."
|
||||
},
|
||||
"noImage": {
|
||||
"title": "An Error Occured!",
|
||||
|
||||
@@ -19,8 +19,7 @@
|
||||
"SHARED_SUCCESSFULLY": "Matagumpay na naibahagi ang Pagtatanghal ng Kredensyal.",
|
||||
"SHARED_WITH_FACE_VERIFIACTION": "Matagumpay ang pag-verify sa mukha, at matagumpay na naibahagi ang Credential Presentation.",
|
||||
"VERIFIER_AUTHENTICATION_FAILED": "Nabigong i-authenticate ang Serbisyo sa Pag-verify sa panahon ng pagbabahagi ng VP.",
|
||||
"INVALID_AUTH_REQUEST": "Ang QR code ay may di-wasto o nawawalang data. Tingnan sa serbisyo ng pag-verify.",
|
||||
"USER_DECLINED_CONSENT": "Tinanggihan ng user ang pahintulot para sa pagbabahagi ng Credential Presentation.",
|
||||
"USER_DECLINED_CONSENT": "பயனர் சான்றுகள் பகிர்வுக்கு ஒப்புதலை நிராகரித்தார்.",
|
||||
"SHARED_AFTER_RETRY": "Ang Pagtatanghal ng Kredensyal ay matagumpay na naibahagi pagkatapos ng muling pagsubok.",
|
||||
"SHARED_WITH_FACE_VERIFICATION_AFTER_RETRY": "Matagumpay ang pag-verify sa mukha, at matagumpay na naibahagi ang Credential Presentation pagkatapos ng muling pagsubok.",
|
||||
"SHARING_FAILED": "Nabigo ang pagbabahagi ng Credential Presentation dahil sa teknikal na error.",
|
||||
@@ -31,7 +30,13 @@
|
||||
"NO_SELECTED_VC_HAS_IMAGE": "Nabigo ang pagbabahagi ng Pagtatanghal ng Kredensyal dahil walang larawan ng mukha ang mga napiling nabe-verify na kredensyal.",
|
||||
"CREDENTIAL_MISMATCH_FROM_KEBAB": "Ang hindi pagkakatugma ng Pagtatanghal ng Mga Kredensyal ay naganap sa panahon ng pagbabahagi mula sa menu, batay sa mga hiniling na claim: {{info}}.",
|
||||
"NO_CREDENTIAL_MATCHING_REQUEST": "Walang nakitang mga kredensyal na tumutugma sa kahilingan ng serbisyo sa pag-verify batay sa mga ibinigay na claim: {{info}}.",
|
||||
"TECHNICAL_ERROR": "Hindi matuloy ang pagbabahagi ng Kredensyal na Presentasyon dahil sa teknikal na error."
|
||||
"TECHNICAL_ERROR": "May nangyaring mali habang pinoproseso ang iyong kahilingan.",
|
||||
"INVALID_REQUEST_URI_METHOD": "Hindi naibahagi ang kredensyal — Gumamit ang verifier ng pamamaraang hindi suportado.",
|
||||
"INVALID_AUTH_REQUEST": "Nabigong maibahagi ang kredensyal — May kulang o maling impormasyon sa kahilingan.",
|
||||
"REQUEST_COULD_NOT_BE_PROCESSED": "Hindi naibahagi ang kredensyal — Hindi naproseso ang kahilingan dahil sa teknikal na isyu.",
|
||||
"INVALID_PRESENTATION_DEFINITION_URI": "Hindi naibahagi ang kredensyal — Mali ang format ng datos sa kahilingan ng verifier.",
|
||||
"SEND_VP_ERROR": "Nabigong maibahagi ang kredensyal dahil sa teknikal na isyu."
|
||||
|
||||
}
|
||||
},
|
||||
"DeviceInfoList": {
|
||||
@@ -216,6 +221,10 @@
|
||||
"title": "Pakisuri ang iyong koneksyon at subukang muli",
|
||||
"message": "Mangyaring kumonekta sa internet at subukang muli."
|
||||
},
|
||||
"networkRequestFailed": {
|
||||
"title": "Nabigo ang kahilingan sa network",
|
||||
"message": "Hindi namin maiproseso ang iyong kahilingan sa ngayon."
|
||||
},
|
||||
"biometricsCancelled": {
|
||||
"title": "Gusto mo bang kanselahin ang pag-download?",
|
||||
"message": "Kinakailangan ang biometric confirmation para magpatuloy sa pag-download ng card."
|
||||
@@ -882,7 +891,7 @@
|
||||
"title": "Oops! Isang Error ang Naganap.",
|
||||
"message": "Nagkaroon ng teknikal na problema habang pinoproseso ang iyong kahilingan. Maaari mong subukang muli pagkatapos ng ilang sandali."
|
||||
},
|
||||
"vpFormatsNotSupported": {
|
||||
"vpFormatsNotSupported": {
|
||||
"title": "Hindi Suportadong Kahilingan",
|
||||
"message": "Ang kahilingang ito ay hindi suportado. Pakiusap, sabihan ang tagapagsuri na subukan sa ibang paraan."
|
||||
},
|
||||
@@ -904,7 +913,7 @@
|
||||
},
|
||||
"sendVPError": {
|
||||
"title": "May Nangyaring Mali",
|
||||
"message": "Mensahe: Hindi namin naibahagi ang iyong card dahil sa isang teknikal na isyu. I-click ang Retry para subukang muli, o pumunta sa Home upang lumabas."
|
||||
"message": "Nagkaroon ng teknikal na problema habang ibinabahagi ang iyong card. Pindutin ang \"Subukang Muli\" para subukang muli o bumalik sa \"Home\"."
|
||||
},
|
||||
"noImage": {
|
||||
"title": "Isang Error ang Naganap!",
|
||||
@@ -1101,4 +1110,4 @@
|
||||
"confirm": "Oo, Pinagkakatiwalaan Ko Ito",
|
||||
"cancel": "Hindi, Bumalik Tayo"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -19,8 +19,7 @@
|
||||
"SHARED_SUCCESSFULLY": "क्रेडेंशियल प्रेजेंटेशन सफलतापूर्वक साझा किया गया है.",
|
||||
"SHARED_WITH_FACE_VERIFIACTION": "चेहरा सत्यापन सफल है, और क्रेडेंशियल प्रस्तुति सफलतापूर्वक साझा की गई है।",
|
||||
"VERIFIER_AUTHENTICATION_FAILED": "वीपी साझाकरण के दौरान सत्यापन सेवा को प्रमाणित करने में विफल।",
|
||||
"INVALID_AUTH_REQUEST": "QR कोड में अमान्य या अनुपलब्ध डेटा है. सत्यापन सेवा से जांचें.",
|
||||
"USER_DECLINED_CONSENT": "उपयोगकर्ता ने क्रेडेंशियल प्रेजेंटेशन साझा करने के लिए सहमति देने से इनकार कर दिया।",
|
||||
"USER_DECLINED_CONSENT": "उपयोगकर्ता ने क्रेडेंशियल प्रस्तुति साझा करने के लिए सहमति अस्वीकार कर दी।",
|
||||
"SHARED_AFTER_RETRY": "पुन: प्रयास के बाद क्रेडेंशियल प्रस्तुति सफलतापूर्वक साझा की जाती है।",
|
||||
"SHARED_WITH_FACE_VERIFICATION_AFTER_RETRY": "चेहरे का सत्यापन सफल है, और पुन: प्रयास के बाद क्रेडेंशियल प्रस्तुति सफलतापूर्वक साझा की जाती है।",
|
||||
"SHARING_FAILED": "तकनीकी त्रुटि के कारण क्रेडेंशियल प्रेजेंटेशन साझा करना विफल रहा।",
|
||||
@@ -31,7 +30,13 @@
|
||||
"NO_SELECTED_VC_HAS_IMAGE": "क्रेडेंशियल प्रस्तुति साझाकरण विफल रहा क्योंकि चयनित सत्यापन योग्य क्रेडेंशियल में चेहरे की छवि का अभाव है।",
|
||||
"CREDENTIAL_MISMATCH_FROM_KEBAB": "अनुरोधित दावों के आधार पर, मेनू से साझा करने के दौरान क्रेडेंशियल प्रस्तुतिकरण बेमेल हुआ: {{info}}।",
|
||||
"NO_CREDENTIAL_MATCHING_REQUEST": "प्रदान किए गए दावों के आधार पर सत्यापन सेवा के अनुरोध से मेल खाने वाला कोई क्रेडेंशियल नहीं मिला: {{info}}।",
|
||||
"TECHNICAL_ERROR": "तकनीकी त्रुटि के कारण क्रेडेंशियल प्रेजेंटेशन साझाकरण आगे नहीं बढ़ सका।"
|
||||
"TECHNICAL_ERROR": "आपके अनुरोध को प्रोसेस करते समय कुछ गलत हो गया।",
|
||||
"INVALID_REQUEST_URI_METHOD": "क्रेडेंशियल साझा नहीं किया गया — सत्यापनकर्ता ने एक असमर्थित विधि का उपयोग किया।",
|
||||
"INVALID_AUTH_REQUEST": "क्रेडेंशियल साझा विफल रहा — अनुरोध में जानकारी अधूरी या गलत थी।",
|
||||
"REQUEST_COULD_NOT_BE_PROCESSED": "क्रेडेंशियल साझा नहीं किया गया — तकनीकी समस्या के कारण अनुरोध प्रोसेस नहीं हो सका।",
|
||||
"INVALID_PRESENTATION_DEFINITION_URI": "क्रेडेंशियल साझा नहीं किया गया — सत्यापनकर्ता की अनुरोध में गलत डेटा प्रारूप था।",
|
||||
"SEND_VP_ERROR": "तकनीकी समस्या के कारण क्रेडेंशियल साझा करना विफल रहा।"
|
||||
|
||||
}
|
||||
},
|
||||
"DeviceInfoList": {
|
||||
@@ -217,6 +222,10 @@
|
||||
"title": "कोई इंटरनेट कनेक्शन नहीं",
|
||||
"message": "कृपया अपना कनेक्शन जांचें और पुनः प्रयास करें"
|
||||
},
|
||||
"networkRequestFailed": {
|
||||
"title": "नेटवर्क अनुरोध विफल हुआ",
|
||||
"message": "हम इस समय आपके अनुरोध को संसाधित करने में असमर्थ हैं।"
|
||||
},
|
||||
"biometricsCancelled": {
|
||||
"title": "क्या आप डाउनलोड रद्द करना चाहते हैं?",
|
||||
"message": "कार्ड डाउनलोड करना जारी रखने के लिए बायोमेट्रिक पुष्टिकरण आवश्यक है।"
|
||||
@@ -907,7 +916,7 @@
|
||||
},
|
||||
"sendVPError": {
|
||||
"title": "कुछ गलत हो गया",
|
||||
"message": "संदेश: तकनीकी समस्या के कारण हम आपका कार्ड साझा नहीं कर सके। पुनः प्रयास करने के लिए 'पुनः प्रयास करें' पर क्लिक करें, या बाहर निकलने के लिए 'मुखपृष्ठ' पर जाएँ।"
|
||||
"message": "आपका कार्ड साझा करते समय एक तकनीकी समस्या हुई। फिर से प्रयास करने के लिए \"पुनः प्रयास करें\" टैप करें या \"होम\" पर वापस जाएं।"
|
||||
},
|
||||
"noImage": {
|
||||
"title": "एक त्रुटि हुई!",
|
||||
@@ -1102,4 +1111,4 @@
|
||||
"confirm": "हाँ, मैं इस पर भरोसा करता हूँ",
|
||||
"cancel": "नहीं, मुझे वापस ले चलो"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -19,8 +19,7 @@
|
||||
"SHARED_SUCCESSFULLY": "ರುಜುವಾತು ಪ್ರಸ್ತುತಿಯನ್ನು ಯಶಸ್ವಿಯಾಗಿ ಹಂಚಿಕೊಳ್ಳಲಾಗಿದೆ.",
|
||||
"SHARED_WITH_FACE_VERIFIACTION": "ಮುಖ ಪರಿಶೀಲನೆ ಯಶಸ್ವಿಯಾಗಿದೆ ಮತ್ತು ರುಜುವಾತು ಪ್ರಸ್ತುತಿಯನ್ನು ಯಶಸ್ವಿಯಾಗಿ ಹಂಚಿಕೊಳ್ಳಲಾಗಿದೆ.",
|
||||
"VERIFIER_AUTHENTICATION_FAILED": "VP ಹಂಚಿಕೆಯ ಸಮಯದಲ್ಲಿ ಪರಿಶೀಲನೆ ಸೇವೆಯನ್ನು ದೃಢೀಕರಿಸಲು ವಿಫಲವಾಗಿದೆ.",
|
||||
"INVALID_AUTH_REQUEST": "QR ಕೋಡ್ ಅಮಾನ್ಯ ಅಥವಾ ಕಾಣೆಯಾದ ಡೇಟಾವನ್ನು ಹೊಂದಿದೆ. ಪರಿಶೀಲನಾ ಸೇವೆಯೊಂದಿಗೆ ಪರಿಶೀಲಿಸಿ.",
|
||||
"USER_DECLINED_CONSENT": "ರುಜುವಾತು ಪ್ರಸ್ತುತಿ ಹಂಚಿಕೆಗೆ ಬಳಕೆದಾರರು ಒಪ್ಪಿಗೆ ನಿರಾಕರಿಸಿದ್ದಾರೆ.",
|
||||
"USER_DECLINED_CONSENT": "ಬಳಕೆದಾರರು ರುಜುವಾತು ಪ್ರಸ್ತುತಿ ಹಂಚಿಕೆಗೆ ಒಪ್ಪಿಗೆ ನೀಡಲಿಲ್ಲ.",
|
||||
"SHARED_AFTER_RETRY": "ಮರುಪ್ರಯತ್ನದ ನಂತರ ರುಜುವಾತು ಪ್ರಸ್ತುತಿಯನ್ನು ಯಶಸ್ವಿಯಾಗಿ ಹಂಚಿಕೊಳ್ಳಲಾಗಿದೆ.",
|
||||
"SHARED_WITH_FACE_VERIFICATION_AFTER_RETRY": "ಮುಖ ಪರಿಶೀಲನೆ ಯಶಸ್ವಿಯಾಗಿದೆ ಮತ್ತು ಮರುಪ್ರಯತ್ನದ ನಂತರ ರುಜುವಾತು ಪ್ರಸ್ತುತಿಯನ್ನು ಯಶಸ್ವಿಯಾಗಿ ಹಂಚಿಕೊಳ್ಳಲಾಗಿದೆ.",
|
||||
"SHARING_FAILED": "ತಾಂತ್ರಿಕ ದೋಷದಿಂದಾಗಿ ರುಜುವಾತು ಪ್ರಸ್ತುತಿ ಹಂಚಿಕೆ ವಿಫಲವಾಗಿದೆ.",
|
||||
@@ -31,7 +30,12 @@
|
||||
"NO_SELECTED_VC_HAS_IMAGE": "ಆಯ್ಕೆಮಾಡಿದ ಪರಿಶೀಲಿಸಬಹುದಾದ ರುಜುವಾತುಗಳಲ್ಲಿ ಮುಖದ ಚಿತ್ರದ ಕೊರತೆಯಿಂದಾಗಿ ರುಜುವಾತು ಪ್ರಸ್ತುತಿ ಹಂಚಿಕೆ ವಿಫಲವಾಗಿದೆ.",
|
||||
"CREDENTIAL_MISMATCH_FROM_KEBAB": "ವಿನಂತಿಸಿದ ಹಕ್ಕುಗಳ ಆಧಾರದ ಮೇಲೆ ಮೆನುವಿನಿಂದ ಹಂಚಿಕೊಳ್ಳುವಾಗ ರುಜುವಾತುಗಳ ಪ್ರಸ್ತುತಿ ಹೊಂದಿಕೆಯಾಗುತ್ತಿಲ್ಲ: {{info}}.",
|
||||
"NO_CREDENTIAL_MATCHING_REQUEST": "ಒದಗಿಸಿದ ಹಕ್ಕುಗಳ ಆಧಾರದ ಮೇಲೆ ಪರಿಶೀಲನೆ ಸೇವೆಯ ವಿನಂತಿಗೆ ಹೊಂದಿಕೆಯಾಗುವ ಯಾವುದೇ ರುಜುವಾತುಗಳು ಕಂಡುಬಂದಿಲ್ಲ: {{info}}.",
|
||||
"TECHNICAL_ERROR": "ತಾಂತ್ರಿಕ ದೋಷದಿಂದಾಗಿ ರುಜುವಾತು ಪ್ರಸ್ತುತಿ ಹಂಚಿಕೆಯನ್ನು ಮುಂದುವರಿಸಲಾಗಲಿಲ್ಲ."
|
||||
"TECHNICAL_ERROR": "ನಿಮ್ಮ ವಿನಂತಿಯನ್ನು ಪ್ರಕ್ರಿಯೆಗೊಳಿಸುವಾಗ ಏನೋ ತಪ್ಪು ಸಂಭವಿಸಿದೆ.",
|
||||
"INVALID_REQUEST_URI_METHOD": "ಅಧికారಪತ್ರವನ್ನು ಹಂಚಲಾಗಿಲ್ಲ — ಪರಿಶೀಲಕರೊಬ್ಬರು ಬೆಂಬಲವಿಲ್ಲದ ವಿಧಾನವನ್ನು ಬಳಸಿದರು.",
|
||||
"INVALID_AUTH_REQUEST": "ಅಧికారಪತ್ರ ಹಂಚಿಕೆಯಲ್ಲಿ ವಿಫಲವಾಯಿತು — ವಿನಂತಿಯಲ್ಲಿ ತಪ್ಪು ಅಥವಾ ಕೊರತೆಯ ಮಾಹಿತಿ ಇದೆ.",
|
||||
"REQUEST_COULD_NOT_BE_PROCESSED": "ಅಧಕಾರಪತ್ರವನ್ನು ಹಂಚಲಾಗಿಲ್ಲ — ತಾಂತ್ರಿಕ ತೊಂದರೆಯಿಂದ ವಿನಂತಿಯನ್ನು ಪ್ರಕ್ರಿಯೆಗೊಳಿಸಲು ಸಾಧ್ಯವಾಗಲಿಲ್ಲ.",
|
||||
"INVALID_PRESENTATION_DEFINITION_URI": "ಅಧಕಾರಪತ್ರವನ್ನು ಹಂಚಲಾಗಿಲ್ಲ — ಪರಿಶೀಲಕರ ವಿನಂತಿಯಲ್ಲಿ ತಪ್ಪಾದ ಡೇಟಾ ಸ್ವರೂಪವಿದೆ.",
|
||||
"SEND_VP_ERROR": "ತಾಂತ್ರಿಕ ಸಮಸ್ಯೆಯ ಕಾರಣದಿಂದ ಅಧಿಕಾರಪತ್ರ ಹಂಚಿಕೆಯಲ್ಲಿ ವಿಫಲವಾಯಿತು."
|
||||
}
|
||||
},
|
||||
"DeviceInfoList": {
|
||||
@@ -216,6 +220,10 @@
|
||||
"title": "ಇಂಟರ್ನೆಟ್ ಸಂಪರ್ಕವಿಲ್ಲ",
|
||||
"message": "ದಯವಿಟ್ಟು ನಿಮ್ಮ ಸಂಪರ್ಕವನ್ನು ಪರಿಶೀಲಿಸಿ ಮತ್ತು ಮರುಪ್ರಯತ್ನಿಸಿ"
|
||||
},
|
||||
"networkRequestFailed": {
|
||||
"title": "ನೆಟ್ವರ್ಕ್ ವಿನಂತಿ ವಿಫಲವಾಗಿದೆ",
|
||||
"message": "ಈ ಕ್ಷಣದಲ್ಲಿ ನಿಮ್ಮ ವಿನಂತಿಯನ್ನು ಪ್ರಕ್ರಿಯೆಗೊಳಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ."
|
||||
},
|
||||
"biometricsCancelled": {
|
||||
"title": "ನೀವು ಡೌನ್ಲೋಡ್ ರದ್ದುಗೊಳಿಸಲು ಬಯಸುವಿರಾ?",
|
||||
"message": "ಕಾರ್ಡ್ ಡೌನ್ಲೋಡ್ ಮಾಡುವುದನ್ನು ಮುಂದುವರಿಸಲು ಬಯೋಮೆಟ್ರಿಕ್ ದೃಢೀಕರಣದ ಅಗತ್ಯವಿದೆ."
|
||||
@@ -883,7 +891,7 @@
|
||||
"title": "ಓಹ್! ಒಂದು ದೋಷ ಸಂಭವಿಸಿದೆ.",
|
||||
"message": "ನಿಮ್ಮ ವಿನಂತಿಯನ್ನು ಪ್ರಕ್ರಿಯೆಗೊಳಿಸುವಾಗ ತಾಂತ್ರಿಕ ತೊಂದರೆ ಸಂಭವಿಸಿದೆ. ದಯವಿಟ್ಟು ಸ್ವಲ್ಪ ಸಮಯದ ನಂತರ ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ."
|
||||
},
|
||||
"vpFormatsNotSupported": {
|
||||
"vpFormatsNotSupported": {
|
||||
"title": "ಬೆಂಬಲಿಸಲ್ಪಟ್ಟ ವಿನಂತಿಯಲ್ಲ",
|
||||
"message": "ಈ ವಿನಂತಿಯನ್ನು ಬೆಂಬಲಿಸಲಾಗದು. ದಯವಿಟ್ಟು ಪರಿಶೀಲಕರನ್ನು ಬೇರೆ ಮಾರ್ಗದಿಂದ ಪ್ರಯತ್ನಿಸಲು ಕೇಳಿ."
|
||||
},
|
||||
@@ -905,7 +913,7 @@
|
||||
},
|
||||
"sendVPError": {
|
||||
"title": "ಏನೋ ತಪ್ಪು ಸಂಭವಿಸಿದೆ",
|
||||
"message": "ಸಂದೇಶ: ತಾಂತ್ರಿಕ ತೊಂದರೆಯಿಂದಾಗಿ ನಿಮ್ಮ ಕಾರ್ಡ್ ಅನ್ನು ಹಂಚಲಾಗಲಿಲ್ಲ. ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಲು 'ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ' ಕ್ಲಿಕ್ ಮಾಡಿ ಅಥವಾ ನಿರ್ಗಮಿಸಲು 'ಮುಖಪುಟ' ಗೆ ಹೋಗಿ."
|
||||
"message": "ನಿಮ್ಮ ಕಾರ್ಡ್ ಹಂಚಿಕೊಳ್ಳುವಾಗ ತಾಂತ್ರಿಕ ಸಮಸ್ಯೆ ಸಂಭವಿಸಿದೆ. ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಲು \"ಮರುಪ್ರಯತ್ನಿಸಿ\" ಒತ್ತಿರಿ ಅಥವಾ \"ಮುಖಪುಟ\" ಗೆ ಹಿಂದಿರುಗಿ."
|
||||
},
|
||||
"noImage": {
|
||||
"title": "ಒಂದು ದೋಷ ಸಂಭವಿಸಿದೆ!",
|
||||
@@ -1102,4 +1110,4 @@
|
||||
"confirm": "ಹೌದು, ನಾನು ನಂಬುತ್ತೇನೆ",
|
||||
"cancel": "ಇಲ್ಲ, ನನನ್ನು ಹಿಂದಕ್ಕೆ ಕರೆ"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -19,8 +19,7 @@
|
||||
"SHARED_SUCCESSFULLY": "நற்சான்றிதழ் வழங்கல் வெற்றிகரமாகப் பகிரப்பட்டது.",
|
||||
"SHARED_WITH_FACE_VERIFIACTION": "முக சரிபார்ப்பு வெற்றிகரமாக உள்ளது, மேலும் நற்சான்றிதழ் விளக்கக்காட்சி வெற்றிகரமாக பகிரப்பட்டது.",
|
||||
"VERIFIER_AUTHENTICATION_FAILED": "VP பகிர்வின் போது சரிபார்ப்பு சேவையை அங்கீகரிப்பதில் தோல்வி.",
|
||||
"INVALID_AUTH_REQUEST": "QR குறியீட்டில் தவறான அல்லது விடுபட்ட தரவு உள்ளது. சரிபார்ப்பு சேவையுடன் சரிபார்க்கவும்.",
|
||||
"USER_DECLINED_CONSENT": "நற்சான்றிதழ் விளக்கக்காட்சி பகிர்வுக்கான ஒப்புதலை பயனர் நிராகரித்தார்.",
|
||||
"USER_DECLINED_CONSENT": "பயனர் சான்றுகள் பகிர்வுக்கு ஒப்புதலை நிராகரித்தார்.",
|
||||
"SHARED_AFTER_RETRY": "நற்சான்றிதழ் விளக்கக்காட்சி மீண்டும் முயற்சித்த பிறகு வெற்றிகரமாகப் பகிரப்பட்டது.",
|
||||
"SHARED_WITH_FACE_VERIFICATION_AFTER_RETRY": "முகச் சரிபார்ப்பு வெற்றிகரமாக உள்ளது, மீண்டும் முயற்சித்த பிறகு நற்சான்றிதழ் விளக்கக்காட்சி வெற்றிகரமாகப் பகிரப்பட்டது.",
|
||||
"SHARING_FAILED": "தொழில்நுட்பப் பிழை காரணமாக நற்சான்றிதழ் வழங்கல் பகிர்வு தோல்வியடைந்தது.",
|
||||
@@ -31,7 +30,12 @@
|
||||
"NO_SELECTED_VC_HAS_IMAGE": "தேர்ந்தெடுக்கப்பட்ட சரிபார்க்கக்கூடிய நற்சான்றிதழ்களில் முகப் படம் இல்லாததால் நற்சான்றிதழ் வழங்கல் பகிர்வு தோல்வியடைந்தது.",
|
||||
"CREDENTIAL_MISMATCH_FROM_KEBAB": "கோரப்பட்ட உரிமைகோரல்களின் அடிப்படையில், மெனுவிலிருந்து பகிரும் போது நற்சான்றிதழ்கள் வழங்கல் பொருந்தவில்லை: {{info}}.",
|
||||
"NO_CREDENTIAL_MATCHING_REQUEST": "வழங்கப்பட்ட உரிமைகோரல்களின் அடிப்படையில் சரிபார்ப்பு சேவையின் கோரிக்கையுடன் பொருந்தக்கூடிய நற்சான்றிதழ்கள் எதுவும் கண்டறியப்படவில்லை: {{info}}.",
|
||||
"TECHNICAL_ERROR": "தொழில்நுட்ப பிழை காரணமாக நற்சான்றிதழ் வழங்கல் பகிர்வை தொடர முடியவில்லை."
|
||||
"TECHNICAL_ERROR": "உங்கள் கோரிக்கையை செயலாக்கும் போது ஏதோ தவறு ஏற்பட்டது.",
|
||||
"INVALID_REQUEST_URI_METHOD": "அங்கீகாரம் பகிரப்படவில்லை — சரிபார்ப்பவர் ஆதரிக்கப்படாத முறையை பயன்படுத்தினார்.",
|
||||
"INVALID_AUTH_REQUEST": "அங்கீகாரம் பகிர்வு தோல்வியடைந்தது — கோரிக்கையில் தவறான அல்லது காணாமற்போன தகவல்கள் உள்ளன.",
|
||||
"REQUEST_COULD_NOT_BE_PROCESSED": "அங்கீகாரம் பகிரப்படவில்லை — தொழில்நுட்ப பிரச்சனை காரணமாக கோரிக்கையை செயலாக்க முடியவில்லை.",
|
||||
"INVALID_PRESENTATION_DEFINITION_URI": "அங்கீகாரம் பகிரப்படவில்லை — சரிபார்ப்பவரின் கோரிக்கையில் தவறான தரவுகள் உள்ளன.",
|
||||
"SEND_VP_ERROR": "அங்கீகாரம் பகிர்வதில் தொழில்நுட்ப பிரச்சனை ஏற்பட்டது."
|
||||
}
|
||||
},
|
||||
"DeviceInfoList": {
|
||||
@@ -216,6 +220,10 @@
|
||||
"title": "இணைய இணைப்பு இல்லை",
|
||||
"message": "உங்கள் இணைப்பைச் சரிபார்த்து மீண்டும் முயற்சிக்கவும்"
|
||||
},
|
||||
"networkRequestFailed": {
|
||||
"title": "நெட்வொர்க் கோரிக்கை தோல்வியடைந்தது",
|
||||
"message": "தற்போது உங்கள் கோரிக்கையை செயலாக்க முடியவில்லை."
|
||||
},
|
||||
"biometricsCancelled": {
|
||||
"title": "பதிவிறக்கத்தை ரத்து செய்ய வேண்டுமா?",
|
||||
"message": "கார்டை தொடர்ந்து பதிவிறக்க பயோமெட்ரிக் உறுதிப்படுத்தல் தேவை."
|
||||
@@ -905,7 +913,7 @@
|
||||
},
|
||||
"sendVPError": {
|
||||
"title": "ஏதோ தவறு நடந்துவிட்டது",
|
||||
"message": "தகவல்: தொழில்நுட்ப சிக்கலால் உங்கள் அட்டையை பகிர முடியவில்லை. மீண்டும் முயற்சிக்க 'மீண்டும் முயற்சி' என்பதை கிளிக் செய்யவும், அல்லது வெளியேற 'முகப்பு' என்பதைக் கிளிக் செய்யவும்."
|
||||
"message": "உங்கள் கார்டைப் பகிரும்போது தொழில்நுட்ப சிக்கல் ஏற்பட்டது. மீண்டும் முயற்சிக்க \"மீண்டும் முயற்சி செய்\" என்பதைத் தட்டவும் அல்லது \"முகப்பு\" பக்கம் திரும்பவும்."
|
||||
},
|
||||
"noImage": {
|
||||
"title": "ஒரு பிழை ஏற்பட்டது!",
|
||||
@@ -1102,4 +1110,4 @@
|
||||
"confirm": "ஆம், நம்புகிறேன்",
|
||||
"cancel": "இல்லை, என்னை திரும்ப அழைத்துச் செல்"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,6 +8,7 @@ import {
|
||||
import {
|
||||
EXPIRED_VC_ERROR_CODE,
|
||||
MY_VCS_STORE_KEY,
|
||||
NO_INTERNET,
|
||||
REQUEST_TIMEOUT,
|
||||
isIOS,
|
||||
} from '../../shared/constants';
|
||||
@@ -25,9 +26,8 @@ import {
|
||||
} from '../../shared/telemetry/TelemetryUtils';
|
||||
import {TelemetryConstants} from '../../shared/telemetry/TelemetryConstants';
|
||||
import {NativeModules} from 'react-native';
|
||||
import {KeyTypes} from '../../shared/cryptoutil/KeyTypes';
|
||||
import {VCActivityLog} from '../../components/ActivityLogEvent';
|
||||
import {isNetworkError} from '../../shared/Utils';
|
||||
import {isNetworkError, parseJSON} from '../../shared/Utils';
|
||||
import {issuerType} from './IssuersMachine';
|
||||
|
||||
const {RNSecureKeystoreModule} = NativeModules;
|
||||
@@ -52,9 +52,6 @@ export const IssuersActions = (model: any) => {
|
||||
setIssuers: model.assign({
|
||||
issuers: (_: any, event: any) => event.data as issuerType[],
|
||||
}),
|
||||
setNoInternet: model.assign({
|
||||
errorMessage: () => ErrorMessage.NO_INTERNET,
|
||||
}),
|
||||
setLoadingReasonAsDisplayIssuers: model.assign({
|
||||
loadingReason: 'displayIssuers',
|
||||
}),
|
||||
@@ -75,7 +72,7 @@ export const IssuersActions = (model: any) => {
|
||||
return proofTypesSupported.jwt
|
||||
.proof_signing_alg_values_supported as string[];
|
||||
} else {
|
||||
return [KeyTypes.RS256] as string[];
|
||||
return [] as string[];
|
||||
}
|
||||
},
|
||||
}),
|
||||
@@ -85,17 +82,6 @@ export const IssuersActions = (model: any) => {
|
||||
resetSelectedCredentialType: model.assign({
|
||||
selectedCredentialType: {},
|
||||
}),
|
||||
setNetworkOrTechnicalError: model.assign({
|
||||
errorMessage: (_: any, event: any) => {
|
||||
console.error(
|
||||
`Error occurred during ${event} flow`,
|
||||
event.data.message,
|
||||
);
|
||||
return isNetworkError(event.data.message)
|
||||
? ErrorMessage.NO_INTERNET
|
||||
: ErrorMessage.TECHNICAL_DIFFICULTIES;
|
||||
},
|
||||
}),
|
||||
setCredentialTypeListDownloadFailureError: model.assign({
|
||||
errorMessage: (_: any, event: any) => {
|
||||
if (isNetworkError(event.data.message)) {
|
||||
@@ -109,9 +95,12 @@ export const IssuersActions = (model: any) => {
|
||||
errorMessage: (_: any, event: any) => {
|
||||
console.error(`Error occurred while ${event} -> `, event.data.message);
|
||||
const error = event.data.message;
|
||||
if (isNetworkError(error)) {
|
||||
if (error.includes(NO_INTERNET)) {
|
||||
return ErrorMessage.NO_INTERNET;
|
||||
}
|
||||
if (isNetworkError(error)) {
|
||||
return ErrorMessage.NETWORK_REQUEST_FAILED;
|
||||
}
|
||||
if (error.includes(REQUEST_TIMEOUT)) {
|
||||
return ErrorMessage.REQUEST_TIMEDOUT;
|
||||
}
|
||||
@@ -126,9 +115,6 @@ export const IssuersActions = (model: any) => {
|
||||
return ErrorMessage.GENERIC;
|
||||
},
|
||||
}),
|
||||
setOIDCConfigError: model.assign({
|
||||
errorMessage: (_: any, event: any) => event.data.toString(),
|
||||
}),
|
||||
resetError: model.assign({
|
||||
errorMessage: '',
|
||||
}),
|
||||
@@ -236,20 +222,24 @@ export const IssuersActions = (model: any) => {
|
||||
return context.issuers.find(issuer => issuer.issuer_id === event.id);
|
||||
},
|
||||
}),
|
||||
|
||||
resetSelectedIssuer: model.assign({
|
||||
selectedIssuer: () => ({} as issuerType),
|
||||
}),
|
||||
updateIssuerFromWellknown: model.assign({
|
||||
selectedIssuer: (context: any, event: any) => ({
|
||||
...context.selectedIssuer,
|
||||
credential_audience: event.data.credential_issuer,
|
||||
credential_endpoint: event.data.credential_endpoint,
|
||||
credential_configurations_supported:
|
||||
event.data.credential_configurations_supported,
|
||||
display: event.data.display,
|
||||
authorization_servers: event.data.authorization_servers,
|
||||
}),
|
||||
selectedIssuerWellknownResponse: (_: any, event: any) => {
|
||||
return event.data;
|
||||
},
|
||||
}),
|
||||
setCredential: model.assign({
|
||||
credential: (_: any, event: any) => event.data,
|
||||
credential: (_: any, event: any) => event.data.credential,
|
||||
}),
|
||||
setQrData: model.assign({
|
||||
qrData: (_: any, event: any) => event.data,
|
||||
@@ -261,7 +251,7 @@ export const IssuersActions = (model: any) => {
|
||||
}),
|
||||
setAccessToken: model.assign({
|
||||
accessToken: (_: any, event: any) => {
|
||||
return event.accessToken;
|
||||
return event.data.access_token;
|
||||
},
|
||||
}),
|
||||
setCNonce: model.assign({
|
||||
@@ -269,20 +259,41 @@ export const IssuersActions = (model: any) => {
|
||||
return event.cNonce;
|
||||
},
|
||||
}),
|
||||
setOfferCredentialTypeContexts: model.assign({
|
||||
selectedCredentialType: (context: any, event: any) => {
|
||||
return event.credentialTypes[0];
|
||||
},
|
||||
supportedCredentialTypes: (context: any, event: any) => {
|
||||
return event.credentialTypes;
|
||||
},
|
||||
accessToken: (context: any, event: any) => {
|
||||
return event.accessToken;
|
||||
},
|
||||
cNonce: (context: any, event: any) => {
|
||||
return event.cNonce;
|
||||
setCredentialConfigurationId: model.assign({
|
||||
credentialConfigurationId: (_: any, event: any) => {
|
||||
return event.data.credentialConfigurationId;
|
||||
},
|
||||
}),
|
||||
setCredentialOfferCredentialType: model.assign({
|
||||
selectedCredentialType: (context: any, event: any) => {
|
||||
let credentialTypes: Array<{id: string; [key: string]: any}> = [];
|
||||
const credentialConfigurationId = context.credentialConfigurationId;
|
||||
const issuerMetadata = context.selectedIssuerWellknownResponse;
|
||||
if (
|
||||
issuerMetadata.credential_configurations_supported[
|
||||
credentialConfigurationId
|
||||
]
|
||||
) {
|
||||
credentialTypes.push({
|
||||
id: credentialConfigurationId,
|
||||
...issuerMetadata.credential_configurations_supported[
|
||||
credentialConfigurationId
|
||||
],
|
||||
});
|
||||
return credentialTypes[0];
|
||||
}
|
||||
},
|
||||
}),
|
||||
supportedCredentialTypes: (context: any, event: any) => {
|
||||
return event.credentialTypes;
|
||||
},
|
||||
accessToken: (context: any, event: any) => {
|
||||
return event.accessToken;
|
||||
},
|
||||
cNonce: (context: any, event: any) => {
|
||||
return event.cNonce;
|
||||
},
|
||||
|
||||
setRequestTxCode: model.assign({
|
||||
isTransactionCodeRequested: (_: any, event: any) => {
|
||||
return true;
|
||||
@@ -295,22 +306,32 @@ export const IssuersActions = (model: any) => {
|
||||
},
|
||||
}),
|
||||
setCredentialOfferIssuerWellknownResponse: model.assign({
|
||||
selectedIssuerWellknownResponse: (_: any, event: any) => {
|
||||
return event.issuerMetadata;
|
||||
selectedIssuer: (_: any, event: any) => {
|
||||
return event.data;
|
||||
},
|
||||
wellknownKeyTypes: (_: any, event: any) => {
|
||||
const credType = Object.entries(event.credentialTypes)[0][1];
|
||||
const proofTypesSupported = credType.proof_types_supported;
|
||||
if (proofTypesSupported?.jwt) {
|
||||
return proofTypesSupported.jwt
|
||||
.proof_signing_alg_values_supported as string[];
|
||||
} else {
|
||||
return [KeyTypes.RS256] as string[];
|
||||
}
|
||||
selectedIssuerWellknownResponse: (_: any, event: any) => {
|
||||
return event.data;
|
||||
},
|
||||
}),
|
||||
updateSelectedIssuerWellknownResponse: model.assign({
|
||||
selectedIssuerWellknownResponse: (_: any, event: any) => event.data,
|
||||
setWellknwonKeyTypes: model.assign({
|
||||
wellknownKeyTypes: (_: any, event: any) => {
|
||||
return event.proofSigningAlgosSupported;
|
||||
},
|
||||
}),
|
||||
setSelectedCredentialIssuer: model.assign({
|
||||
credentialOfferCredentialIssuer: (_: any, event: any) => {
|
||||
return event.issuer;
|
||||
},
|
||||
}),
|
||||
setTokenRequestObject: model.assign({
|
||||
tokenRequestObject: (_: any, event: any) => {
|
||||
return parseJSON(event.tokenRequest);
|
||||
},
|
||||
}),
|
||||
setTokenResponseObject: model.assign({
|
||||
tokenResponse: (_: any, event: any) => {
|
||||
return event.data;
|
||||
},
|
||||
}),
|
||||
setSelectedIssuerId: model.assign({
|
||||
selectedIssuerId: (_: any, event: any) => event.id,
|
||||
@@ -330,22 +351,17 @@ export const IssuersActions = (model: any) => {
|
||||
txCodeDescription: (_: any, event: any) => event.description,
|
||||
txCodeLength: (_: any, event: any) => event.length,
|
||||
}),
|
||||
setCredentialOfferIssuerMetadata: model.assign({
|
||||
credentialOfferIssuerMetadata: (_: any, event: any) => {
|
||||
return event.issuerMetadata;
|
||||
},
|
||||
}),
|
||||
setIssuerDisplayDetails: model.assign({
|
||||
issuerLogo: (context: any, _: any) => {
|
||||
const displayArray = context.credentialOfferIssuerMetadata?.display;
|
||||
issuerLogo: (_: any, event: any) => {
|
||||
const displayArray = event.issuerDisplay;
|
||||
const display = displayArray
|
||||
? getDisplayObjectForCurrentLanguage(displayArray)
|
||||
: undefined;
|
||||
|
||||
return display?.logo?.url ?? '';
|
||||
},
|
||||
issuerName: (context: any, _: any) => {
|
||||
const displayArray = context.credentialOfferIssuerMetadata?.display;
|
||||
issuerName: (_: any, event: any) => {
|
||||
const displayArray = event.issuerDisplay;
|
||||
const display = displayArray
|
||||
? getDisplayObjectForCurrentLanguage(displayArray)
|
||||
: undefined;
|
||||
@@ -353,13 +369,13 @@ export const IssuersActions = (model: any) => {
|
||||
},
|
||||
}),
|
||||
|
||||
setFlowType: model.assign({
|
||||
setCredentialOfferFlowType: model.assign({
|
||||
isCredentialOfferFlow: (_: any, event: any) => {
|
||||
return true;
|
||||
},
|
||||
}),
|
||||
|
||||
resetFlowType: model.assign({
|
||||
resetCredentialOfferFlowType: model.assign({
|
||||
isCredentialOfferFlow: (_: any, event: any) => {
|
||||
return false;
|
||||
},
|
||||
@@ -402,7 +418,9 @@ export const IssuersActions = (model: any) => {
|
||||
type: 'VC_DOWNLOADED',
|
||||
timestamp: Date.now(),
|
||||
deviceName: '',
|
||||
issuer: context.selectedIssuerId,
|
||||
issuer:
|
||||
context.selectedIssuer.credential_issuer_host ??
|
||||
context.credentialOfferCredentialIssuer,
|
||||
credentialConfigurationId: context.selectedCredentialType.id,
|
||||
}),
|
||||
context.selectedIssuerWellknownResponse,
|
||||
@@ -441,8 +459,9 @@ export const IssuersActions = (model: any) => {
|
||||
},
|
||||
|
||||
updateVerificationErrorMessage: assign({
|
||||
verificationErrorMessage: (_, event: any) =>
|
||||
(event.data as Error).message,
|
||||
verificationErrorMessage: (_, event: any) => {
|
||||
return (event.data as Error).message;
|
||||
},
|
||||
}),
|
||||
|
||||
resetVerificationErrorMessage: model.assign({
|
||||
|
||||
@@ -33,5 +33,6 @@ export const IssuersEvents = {
|
||||
TX_CODE_REQUEST: () => ({}),
|
||||
TX_CODE_RECEIVED: (txCode: string) => ({txCode}),
|
||||
ON_CONSENT_GIVEN: () => ({}),
|
||||
TRUST_ISSUER_CONSENT_REQUEST: (issuerMetadata: object) => ({issuerMetadata})
|
||||
TRUST_ISSUER_CONSENT_REQUEST: (issuerMetadata: object) => ({issuerMetadata}),
|
||||
TOKEN_REQUEST: (tokenRequest: object) => ({tokenRequest}),
|
||||
};
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import {isSignedInResult} from '../../shared/CloudBackupAndRestoreUtils';
|
||||
import {ErrorMessage, OIDCErrors} from '../../shared/openId4VCI/Utils';
|
||||
import {isHardwareKeystoreExists} from '../../shared/cryptoutil/cryptoUtil';
|
||||
import {BiometricCancellationError} from '../../shared/error/BiometricCancellationError';
|
||||
import {VerificationErrorType} from '../../shared/vcjs/verifyCredential';
|
||||
|
||||
@@ -17,32 +16,6 @@ export const IssuersGuards = () => {
|
||||
return context.keyType == '';
|
||||
},
|
||||
isInternetConnected: (_: any, event: any) => !!event.data.isConnected,
|
||||
isOIDCflowCancelled: (_: any, event: any) => {
|
||||
// iOS & Android have different error strings for user cancelled flow
|
||||
const err = [
|
||||
OIDCErrors.OIDC_FLOW_CANCELLED_ANDROID,
|
||||
OIDCErrors.OIDC_FLOW_CANCELLED_IOS,
|
||||
];
|
||||
return (
|
||||
!!event.data &&
|
||||
typeof event.data.toString === 'function' &&
|
||||
err.some(e => event.data.toString().includes(e))
|
||||
);
|
||||
},
|
||||
isOIDCConfigError: (_: any, event: any) => {
|
||||
return (
|
||||
!!event.data &&
|
||||
typeof event.data.toString === 'function' &&
|
||||
event.data.toString().includes(OIDCErrors.OIDC_CONFIG_ERROR_PREFIX)
|
||||
);
|
||||
},
|
||||
isGrantTypeNotSupportedError: (_: any, event: any) => {
|
||||
return (
|
||||
!!event.data &&
|
||||
event.data.toString() ===
|
||||
OIDCErrors.AUTHORIZATION_ENDPOINT_DISCOVERY.GRANT_TYPE_NOT_SUPPORTED
|
||||
);
|
||||
},
|
||||
canSelectIssuerAgain: (context: any) => {
|
||||
return (
|
||||
context.errorMessage.includes(OIDCErrors.OIDC_CONFIG_ERROR_PREFIX) ||
|
||||
@@ -50,18 +23,13 @@ export const IssuersGuards = () => {
|
||||
);
|
||||
},
|
||||
shouldFetchIssuersAgain: (context: any) => context.issuers.length === 0,
|
||||
isCustomSecureKeystore: () => isHardwareKeystoreExists,
|
||||
hasUserCancelledBiometric: (_: any, event: any) =>
|
||||
event.data instanceof BiometricCancellationError,
|
||||
isGenericError: (_: any, event: any) => {
|
||||
const errorMessage = event.data.message;
|
||||
return errorMessage === ErrorMessage.GENERIC;
|
||||
},
|
||||
isCredentialOfferFlow: (context: any) => {
|
||||
return context.isCredentialOfferFlow;
|
||||
},
|
||||
isIssuerIdInTrustedIssuers: (_: any,event:any) => {
|
||||
isIssuerIdInTrustedIssuers: (_: any, event: any) => {
|
||||
return event.data;
|
||||
}
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -1,556 +0,0 @@
|
||||
// This file was automatically generated. Edits will be overwritten
|
||||
|
||||
export interface Typegen0 {
|
||||
'@@xstate/typegen': true;
|
||||
internalEvents: {
|
||||
'done.invoke.issuersMachine.credentialDownloadFromOffer.checkingIssuerTrust:invocation[0]': {
|
||||
type: 'done.invoke.issuersMachine.credentialDownloadFromOffer.checkingIssuerTrust:invocation[0]';
|
||||
data: unknown;
|
||||
__tip: 'See the XState TS docs to learn how to strongly type this.';
|
||||
};
|
||||
'done.invoke.issuersMachine.credentialDownloadFromOffer.keyManagement.generateKeyPair:invocation[0]': {
|
||||
type: 'done.invoke.issuersMachine.credentialDownloadFromOffer.keyManagement.generateKeyPair:invocation[0]';
|
||||
data: unknown;
|
||||
__tip: 'See the XState TS docs to learn how to strongly type this.';
|
||||
};
|
||||
'done.invoke.issuersMachine.credentialDownloadFromOffer.keyManagement.getKeyPairFromKeystore:invocation[0]': {
|
||||
type: 'done.invoke.issuersMachine.credentialDownloadFromOffer.keyManagement.getKeyPairFromKeystore:invocation[0]';
|
||||
data: unknown;
|
||||
__tip: 'See the XState TS docs to learn how to strongly type this.';
|
||||
};
|
||||
'done.invoke.issuersMachine.credentialDownloadFromOffer.keyManagement.setSelectedKey:invocation[0]': {
|
||||
type: 'done.invoke.issuersMachine.credentialDownloadFromOffer.keyManagement.setSelectedKey:invocation[0]';
|
||||
data: unknown;
|
||||
__tip: 'See the XState TS docs to learn how to strongly type this.';
|
||||
};
|
||||
'done.invoke.issuersMachine.credentialDownloadFromOffer.sendConsentGiven.updatingTrustedIssuerList:invocation[0]': {
|
||||
type: 'done.invoke.issuersMachine.credentialDownloadFromOffer.sendConsentGiven.updatingTrustedIssuerList:invocation[0]';
|
||||
data: unknown;
|
||||
__tip: 'See the XState TS docs to learn how to strongly type this.';
|
||||
};
|
||||
'done.invoke.issuersMachine.credentialDownloadFromOffer.sendConsentGiven:invocation[0]': {
|
||||
type: 'done.invoke.issuersMachine.credentialDownloadFromOffer.sendConsentGiven:invocation[0]';
|
||||
data: unknown;
|
||||
__tip: 'See the XState TS docs to learn how to strongly type this.';
|
||||
};
|
||||
'done.invoke.issuersMachine.credentialDownloadFromOffer:invocation[0]': {
|
||||
type: 'done.invoke.issuersMachine.credentialDownloadFromOffer:invocation[0]';
|
||||
data: unknown;
|
||||
__tip: 'See the XState TS docs to learn how to strongly type this.';
|
||||
};
|
||||
'done.invoke.issuersMachine.displayIssuers:invocation[0]': {
|
||||
type: 'done.invoke.issuersMachine.displayIssuers:invocation[0]';
|
||||
data: unknown;
|
||||
__tip: 'See the XState TS docs to learn how to strongly type this.';
|
||||
};
|
||||
'done.invoke.issuersMachine.downloadCredentials.keyManagement.generateKeyPair:invocation[0]': {
|
||||
type: 'done.invoke.issuersMachine.downloadCredentials.keyManagement.generateKeyPair:invocation[0]';
|
||||
data: unknown;
|
||||
__tip: 'See the XState TS docs to learn how to strongly type this.';
|
||||
};
|
||||
'done.invoke.issuersMachine.downloadCredentials.keyManagement.getKeyPairFromKeystore:invocation[0]': {
|
||||
type: 'done.invoke.issuersMachine.downloadCredentials.keyManagement.getKeyPairFromKeystore:invocation[0]';
|
||||
data: unknown;
|
||||
__tip: 'See the XState TS docs to learn how to strongly type this.';
|
||||
};
|
||||
'done.invoke.issuersMachine.downloadCredentials.keyManagement.setSelectedKey:invocation[0]': {
|
||||
type: 'done.invoke.issuersMachine.downloadCredentials.keyManagement.setSelectedKey:invocation[0]';
|
||||
data: unknown;
|
||||
__tip: 'See the XState TS docs to learn how to strongly type this.';
|
||||
};
|
||||
'done.invoke.issuersMachine.downloadCredentials:invocation[0]': {
|
||||
type: 'done.invoke.issuersMachine.downloadCredentials:invocation[0]';
|
||||
data: unknown;
|
||||
__tip: 'See the XState TS docs to learn how to strongly type this.';
|
||||
};
|
||||
'done.invoke.issuersMachine.downloadIssuerWellknown:invocation[0]': {
|
||||
type: 'done.invoke.issuersMachine.downloadIssuerWellknown:invocation[0]';
|
||||
data: unknown;
|
||||
__tip: 'See the XState TS docs to learn how to strongly type this.';
|
||||
};
|
||||
'done.invoke.issuersMachine.getCredentialTypes:invocation[0]': {
|
||||
type: 'done.invoke.issuersMachine.getCredentialTypes:invocation[0]';
|
||||
data: unknown;
|
||||
__tip: 'See the XState TS docs to learn how to strongly type this.';
|
||||
};
|
||||
'done.invoke.issuersMachine.proccessingCredential:invocation[0]': {
|
||||
type: 'done.invoke.issuersMachine.proccessingCredential:invocation[0]';
|
||||
data: unknown;
|
||||
__tip: 'See the XState TS docs to learn how to strongly type this.';
|
||||
};
|
||||
'done.invoke.issuersMachine.storing:invocation[0]': {
|
||||
type: 'done.invoke.issuersMachine.storing:invocation[0]';
|
||||
data: unknown;
|
||||
__tip: 'See the XState TS docs to learn how to strongly type this.';
|
||||
};
|
||||
'done.invoke.issuersMachine.verifyingCredential:invocation[0]': {
|
||||
type: 'done.invoke.issuersMachine.verifyingCredential:invocation[0]';
|
||||
data: unknown;
|
||||
__tip: 'See the XState TS docs to learn how to strongly type this.';
|
||||
};
|
||||
'error.platform.issuersMachine.credentialDownloadFromOffer.keyManagement.constructProof:invocation[0]': {
|
||||
type: 'error.platform.issuersMachine.credentialDownloadFromOffer.keyManagement.constructProof:invocation[0]';
|
||||
data: unknown;
|
||||
};
|
||||
'error.platform.issuersMachine.credentialDownloadFromOffer.keyManagement.getKeyPairFromKeystore:invocation[0]': {
|
||||
type: 'error.platform.issuersMachine.credentialDownloadFromOffer.keyManagement.getKeyPairFromKeystore:invocation[0]';
|
||||
data: unknown;
|
||||
};
|
||||
'error.platform.issuersMachine.credentialDownloadFromOffer.keyManagement.setSelectedKey:invocation[0]': {
|
||||
type: 'error.platform.issuersMachine.credentialDownloadFromOffer.keyManagement.setSelectedKey:invocation[0]';
|
||||
data: unknown;
|
||||
};
|
||||
'error.platform.issuersMachine.credentialDownloadFromOffer.sendConsentGiven:invocation[0]': {
|
||||
type: 'error.platform.issuersMachine.credentialDownloadFromOffer.sendConsentGiven:invocation[0]';
|
||||
data: unknown;
|
||||
};
|
||||
'error.platform.issuersMachine.credentialDownloadFromOffer.sendTxCode:invocation[0]': {
|
||||
type: 'error.platform.issuersMachine.credentialDownloadFromOffer.sendTxCode:invocation[0]';
|
||||
data: unknown;
|
||||
};
|
||||
'error.platform.issuersMachine.credentialDownloadFromOffer:invocation[0]': {
|
||||
type: 'error.platform.issuersMachine.credentialDownloadFromOffer:invocation[0]';
|
||||
data: unknown;
|
||||
};
|
||||
'error.platform.issuersMachine.displayIssuers:invocation[0]': {
|
||||
type: 'error.platform.issuersMachine.displayIssuers:invocation[0]';
|
||||
data: unknown;
|
||||
};
|
||||
'error.platform.issuersMachine.downloadCredentials.constructProof:invocation[0]': {
|
||||
type: 'error.platform.issuersMachine.downloadCredentials.constructProof:invocation[0]';
|
||||
data: unknown;
|
||||
};
|
||||
'error.platform.issuersMachine.downloadCredentials.keyManagement.getKeyPairFromKeystore:invocation[0]': {
|
||||
type: 'error.platform.issuersMachine.downloadCredentials.keyManagement.getKeyPairFromKeystore:invocation[0]';
|
||||
data: unknown;
|
||||
};
|
||||
'error.platform.issuersMachine.downloadCredentials.keyManagement.setSelectedKey:invocation[0]': {
|
||||
type: 'error.platform.issuersMachine.downloadCredentials.keyManagement.setSelectedKey:invocation[0]';
|
||||
data: unknown;
|
||||
};
|
||||
'error.platform.issuersMachine.downloadCredentials:invocation[0]': {
|
||||
type: 'error.platform.issuersMachine.downloadCredentials:invocation[0]';
|
||||
data: unknown;
|
||||
};
|
||||
'error.platform.issuersMachine.downloadIssuerWellknown:invocation[0]': {
|
||||
type: 'error.platform.issuersMachine.downloadIssuerWellknown:invocation[0]';
|
||||
data: unknown;
|
||||
};
|
||||
'error.platform.issuersMachine.getCredentialTypes:invocation[0]': {
|
||||
type: 'error.platform.issuersMachine.getCredentialTypes:invocation[0]';
|
||||
data: unknown;
|
||||
};
|
||||
'error.platform.issuersMachine.verifyingCredential:invocation[0]': {
|
||||
type: 'error.platform.issuersMachine.verifyingCredential:invocation[0]';
|
||||
data: unknown;
|
||||
};
|
||||
'xstate.init': {type: 'xstate.init'};
|
||||
};
|
||||
invokeSrcNameMap: {
|
||||
addIssuerToTrustedIssuers: 'done.invoke.issuersMachine.credentialDownloadFromOffer.sendConsentGiven.addingIssuerToTrustedIssuers:invocation[0]';
|
||||
checkIssuerIdInStoredTrustedIssuers:
|
||||
| 'done.invoke.issuersMachine.credentialDownloadFromOffer.checkingIssuerTrust:invocation[0]'
|
||||
| 'done.invoke.issuersMachine.credentialDownloadFromOffer.sendConsentGiven.updatingTrustedIssuerList:invocation[0]';
|
||||
constructProof: 'done.invoke.issuersMachine.credentialDownloadFromOffer.keyManagement.constructProof:invocation[0]';
|
||||
constructProofForTrustedIssuers: 'done.invoke.issuersMachine.downloadCredentials.constructProof:invocation[0]';
|
||||
downloadCredential: 'done.invoke.issuersMachine.downloadCredentials:invocation[0]';
|
||||
downloadCredentialFromOffer: 'done.invoke.issuersMachine.credentialDownloadFromOffer:invocation[0]';
|
||||
downloadIssuerWellknown: 'done.invoke.issuersMachine.downloadIssuerWellknown:invocation[0]';
|
||||
downloadIssuersList: 'done.invoke.issuersMachine.displayIssuers:invocation[0]';
|
||||
generateKeyPair:
|
||||
| 'done.invoke.issuersMachine.credentialDownloadFromOffer.keyManagement.generateKeyPair:invocation[0]'
|
||||
| 'done.invoke.issuersMachine.downloadCredentials.keyManagement.generateKeyPair:invocation[0]';
|
||||
getCredentialTypes: 'done.invoke.issuersMachine.getCredentialTypes:invocation[0]';
|
||||
getKeyOrderList:
|
||||
| 'done.invoke.issuersMachine.credentialDownloadFromOffer.keyManagement.setSelectedKey:invocation[0]'
|
||||
| 'done.invoke.issuersMachine.downloadCredentials.keyManagement.setSelectedKey:invocation[0]';
|
||||
getKeyPair:
|
||||
| 'done.invoke.issuersMachine.credentialDownloadFromOffer.keyManagement.getKeyPairFromKeystore:invocation[0]'
|
||||
| 'done.invoke.issuersMachine.downloadCredentials.keyManagement.getKeyPairFromKeystore:invocation[0]';
|
||||
isUserSignedAlready: 'done.invoke.issuersMachine.storing:invocation[0]';
|
||||
sendConsentGiven: 'done.invoke.issuersMachine.credentialDownloadFromOffer.sendConsentGiven:invocation[0]';
|
||||
sendConsentNotGiven: 'done.invoke.issuersMachine.credentialDownloadFromOffer.sendConsentNotGiven:invocation[0]';
|
||||
sendTxCode: 'done.invoke.issuersMachine.credentialDownloadFromOffer.sendTxCode:invocation[0]';
|
||||
updateCredential: 'done.invoke.issuersMachine.proccessingCredential:invocation[0]';
|
||||
verifyCredential: 'done.invoke.issuersMachine.verifyingCredential:invocation[0]';
|
||||
};
|
||||
missingImplementations: {
|
||||
actions:
|
||||
| 'downloadIssuerWellknown'
|
||||
| 'loadKeyPair'
|
||||
| 'logDownloaded'
|
||||
| 'resetCredentialOfferIssuer'
|
||||
| 'resetError'
|
||||
| 'resetLoadingReason'
|
||||
| 'resetQrData'
|
||||
| 'resetRequestConsentToTrustIssuer'
|
||||
| 'resetRequestTxCode'
|
||||
| 'resetSelectedCredentialType'
|
||||
| 'resetVerificationErrorMessage'
|
||||
| 'resetVerificationResult'
|
||||
| 'sendBackupEvent'
|
||||
| 'sendDownloadingFailedToVcMeta'
|
||||
| 'sendErrorEndEvent'
|
||||
| 'sendImpressionEvent'
|
||||
| 'sendSuccessEndEvent'
|
||||
| 'setAccessToken'
|
||||
| 'setCNonce'
|
||||
| 'setCredential'
|
||||
| 'setCredentialOfferIssuer'
|
||||
| 'setCredentialOfferIssuerMetadata'
|
||||
| 'setCredentialOfferIssuerWellknownResponse'
|
||||
| 'setCredentialTypeListDownloadFailureError'
|
||||
| 'setCredentialWrapper'
|
||||
| 'setError'
|
||||
| 'setIssuerDisplayDetails'
|
||||
| 'setIssuers'
|
||||
| 'setLoadingReasonAsDisplayIssuers'
|
||||
| 'setLoadingReasonAsDownloadingCredentials'
|
||||
| 'setLoadingReasonAsSettingUp'
|
||||
| 'setMetadataInCredentialData'
|
||||
| 'setNetworkOrTechnicalError'
|
||||
| 'setOfferCredentialTypeContexts'
|
||||
| 'setPrivateKey'
|
||||
| 'setPublicKey'
|
||||
| 'setQrData'
|
||||
| 'setRequestConsentToTrustIssuer'
|
||||
| 'setRequestTxCode'
|
||||
| 'setSelectedCredentialType'
|
||||
| 'setSelectedIssuerId'
|
||||
| 'setSelectedIssuers'
|
||||
| 'setSelectedKey'
|
||||
| 'setSupportedCredentialTypes'
|
||||
| 'setTxCode'
|
||||
| 'setTxCodeDisplayDetails'
|
||||
| 'setVCMetadata'
|
||||
| 'setVerifiableCredential'
|
||||
| 'setVerificationResult'
|
||||
| 'storeKeyPair'
|
||||
| 'storeVcMetaContext'
|
||||
| 'storeVcsContext'
|
||||
| 'storeVerifiableCredentialData'
|
||||
| 'storeVerifiableCredentialMeta'
|
||||
| 'updateIssuerFromWellknown'
|
||||
| 'updateSelectedIssuerWellknownResponse'
|
||||
| 'updateVerificationErrorMessage';
|
||||
delays: never;
|
||||
guards:
|
||||
| 'canSelectIssuerAgain'
|
||||
| 'hasUserCancelledBiometric'
|
||||
| 'isCredentialOfferFlow'
|
||||
| 'isGenericError'
|
||||
| 'isIssuerIdInTrustedIssuers'
|
||||
| 'isKeyTypeNotFound'
|
||||
| 'isSignedIn'
|
||||
| 'isVerificationPendingBecauseOfNetworkIssue'
|
||||
| 'shouldFetchIssuersAgain';
|
||||
services:
|
||||
| 'addIssuerToTrustedIssuers'
|
||||
| 'checkIssuerIdInStoredTrustedIssuers'
|
||||
| 'constructProof'
|
||||
| 'constructProofForTrustedIssuers'
|
||||
| 'downloadCredential'
|
||||
| 'downloadCredentialFromOffer'
|
||||
| 'downloadIssuerWellknown'
|
||||
| 'downloadIssuersList'
|
||||
| 'generateKeyPair'
|
||||
| 'getCredentialTypes'
|
||||
| 'getKeyOrderList'
|
||||
| 'getKeyPair'
|
||||
| 'isUserSignedAlready'
|
||||
| 'sendConsentGiven'
|
||||
| 'sendConsentNotGiven'
|
||||
| 'sendTxCode'
|
||||
| 'updateCredential'
|
||||
| 'verifyCredential';
|
||||
};
|
||||
eventsCausingActions: {
|
||||
downloadIssuerWellknown: 'TRY_AGAIN';
|
||||
loadKeyPair:
|
||||
| 'done.invoke.issuersMachine.credentialDownloadFromOffer.keyManagement.getKeyPairFromKeystore:invocation[0]'
|
||||
| 'done.invoke.issuersMachine.downloadCredentials.keyManagement.getKeyPairFromKeystore:invocation[0]';
|
||||
logDownloaded:
|
||||
| 'done.invoke.issuersMachine.proccessingCredential:invocation[0]'
|
||||
| 'done.invoke.issuersMachine.verifyingCredential:invocation[0]'
|
||||
| 'error.platform.issuersMachine.verifyingCredential:invocation[0]';
|
||||
resetCredentialOfferIssuer:
|
||||
| 'error.platform.issuersMachine.credentialDownloadFromOffer.sendConsentGiven:invocation[0]'
|
||||
| 'error.platform.issuersMachine.credentialDownloadFromOffer.sendTxCode:invocation[0]';
|
||||
resetError: 'RESET_ERROR' | 'TRY_AGAIN';
|
||||
resetLoadingReason:
|
||||
| 'CANCEL'
|
||||
| 'RESET_ERROR'
|
||||
| 'done.invoke.issuersMachine.displayIssuers:invocation[0]'
|
||||
| 'error.platform.issuersMachine.credentialDownloadFromOffer.keyManagement.constructProof:invocation[0]'
|
||||
| 'error.platform.issuersMachine.credentialDownloadFromOffer.keyManagement.getKeyPairFromKeystore:invocation[0]'
|
||||
| 'error.platform.issuersMachine.credentialDownloadFromOffer.keyManagement.setSelectedKey:invocation[0]'
|
||||
| 'error.platform.issuersMachine.credentialDownloadFromOffer.sendConsentGiven:invocation[0]'
|
||||
| 'error.platform.issuersMachine.credentialDownloadFromOffer.sendTxCode:invocation[0]'
|
||||
| 'error.platform.issuersMachine.credentialDownloadFromOffer:invocation[0]'
|
||||
| 'error.platform.issuersMachine.downloadCredentials.constructProof:invocation[0]'
|
||||
| 'error.platform.issuersMachine.downloadCredentials.keyManagement.getKeyPairFromKeystore:invocation[0]'
|
||||
| 'error.platform.issuersMachine.downloadCredentials.keyManagement.setSelectedKey:invocation[0]'
|
||||
| 'error.platform.issuersMachine.downloadCredentials:invocation[0]'
|
||||
| 'error.platform.issuersMachine.downloadIssuerWellknown:invocation[0]'
|
||||
| 'error.platform.issuersMachine.getCredentialTypes:invocation[0]'
|
||||
| 'error.platform.issuersMachine.verifyingCredential:invocation[0]';
|
||||
resetQrData:
|
||||
| 'CANCEL'
|
||||
| 'error.platform.issuersMachine.credentialDownloadFromOffer.sendConsentGiven:invocation[0]'
|
||||
| 'error.platform.issuersMachine.credentialDownloadFromOffer.sendTxCode:invocation[0]';
|
||||
resetRequestConsentToTrustIssuer:
|
||||
| 'CANCEL'
|
||||
| 'ON_CONSENT_GIVEN'
|
||||
| 'error.platform.issuersMachine.credentialDownloadFromOffer.sendConsentGiven:invocation[0]';
|
||||
resetRequestTxCode:
|
||||
| 'CANCEL'
|
||||
| 'TX_CODE_RECEIVED'
|
||||
| 'error.platform.issuersMachine.credentialDownloadFromOffer.sendTxCode:invocation[0]';
|
||||
resetSelectedCredentialType:
|
||||
| 'CANCEL'
|
||||
| 'error.platform.issuersMachine.credentialDownloadFromOffer.keyManagement.constructProof:invocation[0]'
|
||||
| 'error.platform.issuersMachine.credentialDownloadFromOffer.keyManagement.getKeyPairFromKeystore:invocation[0]'
|
||||
| 'error.platform.issuersMachine.credentialDownloadFromOffer.keyManagement.setSelectedKey:invocation[0]'
|
||||
| 'error.platform.issuersMachine.credentialDownloadFromOffer:invocation[0]'
|
||||
| 'error.platform.issuersMachine.downloadCredentials.constructProof:invocation[0]'
|
||||
| 'error.platform.issuersMachine.downloadCredentials.keyManagement.getKeyPairFromKeystore:invocation[0]'
|
||||
| 'error.platform.issuersMachine.downloadCredentials.keyManagement.setSelectedKey:invocation[0]'
|
||||
| 'error.platform.issuersMachine.downloadCredentials:invocation[0]';
|
||||
resetVerificationErrorMessage: 'RESET_VERIFY_ERROR';
|
||||
resetVerificationResult: 'error.platform.issuersMachine.verifyingCredential:invocation[0]';
|
||||
sendBackupEvent: 'done.invoke.issuersMachine.storing:invocation[0]';
|
||||
sendDownloadingFailedToVcMeta:
|
||||
| 'error.platform.issuersMachine.credentialDownloadFromOffer.keyManagement.constructProof:invocation[0]'
|
||||
| 'error.platform.issuersMachine.credentialDownloadFromOffer.keyManagement.getKeyPairFromKeystore:invocation[0]'
|
||||
| 'error.platform.issuersMachine.credentialDownloadFromOffer.keyManagement.setSelectedKey:invocation[0]'
|
||||
| 'error.platform.issuersMachine.credentialDownloadFromOffer:invocation[0]'
|
||||
| 'error.platform.issuersMachine.downloadCredentials.constructProof:invocation[0]'
|
||||
| 'error.platform.issuersMachine.downloadCredentials.keyManagement.getKeyPairFromKeystore:invocation[0]'
|
||||
| 'error.platform.issuersMachine.downloadCredentials.keyManagement.setSelectedKey:invocation[0]'
|
||||
| 'error.platform.issuersMachine.downloadCredentials:invocation[0]';
|
||||
sendErrorEndEvent: 'error.platform.issuersMachine.verifyingCredential:invocation[0]';
|
||||
sendImpressionEvent: 'done.invoke.issuersMachine.displayIssuers:invocation[0]';
|
||||
sendSuccessEndEvent:
|
||||
| 'done.invoke.issuersMachine.proccessingCredential:invocation[0]'
|
||||
| 'done.invoke.issuersMachine.verifyingCredential:invocation[0]';
|
||||
setAccessToken: 'PROOF_REQUEST';
|
||||
setCNonce: 'PROOF_REQUEST';
|
||||
setCredential: 'done.invoke.issuersMachine.credentialDownloadFromOffer:invocation[0]';
|
||||
setCredentialOfferIssuer: 'PROOF_REQUEST';
|
||||
setCredentialOfferIssuerMetadata: 'TRUST_ISSUER_CONSENT_REQUEST';
|
||||
setCredentialOfferIssuerWellknownResponse: 'PROOF_REQUEST';
|
||||
setCredentialTypeListDownloadFailureError: 'error.platform.issuersMachine.getCredentialTypes:invocation[0]';
|
||||
setCredentialWrapper:
|
||||
| 'done.invoke.issuersMachine.downloadCredentials:invocation[0]'
|
||||
| 'done.invoke.issuersMachine.proccessingCredential:invocation[0]';
|
||||
setError:
|
||||
| 'error.platform.issuersMachine.credentialDownloadFromOffer.keyManagement.constructProof:invocation[0]'
|
||||
| 'error.platform.issuersMachine.credentialDownloadFromOffer.keyManagement.getKeyPairFromKeystore:invocation[0]'
|
||||
| 'error.platform.issuersMachine.credentialDownloadFromOffer.keyManagement.setSelectedKey:invocation[0]'
|
||||
| 'error.platform.issuersMachine.credentialDownloadFromOffer:invocation[0]'
|
||||
| 'error.platform.issuersMachine.displayIssuers:invocation[0]'
|
||||
| 'error.platform.issuersMachine.downloadCredentials.constructProof:invocation[0]'
|
||||
| 'error.platform.issuersMachine.downloadCredentials.keyManagement.getKeyPairFromKeystore:invocation[0]'
|
||||
| 'error.platform.issuersMachine.downloadCredentials.keyManagement.setSelectedKey:invocation[0]'
|
||||
| 'error.platform.issuersMachine.downloadCredentials:invocation[0]';
|
||||
setIssuerDisplayDetails: 'done.invoke.issuersMachine.credentialDownloadFromOffer.checkingIssuerTrust:invocation[0]';
|
||||
setIssuers: 'done.invoke.issuersMachine.displayIssuers:invocation[0]';
|
||||
setLoadingReasonAsDisplayIssuers: 'TRY_AGAIN';
|
||||
setLoadingReasonAsDownloadingCredentials:
|
||||
| 'ON_CONSENT_GIVEN'
|
||||
| 'QR_CODE_SCANNED'
|
||||
| 'SELECTED_CREDENTIAL_TYPE'
|
||||
| 'TRY_AGAIN'
|
||||
| 'done.invoke.issuersMachine.credentialDownloadFromOffer.keyManagement.generateKeyPair:invocation[0]'
|
||||
| 'done.invoke.issuersMachine.downloadCredentials.keyManagement.generateKeyPair:invocation[0]';
|
||||
setLoadingReasonAsSettingUp: 'SELECTED_ISSUER' | 'TRY_AGAIN';
|
||||
setMetadataInCredentialData:
|
||||
| 'done.invoke.issuersMachine.proccessingCredential:invocation[0]'
|
||||
| 'done.invoke.issuersMachine.verifyingCredential:invocation[0]'
|
||||
| 'error.platform.issuersMachine.verifyingCredential:invocation[0]';
|
||||
setNetworkOrTechnicalError: 'error.platform.issuersMachine.downloadIssuerWellknown:invocation[0]';
|
||||
setOfferCredentialTypeContexts: 'PROOF_REQUEST';
|
||||
setPrivateKey:
|
||||
| 'done.invoke.issuersMachine.credentialDownloadFromOffer.keyManagement.generateKeyPair:invocation[0]'
|
||||
| 'done.invoke.issuersMachine.downloadCredentials.keyManagement.generateKeyPair:invocation[0]';
|
||||
setPublicKey:
|
||||
| 'done.invoke.issuersMachine.credentialDownloadFromOffer.keyManagement.generateKeyPair:invocation[0]'
|
||||
| 'done.invoke.issuersMachine.downloadCredentials.keyManagement.generateKeyPair:invocation[0]';
|
||||
setQrData: 'ON_CONSENT_GIVEN' | 'QR_CODE_SCANNED';
|
||||
setRequestConsentToTrustIssuer: 'done.invoke.issuersMachine.credentialDownloadFromOffer.checkingIssuerTrust:invocation[0]';
|
||||
setRequestTxCode: 'TX_CODE_REQUEST';
|
||||
setSelectedCredentialType: 'SELECTED_CREDENTIAL_TYPE';
|
||||
setSelectedIssuerId: 'SELECTED_ISSUER';
|
||||
setSelectedIssuers: 'SELECTED_ISSUER';
|
||||
setSelectedKey:
|
||||
| 'done.invoke.issuersMachine.credentialDownloadFromOffer.keyManagement.setSelectedKey:invocation[0]'
|
||||
| 'done.invoke.issuersMachine.downloadCredentials.keyManagement.setSelectedKey:invocation[0]';
|
||||
setSupportedCredentialTypes: 'done.invoke.issuersMachine.getCredentialTypes:invocation[0]';
|
||||
setTxCode: 'TX_CODE_RECEIVED';
|
||||
setTxCodeDisplayDetails: 'TX_CODE_REQUEST';
|
||||
setVCMetadata:
|
||||
| 'done.invoke.issuersMachine.proccessingCredential:invocation[0]'
|
||||
| 'done.invoke.issuersMachine.verifyingCredential:invocation[0]'
|
||||
| 'error.platform.issuersMachine.verifyingCredential:invocation[0]';
|
||||
setVerifiableCredential:
|
||||
| 'done.invoke.issuersMachine.downloadCredentials:invocation[0]'
|
||||
| 'done.invoke.issuersMachine.proccessingCredential:invocation[0]';
|
||||
setVerificationResult:
|
||||
| 'done.invoke.issuersMachine.proccessingCredential:invocation[0]'
|
||||
| 'done.invoke.issuersMachine.verifyingCredential:invocation[0]';
|
||||
storeKeyPair:
|
||||
| 'done.invoke.issuersMachine.credentialDownloadFromOffer.keyManagement.generateKeyPair:invocation[0]'
|
||||
| 'done.invoke.issuersMachine.downloadCredentials.keyManagement.generateKeyPair:invocation[0]';
|
||||
storeVcMetaContext:
|
||||
| 'done.invoke.issuersMachine.proccessingCredential:invocation[0]'
|
||||
| 'done.invoke.issuersMachine.verifyingCredential:invocation[0]'
|
||||
| 'error.platform.issuersMachine.verifyingCredential:invocation[0]';
|
||||
storeVcsContext:
|
||||
| 'done.invoke.issuersMachine.proccessingCredential:invocation[0]'
|
||||
| 'done.invoke.issuersMachine.verifyingCredential:invocation[0]'
|
||||
| 'error.platform.issuersMachine.verifyingCredential:invocation[0]';
|
||||
storeVerifiableCredentialData:
|
||||
| 'done.invoke.issuersMachine.proccessingCredential:invocation[0]'
|
||||
| 'done.invoke.issuersMachine.verifyingCredential:invocation[0]'
|
||||
| 'error.platform.issuersMachine.verifyingCredential:invocation[0]';
|
||||
storeVerifiableCredentialMeta:
|
||||
| 'done.invoke.issuersMachine.proccessingCredential:invocation[0]'
|
||||
| 'done.invoke.issuersMachine.verifyingCredential:invocation[0]'
|
||||
| 'error.platform.issuersMachine.verifyingCredential:invocation[0]';
|
||||
updateIssuerFromWellknown: 'done.invoke.issuersMachine.downloadIssuerWellknown:invocation[0]';
|
||||
updateSelectedIssuerWellknownResponse: 'done.invoke.issuersMachine.downloadIssuerWellknown:invocation[0]';
|
||||
updateVerificationErrorMessage: 'error.platform.issuersMachine.verifyingCredential:invocation[0]';
|
||||
};
|
||||
eventsCausingDelays: {};
|
||||
eventsCausingGuards: {
|
||||
canSelectIssuerAgain: 'TRY_AGAIN';
|
||||
hasUserCancelledBiometric:
|
||||
| 'error.platform.issuersMachine.credentialDownloadFromOffer.keyManagement.getKeyPairFromKeystore:invocation[0]'
|
||||
| 'error.platform.issuersMachine.downloadCredentials.constructProof:invocation[0]'
|
||||
| 'error.platform.issuersMachine.downloadCredentials.keyManagement.getKeyPairFromKeystore:invocation[0]'
|
||||
| 'error.platform.issuersMachine.downloadCredentials:invocation[0]';
|
||||
isCredentialOfferFlow: 'TRY_AGAIN';
|
||||
isGenericError:
|
||||
| 'error.platform.issuersMachine.credentialDownloadFromOffer:invocation[0]'
|
||||
| 'error.platform.issuersMachine.downloadCredentials:invocation[0]';
|
||||
isIssuerIdInTrustedIssuers:
|
||||
| 'done.invoke.issuersMachine.credentialDownloadFromOffer.checkingIssuerTrust:invocation[0]'
|
||||
| 'done.invoke.issuersMachine.credentialDownloadFromOffer.sendConsentGiven.updatingTrustedIssuerList:invocation[0]';
|
||||
isKeyTypeNotFound:
|
||||
| 'error.platform.issuersMachine.credentialDownloadFromOffer.keyManagement.getKeyPairFromKeystore:invocation[0]'
|
||||
| 'error.platform.issuersMachine.downloadCredentials.keyManagement.getKeyPairFromKeystore:invocation[0]';
|
||||
isSignedIn: 'done.invoke.issuersMachine.storing:invocation[0]';
|
||||
isVerificationPendingBecauseOfNetworkIssue: 'error.platform.issuersMachine.verifyingCredential:invocation[0]';
|
||||
shouldFetchIssuersAgain: 'TRY_AGAIN';
|
||||
};
|
||||
eventsCausingServices: {
|
||||
addIssuerToTrustedIssuers: 'done.invoke.issuersMachine.credentialDownloadFromOffer.sendConsentGiven.updatingTrustedIssuerList:invocation[0]';
|
||||
checkIssuerIdInStoredTrustedIssuers:
|
||||
| 'TRUST_ISSUER_CONSENT_REQUEST'
|
||||
| 'done.invoke.issuersMachine.credentialDownloadFromOffer.sendConsentGiven:invocation[0]';
|
||||
constructProof:
|
||||
| 'done.invoke.issuersMachine.credentialDownloadFromOffer.keyManagement.generateKeyPair:invocation[0]'
|
||||
| 'done.invoke.issuersMachine.credentialDownloadFromOffer.keyManagement.getKeyPairFromKeystore:invocation[0]';
|
||||
constructProofForTrustedIssuers:
|
||||
| 'TRY_AGAIN'
|
||||
| 'done.invoke.issuersMachine.downloadCredentials.keyManagement.getKeyPairFromKeystore:invocation[0]';
|
||||
downloadCredential: 'SELECTED_CREDENTIAL_TYPE';
|
||||
downloadCredentialFromOffer: 'QR_CODE_SCANNED';
|
||||
downloadIssuerWellknown: 'SELECTED_ISSUER' | 'TRY_AGAIN';
|
||||
downloadIssuersList: 'CANCEL' | 'TRY_AGAIN' | 'xstate.init';
|
||||
generateKeyPair:
|
||||
| 'error.platform.issuersMachine.credentialDownloadFromOffer.keyManagement.getKeyPairFromKeystore:invocation[0]'
|
||||
| 'error.platform.issuersMachine.downloadCredentials.keyManagement.getKeyPairFromKeystore:invocation[0]';
|
||||
getCredentialTypes: 'done.invoke.issuersMachine.downloadIssuerWellknown:invocation[0]';
|
||||
getKeyOrderList: 'PROOF_REQUEST';
|
||||
getKeyPair:
|
||||
| 'TRY_AGAIN'
|
||||
| 'done.invoke.issuersMachine.credentialDownloadFromOffer.keyManagement.setSelectedKey:invocation[0]'
|
||||
| 'done.invoke.issuersMachine.downloadCredentials.keyManagement.setSelectedKey:invocation[0]';
|
||||
isUserSignedAlready:
|
||||
| 'done.invoke.issuersMachine.proccessingCredential:invocation[0]'
|
||||
| 'done.invoke.issuersMachine.verifyingCredential:invocation[0]'
|
||||
| 'error.platform.issuersMachine.verifyingCredential:invocation[0]';
|
||||
sendConsentGiven:
|
||||
| 'ON_CONSENT_GIVEN'
|
||||
| 'done.invoke.issuersMachine.credentialDownloadFromOffer.checkingIssuerTrust:invocation[0]';
|
||||
sendConsentNotGiven: 'CANCEL';
|
||||
sendTxCode: 'TX_CODE_RECEIVED';
|
||||
updateCredential: 'done.invoke.issuersMachine.credentialDownloadFromOffer:invocation[0]';
|
||||
verifyCredential: 'done.invoke.issuersMachine.downloadCredentials:invocation[0]';
|
||||
};
|
||||
matchesStates:
|
||||
| 'credentialDownloadFromOffer'
|
||||
| 'credentialDownloadFromOffer.checkingIssuerTrust'
|
||||
| 'credentialDownloadFromOffer.credentialOfferDownloadConsent'
|
||||
| 'credentialDownloadFromOffer.idle'
|
||||
| 'credentialDownloadFromOffer.keyManagement'
|
||||
| 'credentialDownloadFromOffer.keyManagement.constructProof'
|
||||
| 'credentialDownloadFromOffer.keyManagement.generateKeyPair'
|
||||
| 'credentialDownloadFromOffer.keyManagement.getKeyPairFromKeystore'
|
||||
| 'credentialDownloadFromOffer.keyManagement.setSelectedKey'
|
||||
| 'credentialDownloadFromOffer.keyManagement.userCancelledBiometric'
|
||||
| 'credentialDownloadFromOffer.sendConsentGiven'
|
||||
| 'credentialDownloadFromOffer.sendConsentGiven.addingIssuerToTrustedIssuers'
|
||||
| 'credentialDownloadFromOffer.sendConsentGiven.updatingTrustedIssuerList'
|
||||
| 'credentialDownloadFromOffer.sendConsentNotGiven'
|
||||
| 'credentialDownloadFromOffer.sendTxCode'
|
||||
| 'credentialDownloadFromOffer.waitingForTxCode'
|
||||
| 'displayIssuers'
|
||||
| 'done'
|
||||
| 'downloadCredentials'
|
||||
| 'downloadCredentials.constructProof'
|
||||
| 'downloadCredentials.idle'
|
||||
| 'downloadCredentials.keyManagement'
|
||||
| 'downloadCredentials.keyManagement.generateKeyPair'
|
||||
| 'downloadCredentials.keyManagement.getKeyPairFromKeystore'
|
||||
| 'downloadCredentials.keyManagement.setSelectedKey'
|
||||
| 'downloadCredentials.keyManagement.userCancelledBiometric'
|
||||
| 'downloadCredentials.userCancelledBiometric'
|
||||
| 'downloadIssuerWellknown'
|
||||
| 'error'
|
||||
| 'getCredentialTypes'
|
||||
| 'handleVCVerificationFailure'
|
||||
| 'idle'
|
||||
| 'proccessingCredential'
|
||||
| 'selectingCredentialType'
|
||||
| 'selectingIssuer'
|
||||
| 'storing'
|
||||
| 'verifyingCredential'
|
||||
| 'waitingForQrScan'
|
||||
| {
|
||||
credentialDownloadFromOffer?:
|
||||
| 'checkingIssuerTrust'
|
||||
| 'credentialOfferDownloadConsent'
|
||||
| 'idle'
|
||||
| 'keyManagement'
|
||||
| 'sendConsentGiven'
|
||||
| 'sendConsentNotGiven'
|
||||
| 'sendTxCode'
|
||||
| 'waitingForTxCode'
|
||||
| {
|
||||
keyManagement?:
|
||||
| 'constructProof'
|
||||
| 'generateKeyPair'
|
||||
| 'getKeyPairFromKeystore'
|
||||
| 'setSelectedKey'
|
||||
| 'userCancelledBiometric';
|
||||
sendConsentGiven?:
|
||||
| 'addingIssuerToTrustedIssuers'
|
||||
| 'updatingTrustedIssuerList';
|
||||
};
|
||||
downloadCredentials?:
|
||||
| 'constructProof'
|
||||
| 'idle'
|
||||
| 'keyManagement'
|
||||
| 'userCancelledBiometric'
|
||||
| {
|
||||
keyManagement?:
|
||||
| 'generateKeyPair'
|
||||
| 'getKeyPairFromKeystore'
|
||||
| 'setSelectedKey'
|
||||
| 'userCancelledBiometric';
|
||||
};
|
||||
};
|
||||
tags: never;
|
||||
}
|
||||
|
||||
@@ -1,15 +1,14 @@
|
||||
import {createModel} from 'xstate/lib/model';
|
||||
import {AuthorizeResult} from 'react-native-app-auth';
|
||||
import { createModel } from 'xstate/lib/model';
|
||||
import {
|
||||
CredentialTypes,
|
||||
CredentialWrapper,
|
||||
IssuerWellknownResponse,
|
||||
VerifiableCredential,
|
||||
} from '../VerifiableCredential/VCMetaMachine/vc';
|
||||
import {AppServices} from '../../shared/GlobalContext';
|
||||
import {VCMetadata} from '../../shared/VCMetadata';
|
||||
import {IssuersEvents} from './IssuersEvents';
|
||||
import {issuerType} from './IssuersMachine';
|
||||
import { AppServices } from '../../shared/GlobalContext';
|
||||
import { VCMetadata } from '../../shared/VCMetadata';
|
||||
import { IssuersEvents } from './IssuersEvents';
|
||||
import { issuerType } from './IssuersMachine';
|
||||
|
||||
export const IssuersModel = createModel(
|
||||
{
|
||||
@@ -18,7 +17,7 @@ export const IssuersModel = createModel(
|
||||
qrData: '' as string,
|
||||
selectedIssuer: {} as issuerType,
|
||||
selectedIssuerWellknownResponse: {} as IssuerWellknownResponse,
|
||||
tokenResponse: {} as AuthorizeResult,
|
||||
tokenResponse: {} as object,
|
||||
errorMessage: '' as string,
|
||||
loadingReason: 'displayIssuers' as string,
|
||||
verifiableCredential: null as VerifiableCredential | null,
|
||||
@@ -45,7 +44,9 @@ export const IssuersModel = createModel(
|
||||
txCodeDescription: '' as string,
|
||||
txCodeLength: null as number | null,
|
||||
isCredentialOfferFlow: false as boolean,
|
||||
credentialOfferIssuerMetadata: {} as object,
|
||||
credentialOfferCredentialIssuer: {} as string,
|
||||
tokenRequestObject: {} as object,
|
||||
credentialConfigurationId: '' as string,
|
||||
},
|
||||
{
|
||||
events: IssuersEvents,
|
||||
|
||||
@@ -104,7 +104,3 @@ export function selectSupportedCredentialTypes(state: State) {
|
||||
export function selectIsQrScanning(state: State) {
|
||||
return state.matches('waitingForQrScan');
|
||||
}
|
||||
|
||||
export function selectCredentialOfferData(state: State) {
|
||||
return state.context.credentialOfferData;
|
||||
}
|
||||
|
||||
@@ -1,23 +1,23 @@
|
||||
import NetInfo from '@react-native-community/netinfo';
|
||||
import {NativeModules} from 'react-native';
|
||||
import { NativeModules } from 'react-native';
|
||||
import Cloud from '../../shared/CloudBackupAndRestoreUtils';
|
||||
import {CACHED_API} from '../../shared/api';
|
||||
import getAllConfigurations, { CACHED_API } from '../../shared/api';
|
||||
import {
|
||||
fetchKeyPair,
|
||||
generateKeyPair,
|
||||
} from '../../shared/cryptoutil/cryptoUtil';
|
||||
import {
|
||||
constructIssuerMetaData,
|
||||
constructProofJWT,
|
||||
hasKeyPair,
|
||||
updateCredentialInformation,
|
||||
verifyCredentialData,
|
||||
} from '../../shared/openId4VCI/Utils';
|
||||
import VciClient from '../../shared/vciClient/VciClient';
|
||||
import {issuerType} from './IssuersMachine';
|
||||
import {setItem} from '../store';
|
||||
import {API_CACHED_STORAGE_KEYS} from '../../shared/constants';
|
||||
import {createCacheObject} from '../../shared/Utils';
|
||||
import { displayType, issuerType } from './IssuersMachine';
|
||||
import { setItem } from '../store';
|
||||
import { API_CACHED_STORAGE_KEYS } from '../../shared/constants';
|
||||
import { createCacheObject } from '../../shared/Utils';
|
||||
import { VerificationResult } from '../../shared/vcjs/verifyCredential';
|
||||
|
||||
export const IssuersService = () => {
|
||||
return {
|
||||
@@ -30,21 +30,26 @@ export const IssuersService = () => {
|
||||
},
|
||||
checkInternet: async () => await NetInfo.fetch(),
|
||||
downloadIssuerWellknown: async (context: any) => {
|
||||
const wellknownResponse = await CACHED_API.fetchIssuerWellknownConfig(
|
||||
context.selectedIssuer.issuer_id,
|
||||
context.selectedIssuer.credential_issuer_host
|
||||
? context.selectedIssuer.credential_issuer_host
|
||||
: context.selectedIssuer.credential_issuer,
|
||||
const wellknownResponse = (await VciClient.getInstance().getIssuerMetadata(
|
||||
context.selectedIssuer.credential_issuer_host,
|
||||
)) as issuerType;
|
||||
const wellknownCacheObject = createCacheObject(wellknownResponse);
|
||||
await setItem(
|
||||
API_CACHED_STORAGE_KEYS.fetchIssuerWellknownConfig(
|
||||
context.selectedIssuer.credential_issuer_host,
|
||||
),
|
||||
wellknownCacheObject,
|
||||
'',
|
||||
);
|
||||
return wellknownResponse;
|
||||
},
|
||||
getCredentialTypes: async (context: any) => {
|
||||
const credentialTypes = [];
|
||||
const credentialTypes: Array<{id: string; [key: string]: any}> = [];
|
||||
const selectedIssuer = context.selectedIssuer;
|
||||
|
||||
const keys =
|
||||
selectedIssuer.credential_configuration_ids ??
|
||||
Object.keys(selectedIssuer.credential_configurations_supported);
|
||||
const keys = Object.keys(
|
||||
selectedIssuer.credential_configurations_supported,
|
||||
);
|
||||
|
||||
for (const key of keys) {
|
||||
if (selectedIssuer.credential_configurations_supported[key]) {
|
||||
@@ -70,26 +75,35 @@ export const IssuersService = () => {
|
||||
authEndpoint: authorizationEndpoint,
|
||||
});
|
||||
};
|
||||
const getProofJwt = async (accessToken: string, cNonce: string) => {
|
||||
const getProofJwt = async (
|
||||
credentialIssuer: string,
|
||||
cNonce: string | null,
|
||||
proofSigningAlgosSupported: string[] | null,
|
||||
) => {
|
||||
sendBack({
|
||||
type: 'PROOF_REQUEST',
|
||||
accessToken: accessToken,
|
||||
credentialIssuer: credentialIssuer,
|
||||
cNonce: cNonce,
|
||||
proofSigningAlgosSupported: proofSigningAlgosSupported,
|
||||
});
|
||||
};
|
||||
const credential =
|
||||
const getTokenResponse = (tokenRequest: object) => {
|
||||
sendBack({
|
||||
type: 'TOKEN_REQUEST',
|
||||
tokenRequest: tokenRequest,
|
||||
});
|
||||
};
|
||||
const {credential} =
|
||||
await VciClient.getInstance().requestCredentialFromTrustedIssuer(
|
||||
constructIssuerMetaData(
|
||||
context.selectedIssuer,
|
||||
context.selectedCredentialType,
|
||||
context.selectedCredentialType.scope,
|
||||
),
|
||||
context.selectedIssuer.credential_issuer_host,
|
||||
context.selectedCredentialType.id,
|
||||
{
|
||||
clientId: context.selectedIssuer.client_id,
|
||||
redirectUri: context.selectedIssuer.redirect_uri,
|
||||
},
|
||||
getProofJwt,
|
||||
navigateToAuthView,
|
||||
getTokenResponse,
|
||||
);
|
||||
return updateCredentialInformation(context, credential);
|
||||
},
|
||||
@@ -109,7 +123,7 @@ export const IssuersService = () => {
|
||||
const {RNSecureKeystoreModule} = NativeModules;
|
||||
try {
|
||||
return await RNSecureKeystoreModule.hasAlias(
|
||||
context.credentialOfferIssuerMetadata.credential_issuer,
|
||||
context.credentialOfferCredentialIssuer,
|
||||
);
|
||||
} catch (error) {
|
||||
console.error(
|
||||
@@ -123,8 +137,8 @@ export const IssuersService = () => {
|
||||
const {RNSecureKeystoreModule} = NativeModules;
|
||||
try {
|
||||
await RNSecureKeystoreModule.storeData(
|
||||
context.credentialOfferIssuerMetadata.credential_issuer,
|
||||
JSON.stringify(context.credentialOfferIssuerMetadata),
|
||||
context.credentialOfferCredentialIssuer,
|
||||
'trusted',
|
||||
);
|
||||
} catch {
|
||||
console.error('Error updating issuer trust in keystore');
|
||||
@@ -138,39 +152,16 @@ export const IssuersService = () => {
|
||||
});
|
||||
};
|
||||
const getSignedProofJwt = async (
|
||||
accessToken: string,
|
||||
credentialIssuer: string,
|
||||
cNonce: string | null,
|
||||
issuerMetadata: object,
|
||||
credentialConfigurationId: string,
|
||||
proofSigningAlgosSupported: string[] | null,
|
||||
) => {
|
||||
let issuer = issuerMetadata as issuerType;
|
||||
issuer.issuer_id = issuer.credential_issuer;
|
||||
const wellknownCacheObject = createCacheObject(issuer);
|
||||
await setItem(
|
||||
API_CACHED_STORAGE_KEYS.fetchIssuerWellknownConfig(issuer.issuer_id),
|
||||
wellknownCacheObject,
|
||||
'',
|
||||
);
|
||||
|
||||
let credentialTypes: Array<{id: string; [key: string]: any}> = [];
|
||||
if (
|
||||
issuer.credential_configurations_supported[credentialConfigurationId]
|
||||
) {
|
||||
credentialTypes.push({
|
||||
id: credentialConfigurationId,
|
||||
...issuer.credential_configurations_supported[
|
||||
credentialConfigurationId
|
||||
],
|
||||
});
|
||||
sendBack({
|
||||
type: 'PROOF_REQUEST',
|
||||
accessToken: accessToken,
|
||||
cNonce: cNonce,
|
||||
issuerMetadata: issuerMetadata,
|
||||
issuer: issuer,
|
||||
credentialTypes: credentialTypes,
|
||||
});
|
||||
}
|
||||
sendBack({
|
||||
type: 'PROOF_REQUEST',
|
||||
cNonce: cNonce,
|
||||
issuer: credentialIssuer,
|
||||
proofSigningAlgosSupported: proofSigningAlgosSupported,
|
||||
});
|
||||
};
|
||||
|
||||
const getTxCode = async (
|
||||
@@ -186,24 +177,55 @@ export const IssuersService = () => {
|
||||
});
|
||||
};
|
||||
|
||||
const requesTrustIssuerConsent = async (issuerMetadata: object) => {
|
||||
const issuerMetadataObject = issuerMetadata as issuerType;
|
||||
const requesTrustIssuerConsent = async (
|
||||
credentialIssuer: string,
|
||||
issuerDisplay: object[],
|
||||
) => {
|
||||
const issuerDisplayObject = issuerDisplay as displayType[];
|
||||
|
||||
sendBack({
|
||||
type: 'TRUST_ISSUER_CONSENT_REQUEST',
|
||||
issuerMetadata: issuerMetadataObject,
|
||||
issuerDisplay: issuerDisplayObject,
|
||||
issuer: credentialIssuer,
|
||||
});
|
||||
};
|
||||
const getTokenResponse = (tokenRequest: object) => {
|
||||
sendBack({
|
||||
type: 'TOKEN_REQUEST',
|
||||
tokenRequest: tokenRequest,
|
||||
});
|
||||
};
|
||||
|
||||
const credential = await VciClient.getInstance().requestCredentialByOffer(
|
||||
context.qrData,
|
||||
getTxCode,
|
||||
getSignedProofJwt,
|
||||
navigateToAuthView,
|
||||
requesTrustIssuerConsent,
|
||||
);
|
||||
return credential;
|
||||
const credentialResponse =
|
||||
await VciClient.getInstance().requestCredentialByOffer(
|
||||
context.qrData,
|
||||
getTxCode,
|
||||
getSignedProofJwt,
|
||||
navigateToAuthView,
|
||||
getTokenResponse,
|
||||
requesTrustIssuerConsent,
|
||||
);
|
||||
return credentialResponse;
|
||||
},
|
||||
sendTokenRequest: async (context: any) => {
|
||||
const tokenRequestObject = context.tokenRequestObject;
|
||||
return await sendTokenRequest(
|
||||
tokenRequestObject,
|
||||
context.selectedIssuer?.token_endpoint,
|
||||
);
|
||||
},
|
||||
sendTokenResponse: async (context: any) => {
|
||||
const tokenResponse = context.tokenResponse;
|
||||
if (!tokenResponse) {
|
||||
throw new Error(
|
||||
'Could not send token response, tokenResponse is undefined or null',
|
||||
);
|
||||
}
|
||||
return await VciClient.getInstance().sendTokenResponse(
|
||||
JSON.stringify(tokenResponse),
|
||||
);
|
||||
},
|
||||
|
||||
updateCredential: async (context: any) => {
|
||||
const credential = await updateCredentialInformation(
|
||||
context,
|
||||
@@ -211,13 +233,25 @@ export const IssuersService = () => {
|
||||
);
|
||||
return credential;
|
||||
},
|
||||
cacheIssuerWellknown: async (context: any) => {
|
||||
const credentialIssuer = context.credentialOfferCredentialIssuer;
|
||||
const issuerMetadata = (await VciClient.getInstance().getIssuerMetadata(
|
||||
credentialIssuer,
|
||||
)) as issuerType;
|
||||
const wellknownCacheObject = createCacheObject(issuerMetadata);
|
||||
await setItem(
|
||||
API_CACHED_STORAGE_KEYS.fetchIssuerWellknownConfig(credentialIssuer),
|
||||
wellknownCacheObject,
|
||||
'',
|
||||
);
|
||||
return issuerMetadata;
|
||||
},
|
||||
constructProof: async (context: any) => {
|
||||
const issuerMeta = context.selectedIssuer;
|
||||
const proofJWT = await constructProofJWT(
|
||||
context.publicKey,
|
||||
context.privateKey,
|
||||
context.accessToken,
|
||||
issuerMeta,
|
||||
context.credentialOfferCredentialIssuer,
|
||||
null,
|
||||
context.keyType,
|
||||
context.wellknownKeyTypes,
|
||||
true,
|
||||
@@ -226,13 +260,13 @@ export const IssuersService = () => {
|
||||
await VciClient.getInstance().sendProof(proofJWT);
|
||||
return proofJWT;
|
||||
},
|
||||
constructProofForTrustedIssuers: async (context: any) => {
|
||||
constructAndSendProofForTrustedIssuers: async (context: any) => {
|
||||
const issuerMeta = context.selectedIssuer;
|
||||
const proofJWT = await constructProofJWT(
|
||||
context.publicKey,
|
||||
context.privateKey,
|
||||
context.accessToken,
|
||||
issuerMeta,
|
||||
context.selectedIssuer.credential_issuer_host,
|
||||
context.selectedIssuer.client_id,
|
||||
context.keyType,
|
||||
context.wellknownKeyTypes,
|
||||
false,
|
||||
@@ -267,16 +301,82 @@ export const IssuersService = () => {
|
||||
return context.keyType;
|
||||
},
|
||||
|
||||
verifyCredential: async (context: any) => {
|
||||
verifyCredential: async (context: any): Promise<VerificationResult> => {
|
||||
const { isCredentialOfferFlow, verifiableCredential, selectedCredentialType } = context;
|
||||
if (isCredentialOfferFlow) {
|
||||
const configurations = await getAllConfigurations();
|
||||
if (configurations.disableCredentialOfferVcVerification) {
|
||||
return {
|
||||
isVerified: true,
|
||||
verificationMessage: '',
|
||||
verificationErrorCode: '',
|
||||
};
|
||||
}
|
||||
}
|
||||
const verificationResult = await verifyCredentialData(
|
||||
context.verifiableCredential?.credential,
|
||||
context.selectedCredentialType.format
|
||||
verifiableCredential?.credential,
|
||||
selectedCredentialType.format,
|
||||
);
|
||||
if (!verificationResult.isVerified) {
|
||||
throw new Error(verificationResult.verificationErrorCode);
|
||||
}
|
||||
|
||||
|
||||
return verificationResult;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
async function sendTokenRequest(
|
||||
tokenRequestObject: any,
|
||||
proxyTokenEndpoint: any = null,
|
||||
) {
|
||||
if (proxyTokenEndpoint) {
|
||||
tokenRequestObject.tokenEndpoint = proxyTokenEndpoint;
|
||||
}
|
||||
if (!tokenRequestObject?.tokenEndpoint) {
|
||||
console.error('tokenEndpoint is not provided in tokenRequestObject');
|
||||
throw new Error('tokenEndpoint is required');
|
||||
}
|
||||
|
||||
const formBody = new URLSearchParams();
|
||||
|
||||
formBody.append('grant_type', tokenRequestObject.grantType);
|
||||
|
||||
if (tokenRequestObject.authCode) {
|
||||
formBody.append('code', tokenRequestObject.authCode);
|
||||
}
|
||||
if (tokenRequestObject.preAuthCode) {
|
||||
formBody.append('pre-authorized_code', tokenRequestObject.preAuthCode);
|
||||
}
|
||||
if (tokenRequestObject.txCode) {
|
||||
formBody.append('tx_code', tokenRequestObject.txCode);
|
||||
}
|
||||
if (tokenRequestObject.clientId) {
|
||||
formBody.append('client_id', tokenRequestObject.clientId);
|
||||
}
|
||||
if (tokenRequestObject.redirectUri) {
|
||||
formBody.append('redirect_uri', tokenRequestObject.redirectUri);
|
||||
}
|
||||
if (tokenRequestObject.codeVerifier) {
|
||||
formBody.append('code_verifier', tokenRequestObject.codeVerifier);
|
||||
}
|
||||
const response = await fetch(tokenRequestObject.tokenEndpoint, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/x-www-form-urlencoded',
|
||||
},
|
||||
};
|
||||
};
|
||||
body: formBody.toString(),
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
const errorText = await response.text();
|
||||
console.error(
|
||||
'Token request failed with status:',
|
||||
response.status,
|
||||
errorText,
|
||||
);
|
||||
throw new Error(`Token request failed: ${response.status} ${errorText}`);
|
||||
}
|
||||
const tokenResponse = await response.json();
|
||||
return tokenResponse;
|
||||
}
|
||||
|
||||
@@ -157,7 +157,7 @@ export const activityLogMachine =
|
||||
setAllWellknownConfigResponse: model.assign({
|
||||
wellKnownIssuerMap: (_, event) => {
|
||||
Object.entries(event.response).forEach(([key, value]) => {
|
||||
event.response[key] = parseJSON(value);
|
||||
event.response[key] = parseJSON(value).response;
|
||||
});
|
||||
|
||||
return event.response as Record<string, Object>;
|
||||
|
||||
@@ -1,120 +1,80 @@
|
||||
|
||||
// This file was automatically generated. Edits will be overwritten
|
||||
|
||||
export interface Typegen0 {
|
||||
'@@xstate/typegen': true;
|
||||
internalEvents: {
|
||||
'done.invoke.app.init.checkKeyPairs:invocation[0]': {
|
||||
type: 'done.invoke.app.init.checkKeyPairs:invocation[0]';
|
||||
data: unknown;
|
||||
__tip: 'See the XState TS docs to learn how to strongly type this.';
|
||||
};
|
||||
'done.invoke.app.init.generateKeyPairs:invocation[0]': {
|
||||
type: 'done.invoke.app.init.generateKeyPairs:invocation[0]';
|
||||
data: unknown;
|
||||
__tip: 'See the XState TS docs to learn how to strongly type this.';
|
||||
};
|
||||
'done.invoke.app.ready.focus.active:invocation[0]': {
|
||||
type: 'done.invoke.app.ready.focus.active:invocation[0]';
|
||||
data: unknown;
|
||||
__tip: 'See the XState TS docs to learn how to strongly type this.';
|
||||
};
|
||||
'error.platform.app.init.checkKeyPairs:invocation[0]': {
|
||||
type: 'error.platform.app.init.checkKeyPairs:invocation[0]';
|
||||
data: unknown;
|
||||
};
|
||||
'xstate.init': {type: 'xstate.init'};
|
||||
};
|
||||
invokeSrcNameMap: {
|
||||
checkFocusState: 'done.invoke.app.ready.focus:invocation[0]';
|
||||
checkKeyPairs: 'done.invoke.app.init.checkKeyPairs:invocation[0]';
|
||||
checkNetworkState: 'done.invoke.app.ready.network:invocation[0]';
|
||||
generateKeyPairsAndStoreOrder: 'done.invoke.app.init.generateKeyPairs:invocation[0]';
|
||||
getAppInfo: 'done.invoke.app.init.info:invocation[0]';
|
||||
isQrLoginByDeepLink: 'done.invoke.app.ready.focus.active:invocation[0]';
|
||||
resetQRLoginDeepLinkData: 'done.invoke.app.ready.focus.active:invocation[1]';
|
||||
};
|
||||
missingImplementations: {
|
||||
actions: never;
|
||||
delays: never;
|
||||
guards: never;
|
||||
services: never;
|
||||
};
|
||||
eventsCausingActions: {
|
||||
forwardToServices: 'ACTIVE' | 'INACTIVE' | 'OFFLINE' | 'ONLINE';
|
||||
loadCredentialRegistryHostFromStorage: 'READY';
|
||||
loadCredentialRegistryInConstants: 'STORE_RESPONSE';
|
||||
loadEsignetHostFromConstants: 'STORE_RESPONSE';
|
||||
loadEsignetHostFromStorage: 'READY';
|
||||
logServiceEvents: 'done.invoke.app.init.checkKeyPairs:invocation[0]';
|
||||
logStoreEvents:
|
||||
| 'BIOMETRIC_CANCELLED'
|
||||
| 'KEY_INVALIDATE_ERROR'
|
||||
| 'RESET_KEY_INVALIDATE_ERROR_DISMISS'
|
||||
| 'xstate.init';
|
||||
requestDeviceInfo: 'REQUEST_DEVICE_INFO';
|
||||
resetKeyInvalidateError: 'READY' | 'RESET_KEY_INVALIDATE_ERROR_DISMISS';
|
||||
resetLinkCode: 'RESET_LINKCODE';
|
||||
setAppInfo: 'APP_INFO_RECEIVED';
|
||||
setIsDecryptError: 'DECRYPT_ERROR';
|
||||
setIsReadError: 'ERROR';
|
||||
setLinkCode: 'done.invoke.app.ready.focus.active:invocation[0]';
|
||||
spawnServiceActors: 'done.invoke.app.init.checkKeyPairs:invocation[0]';
|
||||
spawnStoreActor:
|
||||
| 'BIOMETRIC_CANCELLED'
|
||||
| 'KEY_INVALIDATE_ERROR'
|
||||
| 'RESET_KEY_INVALIDATE_ERROR_DISMISS'
|
||||
| 'xstate.init';
|
||||
unsetIsDecryptError: 'DECRYPT_ERROR_DISMISS' | 'READY';
|
||||
unsetIsReadError: 'READY';
|
||||
updateKeyInvalidateError: 'ERROR' | 'KEY_INVALIDATE_ERROR';
|
||||
};
|
||||
eventsCausingDelays: {};
|
||||
eventsCausingGuards: {};
|
||||
eventsCausingServices: {
|
||||
checkFocusState: 'APP_INFO_RECEIVED';
|
||||
checkKeyPairs:
|
||||
| 'READY'
|
||||
| 'done.invoke.app.init.generateKeyPairs:invocation[0]';
|
||||
checkNetworkState: 'APP_INFO_RECEIVED';
|
||||
generateKeyPairsAndStoreOrder: 'error.platform.app.init.checkKeyPairs:invocation[0]';
|
||||
getAppInfo: 'STORE_RESPONSE';
|
||||
isQrLoginByDeepLink: 'ACTIVE';
|
||||
resetQRLoginDeepLinkData: 'ACTIVE';
|
||||
};
|
||||
matchesStates:
|
||||
| 'init'
|
||||
| 'init.checkKeyPairs'
|
||||
| 'init.credentialRegistry'
|
||||
| 'init.generateKeyPairs'
|
||||
| 'init.info'
|
||||
| 'init.services'
|
||||
| 'init.store'
|
||||
| 'ready'
|
||||
| 'ready.focus'
|
||||
| 'ready.focus.active'
|
||||
| 'ready.focus.checking'
|
||||
| 'ready.focus.inactive'
|
||||
| 'ready.network'
|
||||
| 'ready.network.checking'
|
||||
| 'ready.network.offline'
|
||||
| 'ready.network.online'
|
||||
| 'waiting'
|
||||
| {
|
||||
init?:
|
||||
| 'checkKeyPairs'
|
||||
| 'credentialRegistry'
|
||||
| 'generateKeyPairs'
|
||||
| 'info'
|
||||
| 'services'
|
||||
| 'store';
|
||||
ready?:
|
||||
| 'focus'
|
||||
| 'network'
|
||||
| {
|
||||
focus?: 'active' | 'checking' | 'inactive';
|
||||
network?: 'checking' | 'offline' | 'online';
|
||||
};
|
||||
};
|
||||
tags: never;
|
||||
}
|
||||
export interface Typegen0 {
|
||||
'@@xstate/typegen': true;
|
||||
internalEvents: {
|
||||
"done.invoke.app.init.checkKeyPairs:invocation[0]": { type: "done.invoke.app.init.checkKeyPairs:invocation[0]"; data: unknown; __tip: "See the XState TS docs to learn how to strongly type this." };
|
||||
"done.invoke.app.init.fetchConfig:invocation[0]": { type: "done.invoke.app.init.fetchConfig:invocation[0]"; data: unknown; __tip: "See the XState TS docs to learn how to strongly type this." };
|
||||
"done.invoke.app.init.generateKeyPairs:invocation[0]": { type: "done.invoke.app.init.generateKeyPairs:invocation[0]"; data: unknown; __tip: "See the XState TS docs to learn how to strongly type this." };
|
||||
"done.invoke.app.ready.focus.active:invocation[0]": { type: "done.invoke.app.ready.focus.active:invocation[0]"; data: unknown; __tip: "See the XState TS docs to learn how to strongly type this." };
|
||||
"done.invoke.app.ready.focus.active:invocation[2]": { type: "done.invoke.app.ready.focus.active:invocation[2]"; data: unknown; __tip: "See the XState TS docs to learn how to strongly type this." };
|
||||
"error.platform.app.init.checkKeyPairs:invocation[0]": { type: "error.platform.app.init.checkKeyPairs:invocation[0]"; data: unknown };
|
||||
"error.platform.app.init.fetchConfig:invocation[0]": { type: "error.platform.app.init.fetchConfig:invocation[0]"; data: unknown };
|
||||
"xstate.init": { type: "xstate.init" };
|
||||
};
|
||||
invokeSrcNameMap: {
|
||||
"checkFocusState": "done.invoke.app.ready.focus:invocation[0]";
|
||||
"checkKeyPairs": "done.invoke.app.init.checkKeyPairs:invocation[0]";
|
||||
"checkNetworkState": "done.invoke.app.ready.network:invocation[0]";
|
||||
"fetchAndUpdateCacheTTLFromConfig": "done.invoke.app.init.fetchConfig:invocation[0]";
|
||||
"generateKeyPairsAndStoreOrder": "done.invoke.app.init.generateKeyPairs:invocation[0]";
|
||||
"getAppInfo": "done.invoke.app.init.info:invocation[0]";
|
||||
"getOVPDeepLinkIntent": "done.invoke.app.ready.focus.active:invocation[2]";
|
||||
"getQrLoginDeepLinkIntent": "done.invoke.app.ready.focus.active:invocation[0]";
|
||||
"resetOVPDeepLinkIntent": "done.invoke.app.ready.focus.active:invocation[3]";
|
||||
"resetQrLoginDeepLinkIntent": "done.invoke.app.ready.focus.active:invocation[1]";
|
||||
};
|
||||
missingImplementations: {
|
||||
actions: "forwardToServices";
|
||||
delays: never;
|
||||
guards: never;
|
||||
services: never;
|
||||
};
|
||||
eventsCausingActions: {
|
||||
"forwardToServices": "ACTIVE" | "INACTIVE" | "OFFLINE" | "ONLINE";
|
||||
"loadCredentialRegistryHostFromStorage": "READY";
|
||||
"loadCredentialRegistryInConstants": "STORE_RESPONSE";
|
||||
"loadEsignetHostFromConstants": "STORE_RESPONSE";
|
||||
"loadEsignetHostFromStorage": "READY";
|
||||
"logServiceEvents": "done.invoke.app.init.checkKeyPairs:invocation[0]";
|
||||
"logStoreEvents": "BIOMETRIC_CANCELLED" | "KEY_INVALIDATE_ERROR" | "RESET_KEY_INVALIDATE_ERROR_DISMISS" | "xstate.init";
|
||||
"requestDeviceInfo": "REQUEST_DEVICE_INFO";
|
||||
"resetAuthorizationRequest": "RESET_AUTHORIZATION_REQUEST";
|
||||
"resetKeyInvalidateError": "READY" | "RESET_KEY_INVALIDATE_ERROR_DISMISS";
|
||||
"resetLinkCode": "RESET_LINKCODE";
|
||||
"setAppInfo": "APP_INFO_RECEIVED";
|
||||
"setAuthorizationRequest": "done.invoke.app.ready.focus.active:invocation[2]";
|
||||
"setIsDecryptError": "DECRYPT_ERROR";
|
||||
"setIsReadError": "ERROR";
|
||||
"setLinkCode": "done.invoke.app.ready.focus.active:invocation[0]";
|
||||
"spawnServiceActors": "done.invoke.app.init.checkKeyPairs:invocation[0]";
|
||||
"spawnStoreActor": "BIOMETRIC_CANCELLED" | "KEY_INVALIDATE_ERROR" | "RESET_KEY_INVALIDATE_ERROR_DISMISS" | "xstate.init";
|
||||
"unsetIsDecryptError": "DECRYPT_ERROR_DISMISS" | "READY";
|
||||
"unsetIsReadError": "READY";
|
||||
"updateKeyInvalidateError": "ERROR" | "KEY_INVALIDATE_ERROR";
|
||||
};
|
||||
eventsCausingDelays: {
|
||||
|
||||
};
|
||||
eventsCausingGuards: {
|
||||
|
||||
};
|
||||
eventsCausingServices: {
|
||||
"checkFocusState": "APP_INFO_RECEIVED";
|
||||
"checkKeyPairs": "READY" | "done.invoke.app.init.fetchConfig:invocation[0]" | "error.platform.app.init.fetchConfig:invocation[0]";
|
||||
"checkNetworkState": "APP_INFO_RECEIVED";
|
||||
"fetchAndUpdateCacheTTLFromConfig": "done.invoke.app.init.generateKeyPairs:invocation[0]";
|
||||
"generateKeyPairsAndStoreOrder": "error.platform.app.init.checkKeyPairs:invocation[0]";
|
||||
"getAppInfo": "STORE_RESPONSE";
|
||||
"getOVPDeepLinkIntent": "ACTIVE";
|
||||
"getQrLoginDeepLinkIntent": "ACTIVE";
|
||||
"resetOVPDeepLinkIntent": "ACTIVE";
|
||||
"resetQrLoginDeepLinkIntent": "ACTIVE";
|
||||
};
|
||||
matchesStates: "init" | "init.checkKeyPairs" | "init.credentialRegistry" | "init.fetchConfig" | "init.generateKeyPairs" | "init.info" | "init.services" | "init.store" | "ready" | "ready.focus" | "ready.focus.active" | "ready.focus.checking" | "ready.focus.inactive" | "ready.network" | "ready.network.checking" | "ready.network.offline" | "ready.network.online" | "waiting" | { "init"?: "checkKeyPairs" | "credentialRegistry" | "fetchConfig" | "generateKeyPairs" | "info" | "services" | "store";
|
||||
"ready"?: "focus" | "network" | { "focus"?: "active" | "checking" | "inactive";
|
||||
"network"?: "checking" | "offline" | "online"; }; };
|
||||
tags: never;
|
||||
}
|
||||
|
||||
@@ -1,156 +1,63 @@
|
||||
// This file was automatically generated. Edits will be overwritten
|
||||
|
||||
export interface Typegen0 {
|
||||
'@@xstate/typegen': true;
|
||||
internalEvents: {
|
||||
'done.invoke.restore.restoreBackup.checkInternet:invocation[0]': {
|
||||
type: 'done.invoke.restore.restoreBackup.checkInternet:invocation[0]';
|
||||
data: unknown;
|
||||
__tip: 'See the XState TS docs to learn how to strongly type this.';
|
||||
};
|
||||
'done.invoke.restore.restoreBackup.checkStorageAvailability:invocation[0]': {
|
||||
type: 'done.invoke.restore.restoreBackup.checkStorageAvailability:invocation[0]';
|
||||
data: unknown;
|
||||
__tip: 'See the XState TS docs to learn how to strongly type this.';
|
||||
};
|
||||
'done.invoke.restore.restoreBackup.downloadBackupFileFromCloud:invocation[0]': {
|
||||
type: 'done.invoke.restore.restoreBackup.downloadBackupFileFromCloud:invocation[0]';
|
||||
data: unknown;
|
||||
__tip: 'See the XState TS docs to learn how to strongly type this.';
|
||||
};
|
||||
'done.invoke.restore.restoreBackup.unzipBackupFile:invocation[0]': {
|
||||
type: 'done.invoke.restore.restoreBackup.unzipBackupFile:invocation[0]';
|
||||
data: unknown;
|
||||
__tip: 'See the XState TS docs to learn how to strongly type this.';
|
||||
};
|
||||
'error.platform.restore.restoreBackup.checkInternet:invocation[0]': {
|
||||
type: 'error.platform.restore.restoreBackup.checkInternet:invocation[0]';
|
||||
data: unknown;
|
||||
};
|
||||
'error.platform.restore.restoreBackup.downloadBackupFileFromCloud:invocation[0]': {
|
||||
type: 'error.platform.restore.restoreBackup.downloadBackupFileFromCloud:invocation[0]';
|
||||
data: unknown;
|
||||
};
|
||||
'error.platform.restore.restoreBackup.unzipBackupFile:invocation[0]': {
|
||||
type: 'error.platform.restore.restoreBackup.unzipBackupFile:invocation[0]';
|
||||
data: unknown;
|
||||
};
|
||||
'xstate.init': {type: 'xstate.init'};
|
||||
};
|
||||
invokeSrcNameMap: {
|
||||
checkInternet: 'done.invoke.restore.restoreBackup.checkInternet:invocation[0]';
|
||||
checkStorageAvailability: 'done.invoke.restore.restoreBackup.checkStorageAvailability:invocation[0]';
|
||||
downloadLatestBackup: 'done.invoke.restore.restoreBackup.downloadBackupFileFromCloud:invocation[0]';
|
||||
readBackupFile: 'done.invoke.restore.restoreBackup.readBackupFile:invocation[0]';
|
||||
unzipBackupFile: 'done.invoke.restore.restoreBackup.unzipBackupFile:invocation[0]';
|
||||
};
|
||||
missingImplementations: {
|
||||
actions:
|
||||
| 'cleanupFiles'
|
||||
| 'downloadUnsyncedBackupFiles'
|
||||
| 'loadDataToMemory'
|
||||
| 'refreshVCs'
|
||||
| 'sendDataRestoreErrorEvent'
|
||||
| 'sendDataRestoreFailureEvent'
|
||||
| 'sendDataRestoreStartEvent'
|
||||
| 'sendDataRestoreSuccessEvent'
|
||||
| 'setBackupFileName'
|
||||
| 'setDataFromBackupFile'
|
||||
| 'setRestoreErrorReason'
|
||||
| 'setRestoreErrorReasonAsNetworkError'
|
||||
| 'setRestoreTechnicalError'
|
||||
| 'setShowRestoreInProgress'
|
||||
| 'unsetShowRestoreInProgress';
|
||||
delays: never;
|
||||
guards:
|
||||
| 'isInternetConnected'
|
||||
| 'isMinimumStorageRequiredForBackupRestorationReached';
|
||||
services:
|
||||
| 'checkInternet'
|
||||
| 'checkStorageAvailability'
|
||||
| 'downloadLatestBackup'
|
||||
| 'readBackupFile'
|
||||
| 'unzipBackupFile';
|
||||
};
|
||||
eventsCausingActions: {
|
||||
cleanupFiles:
|
||||
| 'STORE_ERROR'
|
||||
| 'STORE_RESPONSE'
|
||||
| 'done.invoke.restore.restoreBackup.checkInternet:invocation[0]'
|
||||
| 'done.invoke.restore.restoreBackup.checkStorageAvailability:invocation[0]'
|
||||
| 'error.platform.restore.restoreBackup.checkInternet:invocation[0]'
|
||||
| 'error.platform.restore.restoreBackup.downloadBackupFileFromCloud:invocation[0]'
|
||||
| 'error.platform.restore.restoreBackup.unzipBackupFile:invocation[0]';
|
||||
downloadUnsyncedBackupFiles: 'DOWNLOAD_UNSYNCED_BACKUP_FILES';
|
||||
loadDataToMemory: 'DATA_FROM_FILE';
|
||||
refreshVCs: 'STORE_RESPONSE';
|
||||
sendDataRestoreErrorEvent:
|
||||
| 'done.invoke.restore.restoreBackup.checkInternet:invocation[0]'
|
||||
| 'error.platform.restore.restoreBackup.checkInternet:invocation[0]';
|
||||
sendDataRestoreFailureEvent:
|
||||
| 'STORE_ERROR'
|
||||
| 'done.invoke.restore.restoreBackup.checkInternet:invocation[0]'
|
||||
| 'done.invoke.restore.restoreBackup.checkStorageAvailability:invocation[0]'
|
||||
| 'error.platform.restore.restoreBackup.checkInternet:invocation[0]'
|
||||
| 'error.platform.restore.restoreBackup.downloadBackupFileFromCloud:invocation[0]'
|
||||
| 'error.platform.restore.restoreBackup.unzipBackupFile:invocation[0]';
|
||||
sendDataRestoreStartEvent: 'BACKUP_RESTORE';
|
||||
sendDataRestoreSuccessEvent: 'STORE_RESPONSE';
|
||||
setBackupFileName: 'done.invoke.restore.restoreBackup.downloadBackupFileFromCloud:invocation[0]';
|
||||
setDataFromBackupFile: 'DATA_FROM_FILE';
|
||||
setRestoreErrorReason:
|
||||
| 'error.platform.restore.restoreBackup.downloadBackupFileFromCloud:invocation[0]'
|
||||
| 'error.platform.restore.restoreBackup.unzipBackupFile:invocation[0]';
|
||||
setRestoreErrorReasonAsNetworkError:
|
||||
| 'done.invoke.restore.restoreBackup.checkInternet:invocation[0]'
|
||||
| 'error.platform.restore.restoreBackup.checkInternet:invocation[0]';
|
||||
setRestoreTechnicalError:
|
||||
| 'STORE_ERROR'
|
||||
| 'done.invoke.restore.restoreBackup.checkStorageAvailability:invocation[0]';
|
||||
setShowRestoreInProgress: 'BACKUP_RESTORE';
|
||||
unsetShowRestoreInProgress:
|
||||
| 'DISMISS_SHOW_RESTORE_IN_PROGRESS'
|
||||
| 'STORE_ERROR'
|
||||
| 'STORE_RESPONSE'
|
||||
| 'done.invoke.restore.restoreBackup.checkInternet:invocation[0]'
|
||||
| 'done.invoke.restore.restoreBackup.checkStorageAvailability:invocation[0]'
|
||||
| 'error.platform.restore.restoreBackup.checkInternet:invocation[0]'
|
||||
| 'error.platform.restore.restoreBackup.downloadBackupFileFromCloud:invocation[0]'
|
||||
| 'error.platform.restore.restoreBackup.unzipBackupFile:invocation[0]';
|
||||
};
|
||||
eventsCausingDelays: {};
|
||||
eventsCausingGuards: {
|
||||
isInternetConnected: 'done.invoke.restore.restoreBackup.checkInternet:invocation[0]';
|
||||
isMinimumStorageRequiredForBackupRestorationReached: 'done.invoke.restore.restoreBackup.checkStorageAvailability:invocation[0]';
|
||||
};
|
||||
eventsCausingServices: {
|
||||
checkInternet: 'BACKUP_RESTORE';
|
||||
checkStorageAvailability: 'done.invoke.restore.restoreBackup.checkInternet:invocation[0]';
|
||||
downloadLatestBackup: 'done.invoke.restore.restoreBackup.checkStorageAvailability:invocation[0]';
|
||||
readBackupFile: 'done.invoke.restore.restoreBackup.unzipBackupFile:invocation[0]';
|
||||
unzipBackupFile: 'done.invoke.restore.restoreBackup.downloadBackupFileFromCloud:invocation[0]';
|
||||
};
|
||||
matchesStates:
|
||||
| 'init'
|
||||
| 'restoreBackup'
|
||||
| 'restoreBackup.checkInternet'
|
||||
| 'restoreBackup.checkStorageAvailability'
|
||||
| 'restoreBackup.downloadBackupFileFromCloud'
|
||||
| 'restoreBackup.failure'
|
||||
| 'restoreBackup.loadDataToMemory'
|
||||
| 'restoreBackup.readBackupFile'
|
||||
| 'restoreBackup.success'
|
||||
| 'restoreBackup.unzipBackupFile'
|
||||
| {
|
||||
restoreBackup?:
|
||||
| 'checkInternet'
|
||||
| 'checkStorageAvailability'
|
||||
| 'downloadBackupFileFromCloud'
|
||||
| 'failure'
|
||||
| 'loadDataToMemory'
|
||||
| 'readBackupFile'
|
||||
| 'success'
|
||||
| 'unzipBackupFile';
|
||||
};
|
||||
tags: never;
|
||||
}
|
||||
// This file was automatically generated. Edits will be overwritten
|
||||
|
||||
export interface Typegen0 {
|
||||
'@@xstate/typegen': true;
|
||||
internalEvents: {
|
||||
"done.invoke.restore.restoreBackup.checkInternet:invocation[0]": { type: "done.invoke.restore.restoreBackup.checkInternet:invocation[0]"; data: unknown; __tip: "See the XState TS docs to learn how to strongly type this." };
|
||||
"done.invoke.restore.restoreBackup.checkStorageAvailability:invocation[0]": { type: "done.invoke.restore.restoreBackup.checkStorageAvailability:invocation[0]"; data: unknown; __tip: "See the XState TS docs to learn how to strongly type this." };
|
||||
"done.invoke.restore.restoreBackup.downloadBackupFileFromCloud:invocation[0]": { type: "done.invoke.restore.restoreBackup.downloadBackupFileFromCloud:invocation[0]"; data: unknown; __tip: "See the XState TS docs to learn how to strongly type this." };
|
||||
"done.invoke.restore.restoreBackup.unzipBackupFile:invocation[0]": { type: "done.invoke.restore.restoreBackup.unzipBackupFile:invocation[0]"; data: unknown; __tip: "See the XState TS docs to learn how to strongly type this." };
|
||||
"error.platform.restore.restoreBackup.checkInternet:invocation[0]": { type: "error.platform.restore.restoreBackup.checkInternet:invocation[0]"; data: unknown };
|
||||
"error.platform.restore.restoreBackup.downloadBackupFileFromCloud:invocation[0]": { type: "error.platform.restore.restoreBackup.downloadBackupFileFromCloud:invocation[0]"; data: unknown };
|
||||
"error.platform.restore.restoreBackup.unzipBackupFile:invocation[0]": { type: "error.platform.restore.restoreBackup.unzipBackupFile:invocation[0]"; data: unknown };
|
||||
"xstate.init": { type: "xstate.init" };
|
||||
};
|
||||
invokeSrcNameMap: {
|
||||
"checkInternet": "done.invoke.restore.restoreBackup.checkInternet:invocation[0]";
|
||||
"checkStorageAvailability": "done.invoke.restore.restoreBackup.checkStorageAvailability:invocation[0]";
|
||||
"downloadLatestBackup": "done.invoke.restore.restoreBackup.downloadBackupFileFromCloud:invocation[0]";
|
||||
"readBackupFile": "done.invoke.restore.restoreBackup.readBackupFile:invocation[0]";
|
||||
"unzipBackupFile": "done.invoke.restore.restoreBackup.unzipBackupFile:invocation[0]";
|
||||
};
|
||||
missingImplementations: {
|
||||
actions: "cleanupFiles" | "downloadUnsyncedBackupFiles" | "loadDataToMemory" | "refreshVCs" | "sendDataRestoreErrorEvent" | "sendDataRestoreFailureEvent" | "sendDataRestoreStartEvent" | "sendDataRestoreSuccessEvent" | "setBackupFileName" | "setDataFromBackupFile" | "setRestoreErrorReason" | "setRestoreErrorReasonAsNetworkError" | "setRestoreTechnicalError" | "setShowRestoreInProgress" | "unsetShowRestoreInProgress";
|
||||
delays: never;
|
||||
guards: "isInternetConnected" | "isMinimumStorageRequiredForBackupRestorationReached";
|
||||
services: "checkInternet" | "checkStorageAvailability" | "downloadLatestBackup" | "readBackupFile" | "unzipBackupFile";
|
||||
};
|
||||
eventsCausingActions: {
|
||||
"cleanupFiles": "STORE_ERROR" | "STORE_RESPONSE" | "done.invoke.restore.restoreBackup.checkInternet:invocation[0]" | "done.invoke.restore.restoreBackup.checkStorageAvailability:invocation[0]" | "error.platform.restore.restoreBackup.checkInternet:invocation[0]" | "error.platform.restore.restoreBackup.downloadBackupFileFromCloud:invocation[0]" | "error.platform.restore.restoreBackup.unzipBackupFile:invocation[0]";
|
||||
"downloadUnsyncedBackupFiles": "DOWNLOAD_UNSYNCED_BACKUP_FILES";
|
||||
"loadDataToMemory": "DATA_FROM_FILE";
|
||||
"refreshVCs": "STORE_RESPONSE";
|
||||
"sendDataRestoreErrorEvent": "done.invoke.restore.restoreBackup.checkInternet:invocation[0]" | "error.platform.restore.restoreBackup.checkInternet:invocation[0]";
|
||||
"sendDataRestoreFailureEvent": "STORE_ERROR" | "done.invoke.restore.restoreBackup.checkInternet:invocation[0]" | "done.invoke.restore.restoreBackup.checkStorageAvailability:invocation[0]" | "error.platform.restore.restoreBackup.checkInternet:invocation[0]" | "error.platform.restore.restoreBackup.downloadBackupFileFromCloud:invocation[0]" | "error.platform.restore.restoreBackup.unzipBackupFile:invocation[0]";
|
||||
"sendDataRestoreStartEvent": "BACKUP_RESTORE";
|
||||
"sendDataRestoreSuccessEvent": "STORE_RESPONSE";
|
||||
"setBackupFileName": "done.invoke.restore.restoreBackup.downloadBackupFileFromCloud:invocation[0]";
|
||||
"setDataFromBackupFile": "DATA_FROM_FILE";
|
||||
"setRestoreErrorReason": "error.platform.restore.restoreBackup.downloadBackupFileFromCloud:invocation[0]" | "error.platform.restore.restoreBackup.unzipBackupFile:invocation[0]";
|
||||
"setRestoreErrorReasonAsNetworkError": "done.invoke.restore.restoreBackup.checkInternet:invocation[0]" | "error.platform.restore.restoreBackup.checkInternet:invocation[0]";
|
||||
"setRestoreTechnicalError": "STORE_ERROR" | "done.invoke.restore.restoreBackup.checkStorageAvailability:invocation[0]";
|
||||
"setShowRestoreInProgress": "BACKUP_RESTORE";
|
||||
"unsetShowRestoreInProgress": "DISMISS_SHOW_RESTORE_IN_PROGRESS" | "STORE_ERROR" | "STORE_RESPONSE" | "done.invoke.restore.restoreBackup.checkInternet:invocation[0]" | "done.invoke.restore.restoreBackup.checkStorageAvailability:invocation[0]" | "error.platform.restore.restoreBackup.checkInternet:invocation[0]" | "error.platform.restore.restoreBackup.downloadBackupFileFromCloud:invocation[0]" | "error.platform.restore.restoreBackup.unzipBackupFile:invocation[0]";
|
||||
};
|
||||
eventsCausingDelays: {
|
||||
|
||||
};
|
||||
eventsCausingGuards: {
|
||||
"isInternetConnected": "done.invoke.restore.restoreBackup.checkInternet:invocation[0]";
|
||||
"isMinimumStorageRequiredForBackupRestorationReached": "done.invoke.restore.restoreBackup.checkStorageAvailability:invocation[0]";
|
||||
};
|
||||
eventsCausingServices: {
|
||||
"checkInternet": "BACKUP_RESTORE";
|
||||
"checkStorageAvailability": "done.invoke.restore.restoreBackup.checkInternet:invocation[0]";
|
||||
"downloadLatestBackup": "done.invoke.restore.restoreBackup.checkStorageAvailability:invocation[0]";
|
||||
"readBackupFile": "done.invoke.restore.restoreBackup.unzipBackupFile:invocation[0]";
|
||||
"unzipBackupFile": "done.invoke.restore.restoreBackup.downloadBackupFileFromCloud:invocation[0]";
|
||||
};
|
||||
matchesStates: "init" | "restoreBackup" | "restoreBackup.checkInternet" | "restoreBackup.checkStorageAvailability" | "restoreBackup.downloadBackupFileFromCloud" | "restoreBackup.failure" | "restoreBackup.loadDataToMemory" | "restoreBackup.readBackupFile" | "restoreBackup.success" | "restoreBackup.unzipBackupFile" | { "restoreBackup"?: "checkInternet" | "checkStorageAvailability" | "downloadBackupFileFromCloud" | "failure" | "loadDataToMemory" | "readBackupFile" | "success" | "unzipBackupFile"; };
|
||||
tags: never;
|
||||
}
|
||||
|
||||
@@ -218,7 +218,7 @@ export const openID4VPActions = (model: any) => {
|
||||
),
|
||||
|
||||
shareDeclineStatus: () => {
|
||||
OpenID4VP.getInstance().sendErrorToVerifier(
|
||||
OpenID4VP.sendErrorToVerifier(
|
||||
OVP_ERROR_MESSAGES.DECLINED,
|
||||
OVP_ERROR_CODE.DECLINED,
|
||||
);
|
||||
@@ -308,7 +308,7 @@ function getVcsMatchingAuthRequest(context, event) {
|
||||
}
|
||||
|
||||
if (Object.keys(matchingVCs).length === 0) {
|
||||
OpenID4VP.getInstance().sendErrorToVerifier(
|
||||
OpenID4VP.sendErrorToVerifier(
|
||||
OVP_ERROR_MESSAGES.NO_MATCHING_VCS,
|
||||
OVP_ERROR_CODE.NO_MATCHING_VCS,
|
||||
);
|
||||
|
||||
@@ -29,11 +29,10 @@ export const openID4VPServices = () => {
|
||||
},
|
||||
|
||||
getAuthenticationResponse: (context: any) => async () => {
|
||||
const serviceRes = await OpenID4VP.getInstance().authenticateVerifier(
|
||||
return await OpenID4VP.authenticateVerifier(
|
||||
context.urlEncodedAuthorizationRequest,
|
||||
context.trustedVerifiers,
|
||||
);
|
||||
return serviceRes;
|
||||
},
|
||||
|
||||
getKeyPair: async (context: any) => {
|
||||
@@ -47,12 +46,10 @@ export const openID4VPServices = () => {
|
||||
},
|
||||
|
||||
sendVP: (context: any) => async () => {
|
||||
const openid = OpenID4VP.getInstance();
|
||||
|
||||
const jwk = await getJWK(context.publicKey, context.keyType);
|
||||
const holderId = 'did:jwk:' + base64url(JSON.stringify(jwk)) + '#0';
|
||||
|
||||
const unSignedVpTokens = await openid.constructUnsignedVPToken(
|
||||
const unSignedVpTokens = await OpenID4VP.constructUnsignedVPToken(
|
||||
context.selectedVCs,
|
||||
holderId,
|
||||
signatureSuite,
|
||||
@@ -137,7 +134,9 @@ export const openID4VPServices = () => {
|
||||
vpTokenSigningResultMap[formatType] = signedData;
|
||||
}
|
||||
}
|
||||
return await openid.shareVerifiablePresentation(vpTokenSigningResultMap);
|
||||
return await OpenID4VP.shareVerifiablePresentation(
|
||||
vpTokenSigningResultMap,
|
||||
);
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1,54 +0,0 @@
|
||||
|
||||
// This file was automatically generated. Edits will be overwritten
|
||||
|
||||
export interface Typegen0 {
|
||||
'@@xstate/typegen': true;
|
||||
internalEvents: {
|
||||
"done.invoke._store": { type: "done.invoke._store"; data: unknown; __tip: "See the XState TS docs to learn how to strongly type this." };
|
||||
"done.invoke.store.checkFreshInstall:invocation[0]": { type: "done.invoke.store.checkFreshInstall:invocation[0]"; data: unknown; __tip: "See the XState TS docs to learn how to strongly type this." };
|
||||
"done.invoke.store.resettingStorage:invocation[0]": { type: "done.invoke.store.resettingStorage:invocation[0]"; data: unknown; __tip: "See the XState TS docs to learn how to strongly type this." };
|
||||
"error.platform._store": { type: "error.platform._store"; data: unknown };
|
||||
"xstate.init": { type: "xstate.init" };
|
||||
};
|
||||
invokeSrcNameMap: {
|
||||
"checkFreshInstall": "done.invoke.store.checkFreshInstall:invocation[0]";
|
||||
"checkStorageInitialisedOrNot": "done.invoke.store.checkStorageInitialisation:invocation[0]";
|
||||
"clear": "done.invoke.store.resettingStorage:invocation[0]";
|
||||
"clearKeys": "done.invoke.store.clearIosKeys:invocation[0]";
|
||||
"generateEncryptionKey": "done.invoke.store.generatingEncryptionKey:invocation[0]";
|
||||
"getEncryptionKey": "done.invoke.store.gettingEncryptionKey:invocation[0]";
|
||||
"hasEncryptionKey": "done.invoke.store.checkEncryptionKey:invocation[0]";
|
||||
"store": "done.invoke._store";
|
||||
};
|
||||
missingImplementations: {
|
||||
actions: never;
|
||||
delays: never;
|
||||
guards: never;
|
||||
services: never;
|
||||
};
|
||||
eventsCausingActions: {
|
||||
"forwardStoreRequest": "APPEND" | "CLEAR" | "EXPORT" | "FETCH_ALL_WELLKNOWN_CONFIG" | "GET" | "GET_VCS_DATA" | "PREPEND" | "REMOVE" | "REMOVE_ITEMS" | "REMOVE_VC_METADATA" | "RESTORE_BACKUP" | "SET" | "UPDATE";
|
||||
"notifyParent": "KEY_RECEIVED" | "READY" | "done.invoke.store.resettingStorage:invocation[0]";
|
||||
"setEncryptionKey": "KEY_RECEIVED";
|
||||
};
|
||||
eventsCausingDelays: {
|
||||
|
||||
};
|
||||
eventsCausingGuards: {
|
||||
"hasData": "done.invoke.store.checkFreshInstall:invocation[0]";
|
||||
"isCustomSecureKeystore": "KEY_RECEIVED";
|
||||
};
|
||||
eventsCausingServices: {
|
||||
"checkFreshInstall": "BIOMETRIC_CANCELLED" | "xstate.init";
|
||||
"checkStorageInitialisedOrNot": "ERROR";
|
||||
"clear": "KEY_RECEIVED";
|
||||
"clearKeys": "done.invoke.store.checkFreshInstall:invocation[0]";
|
||||
"generateEncryptionKey": "ERROR" | "IGNORE" | "READY";
|
||||
"getEncryptionKey": "TRY_AGAIN";
|
||||
"hasEncryptionKey": never;
|
||||
"store": "KEY_RECEIVED" | "READY" | "done.invoke.store.resettingStorage:invocation[0]";
|
||||
};
|
||||
matchesStates: "checkEncryptionKey" | "checkFreshInstall" | "checkStorageInitialisation" | "clearIosKeys" | "failedReadingKey" | "generatingEncryptionKey" | "gettingEncryptionKey" | "ready" | "resettingStorage";
|
||||
tags: never;
|
||||
}
|
||||
|
||||
@@ -12,17 +12,14 @@ import {
|
||||
selectSelectedIssuer,
|
||||
selectSelectingCredentialType,
|
||||
selectStoring,
|
||||
selectVerificationErrorMessage,
|
||||
selectIsNonGenericError,
|
||||
selectIsQrScanning,
|
||||
selectCredentialOfferData,
|
||||
selectVerificationErrorMessage, selectIsQrScanning,
|
||||
selectAuthWebViewStatus,
|
||||
selectAuthEndPoint,
|
||||
selectIsTxCodeRequested,
|
||||
selectIsConsentRequested,
|
||||
selectIssuerLogo,
|
||||
selectIssuerName,
|
||||
selectTxCodeDisplayDetails,
|
||||
selectTxCodeDisplayDetails
|
||||
} from '../../machines/Issuers/IssuersSelectors';
|
||||
import { ActorRefFrom } from 'xstate';
|
||||
import { BOTTOM_TAB_ROUTES } from '../../routes/routesConstants';
|
||||
@@ -40,10 +37,10 @@ export function useIssuerScreenController({ route, navigation }) {
|
||||
|
||||
return {
|
||||
issuers: useSelector(service, selectIssuers),
|
||||
issuerLogo: useSelector(service,selectIssuerLogo),
|
||||
issuerName: useSelector(service,selectIssuerName),
|
||||
isTxCodeRequested: useSelector(service,selectIsTxCodeRequested),
|
||||
txCodeDisplayDetails: useSelector(service,selectTxCodeDisplayDetails),
|
||||
issuerLogo: useSelector(service, selectIssuerLogo),
|
||||
issuerName: useSelector(service, selectIssuerName),
|
||||
isTxCodeRequested: useSelector(service, selectIsTxCodeRequested),
|
||||
txCodeDisplayDetails: useSelector(service, selectTxCodeDisplayDetails),
|
||||
authEndpount: useSelector(service, selectAuthEndPoint),
|
||||
selectedIssuer: useSelector(service, selectSelectedIssuer),
|
||||
errorMessageType: useSelector(service, selectErrorMessageType),
|
||||
@@ -51,7 +48,6 @@ export function useIssuerScreenController({ route, navigation }) {
|
||||
isBiometricsCancelled: useSelector(service, selectIsBiometricCancelled),
|
||||
isDone: useSelector(service, selectIsDone),
|
||||
isIdle: useSelector(service, selectIsIdle),
|
||||
isNonGenericError: useSelector(service, selectIsNonGenericError),
|
||||
loadingReason: useSelector(service, selectLoadingReason),
|
||||
isStoring: useSelector(service, selectStoring),
|
||||
isQrScanning: useSelector(service, selectIsQrScanning),
|
||||
@@ -61,9 +57,8 @@ export function useIssuerScreenController({ route, navigation }) {
|
||||
selectSelectingCredentialType,
|
||||
),
|
||||
isConsentRequested: useSelector(
|
||||
service,selectIsConsentRequested
|
||||
service, selectIsConsentRequested
|
||||
),
|
||||
credentialOfferData: useSelector(service, selectCredentialOfferData),
|
||||
supportedCredentialTypes: useSelector(
|
||||
service,
|
||||
selectSupportedCredentialTypes,
|
||||
|
||||
@@ -38,6 +38,7 @@ import { IssuersModel } from '../../machines/Issuers/IssuersModel';
|
||||
import { AUTH_ROUTES } from '../../routes/routesConstants';
|
||||
import { TransactionCodeModal } from './TransactionCodeScreen';
|
||||
import { TrustIssuerModal } from './TrustIssuerModal';
|
||||
import i18next from 'i18next';
|
||||
export const IssuersScreen: React.FC<
|
||||
HomeRouteProps | RootRouteProps
|
||||
> = props => {
|
||||
@@ -49,7 +50,7 @@ export const IssuersScreen: React.FC<
|
||||
const [search, setSearch] = useState('');
|
||||
const [tapToSearch, setTapToSearch] = useState(false);
|
||||
const [clearSearchIcon, setClearSearchIcon] = useState(false);
|
||||
const showFullScreenError = controller.isError && controller.errorMessageType;
|
||||
const showFullScreenError = controller.isError
|
||||
|
||||
const isVerificationFailed = controller.verificationErrorMessage !== '';
|
||||
|
||||
@@ -57,7 +58,8 @@ export const IssuersScreen: React.FC<
|
||||
|
||||
const verificationErrorMessage = isTranslationKeyFound(translationKey, t)
|
||||
? t(translationKey)
|
||||
: t(`errors.verificationFailed.ERR_GENERIC`);
|
||||
: t('errors.verificationFailed.ERR_GENERIC');
|
||||
|
||||
|
||||
useLayoutEffect(() => {
|
||||
if (controller.loadingReason || showFullScreenError) {
|
||||
@@ -124,7 +126,8 @@ export const IssuersScreen: React.FC<
|
||||
controller.errorMessageType ===
|
||||
ErrorMessage.CREDENTIAL_TYPE_DOWNLOAD_FAILURE ||
|
||||
controller.errorMessageType ===
|
||||
ErrorMessage.AUTHORIZATION_GRANT_TYPE_NOT_SUPPORTED
|
||||
ErrorMessage.AUTHORIZATION_GRANT_TYPE_NOT_SUPPORTED ||
|
||||
controller.errorMessageType === ErrorMessage.NETWORK_REQUEST_FAILED
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -113,7 +113,7 @@ export const TransactionCodeModal: React.FC<ExtendedModalProps> = props => {
|
||||
}`,
|
||||
)}
|
||||
</Text>
|
||||
{textLineCount >= maxLines && <Text
|
||||
{textLineCount > maxLines && <Text
|
||||
onPress={() => setShowFullDescription(prev => !prev)}
|
||||
style={Theme.TransactionCodeScreenStyle.showMoreButton}
|
||||
>
|
||||
|
||||
@@ -29,16 +29,27 @@ import {VerifyIdentityOverlay} from '../VerifyIdentityOverlay';
|
||||
import {VCShareFlowType} from '../../shared/Utils';
|
||||
import {APP_EVENTS} from '../../machines/app';
|
||||
import {GlobalContext} from '../../shared/GlobalContext';
|
||||
import {useOvpErrorModal} from '../../shared/hooks/useOvpErrorModal';
|
||||
|
||||
export const ScanScreen: React.FC = () => {
|
||||
const {t} = useTranslation('ScanScreen');
|
||||
const scanScreenController = useScanScreen();
|
||||
const sendVcScreenController = useSendVcScreen();
|
||||
const sendVPScreenController = useSendVPScreen();
|
||||
const [errorModal] = useOvpErrorModal({
|
||||
error: sendVPScreenController.error,
|
||||
noCredentialsMatchingVPRequest:
|
||||
sendVPScreenController.noCredentialsMatchingVPRequest,
|
||||
requestedClaimsByVerifier: sendVPScreenController.requestedClaimsByVerifier,
|
||||
getAdditionalMessage: sendVPScreenController.getAdditionalMessage,
|
||||
generateAndStoreLogMessage:
|
||||
sendVPScreenController.generateAndStoreLogMessage,
|
||||
t,
|
||||
});
|
||||
const [isBluetoothOn, setIsBluetoothOn] = useState(false);
|
||||
const showErrorModal =
|
||||
sendVPScreenController.scanScreenError ||
|
||||
(sendVPScreenController.errorModal.show &&
|
||||
(errorModal.show &&
|
||||
(sendVPScreenController.flowType ===
|
||||
VCShareFlowType.MINI_VIEW_SHARE_OPENID4VP ||
|
||||
sendVPScreenController.flowType ===
|
||||
@@ -277,7 +288,7 @@ export const ScanScreen: React.FC = () => {
|
||||
|
||||
const getPrimaryButtonText = () => {
|
||||
if (
|
||||
sendVPScreenController.errorModal.showRetryButton &&
|
||||
errorModal.showRetryButton &&
|
||||
sendVPScreenController.openID4VPRetryCount < 3
|
||||
) {
|
||||
return t('ScanScreen:status.retry');
|
||||
@@ -366,8 +377,8 @@ export const ScanScreen: React.FC = () => {
|
||||
alignActionsOnEnd
|
||||
showClose={false}
|
||||
isVisible={showErrorModal}
|
||||
title={sendVPScreenController.errorModal.title}
|
||||
message={sendVPScreenController.errorModal.message}
|
||||
title={errorModal.title}
|
||||
message={errorModal.message}
|
||||
image={SvgImage.PermissionDenied()}
|
||||
primaryButtonTestID={'retry'}
|
||||
primaryButtonText={getPrimaryButtonText()}
|
||||
|
||||
@@ -32,22 +32,32 @@ import OpenID4VP from '../../shared/openID4VP/OpenID4VP';
|
||||
import {GlobalContext} from '../../shared/GlobalContext';
|
||||
import {APP_EVENTS} from '../../machines/app';
|
||||
import {useScanScreen} from './ScanScreenController';
|
||||
import {useOvpErrorModal} from '../../shared/hooks/useOvpErrorModal';
|
||||
|
||||
export const SendVPScreen: React.FC<ScanLayoutProps> = props => {
|
||||
const {t} = useTranslation('SendVPScreen');
|
||||
const controller = useSendVPScreen();
|
||||
const scanScreenController = useScanScreen();
|
||||
|
||||
const [errorModal, resetErrorModal] = useOvpErrorModal({
|
||||
error: controller.error,
|
||||
noCredentialsMatchingVPRequest: controller.noCredentialsMatchingVPRequest,
|
||||
requestedClaimsByVerifier: controller.requestedClaimsByVerifier,
|
||||
getAdditionalMessage: controller.getAdditionalMessage,
|
||||
generateAndStoreLogMessage: controller.generateAndStoreLogMessage,
|
||||
t,
|
||||
});
|
||||
|
||||
const vcsMatchingAuthRequest = controller.vcsMatchingAuthRequest;
|
||||
|
||||
const {appService} = useContext(GlobalContext);
|
||||
const [triggerExitFlow, setTriggerExitFlow] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
if (controller.errorModal.show && controller.isOVPViaDeepLink) {
|
||||
if (errorModal.show && controller.isOVPViaDeepLink) {
|
||||
const timeout = setTimeout(
|
||||
() => {
|
||||
OpenID4VP.getInstance().sendErrorToVerifier(
|
||||
OpenID4VP.sendErrorToVerifier(
|
||||
OVP_ERROR_MESSAGES.NO_MATCHING_VCS,
|
||||
OVP_ERROR_CODE.NO_MATCHING_VCS,
|
||||
);
|
||||
@@ -58,11 +68,11 @@ export const SendVPScreen: React.FC<ScanLayoutProps> = props => {
|
||||
|
||||
return () => clearTimeout(timeout);
|
||||
}
|
||||
}, [controller.errorModal.show, controller.isOVPViaDeepLink]);
|
||||
}, [errorModal.show, controller.isOVPViaDeepLink]);
|
||||
|
||||
useEffect(() => {
|
||||
if (triggerExitFlow) {
|
||||
controller.RESET_LOGGED_ERROR();
|
||||
RESET_LOGGED_ERROR();
|
||||
controller.GO_TO_HOME();
|
||||
controller.RESET_RETRY_COUNT();
|
||||
appService.send(APP_EVENTS.RESET_AUTHORIZATION_REQUEST());
|
||||
@@ -106,11 +116,16 @@ export const SendVPScreen: React.FC<ScanLayoutProps> = props => {
|
||||
}
|
||||
});
|
||||
|
||||
const RESET_LOGGED_ERROR = () => {
|
||||
resetErrorModal();
|
||||
};
|
||||
|
||||
const handleDismiss = () => {
|
||||
OpenID4VP.getInstance().sendErrorToVerifier(
|
||||
OpenID4VP.sendErrorToVerifier(
|
||||
OVP_ERROR_MESSAGES.DECLINED,
|
||||
OVP_ERROR_CODE.DECLINED,
|
||||
);
|
||||
controller.generateAndStoreLogMessage('USER_DECLINED_CONSENT');
|
||||
if (controller.isOVPViaDeepLink) {
|
||||
controller.GO_TO_HOME();
|
||||
BackHandler.exitApp();
|
||||
@@ -120,10 +135,11 @@ export const SendVPScreen: React.FC<ScanLayoutProps> = props => {
|
||||
};
|
||||
|
||||
const handleRejectButtonEvent = () => {
|
||||
OpenID4VP.getInstance().sendErrorToVerifier(
|
||||
OpenID4VP.sendErrorToVerifier(
|
||||
OVP_ERROR_MESSAGES.DECLINED,
|
||||
OVP_ERROR_CODE.DECLINED,
|
||||
);
|
||||
controller.generateAndStoreLogMessage('USER_DECLINED_CONSENT');
|
||||
if (controller.isOVPViaDeepLink) {
|
||||
controller.GO_TO_HOME();
|
||||
BackHandler.exitApp();
|
||||
@@ -135,12 +151,9 @@ export const SendVPScreen: React.FC<ScanLayoutProps> = props => {
|
||||
const getAdditionalMessage = () => {
|
||||
if (
|
||||
controller.isOVPViaDeepLink &&
|
||||
!(
|
||||
controller.errorModal.showRetryButton &&
|
||||
controller.openID4VPRetryCount < 3
|
||||
)
|
||||
!(errorModal.showRetryButton && controller.openID4VPRetryCount < 3)
|
||||
) {
|
||||
return controller.errorModal.additionalMessage;
|
||||
return errorModal.additionalMessage;
|
||||
}
|
||||
return undefined;
|
||||
};
|
||||
@@ -209,7 +222,7 @@ export const SendVPScreen: React.FC<ScanLayoutProps> = props => {
|
||||
const getPrimaryButtonEvent = () => {
|
||||
if (controller.showConfirmationPopup && controller.isOVPViaDeepLink) {
|
||||
return () => {
|
||||
OpenID4VP.getInstance().sendErrorToVerifier(
|
||||
OpenID4VP.sendErrorToVerifier(
|
||||
OVP_ERROR_MESSAGES.DECLINED,
|
||||
OVP_ERROR_CODE.DECLINED,
|
||||
);
|
||||
@@ -221,8 +234,7 @@ export const SendVPScreen: React.FC<ScanLayoutProps> = props => {
|
||||
};
|
||||
|
||||
const getPrimaryButtonText = () => {
|
||||
return controller.errorModal.showRetryButton &&
|
||||
controller.openID4VPRetryCount < 3
|
||||
return errorModal.showRetryButton && controller.openID4VPRetryCount < 3
|
||||
? t('ScanScreen:status.retry')
|
||||
: undefined;
|
||||
};
|
||||
@@ -417,14 +429,14 @@ export const SendVPScreen: React.FC<ScanLayoutProps> = props => {
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
{controller.errorModal.show && (
|
||||
{errorModal.show && (
|
||||
<Error
|
||||
isModal
|
||||
alignActionsOnEnd
|
||||
showClose={false}
|
||||
isVisible={controller.errorModal.show}
|
||||
title={controller.errorModal.title}
|
||||
message={controller.errorModal.message}
|
||||
isVisible={errorModal.show}
|
||||
title={errorModal.title}
|
||||
message={errorModal.message}
|
||||
additionalMessage={getAdditionalMessage()}
|
||||
image={SvgImage.PermissionDenied()}
|
||||
primaryButtonTestID={'retry'}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import {NavigationProp, useNavigation} from '@react-navigation/native';
|
||||
import {useSelector} from '@xstate/react';
|
||||
import {useContext, useEffect, useRef, useState} from 'react';
|
||||
import {useCallback, useContext, useRef, useState} from 'react';
|
||||
import {useTranslation} from 'react-i18next';
|
||||
import {ActorRefFrom} from 'xstate';
|
||||
import {Theme} from '../../components/ui/styleUtils';
|
||||
@@ -151,208 +151,30 @@ export function useSendVPScreen() {
|
||||
selectIsOVPViaDeeplink,
|
||||
);
|
||||
|
||||
const getAdditionalMessage = () => {
|
||||
const getAdditionalMessage = useCallback(() => {
|
||||
return isOVPViaDeepLink && isIOS() ? t('errors.additionalMessage') : '';
|
||||
};
|
||||
}, [isOVPViaDeepLink, t]);
|
||||
|
||||
const generateAndStoreLogMessage = useCallback(
|
||||
(logType: string, errorInfo?: string) => {
|
||||
activityLogService.send(
|
||||
ActivityLogEvents.LOG_ACTIVITY(
|
||||
VPShareActivityLog.getLogFromObject({
|
||||
timestamp: Date.now(),
|
||||
type: logType,
|
||||
info: errorInfo,
|
||||
}),
|
||||
),
|
||||
);
|
||||
},
|
||||
[activityLogService],
|
||||
);
|
||||
|
||||
function generateAndStoreLogMessage(logType: string, errorInfo?: string) {
|
||||
activityLogService.send(
|
||||
ActivityLogEvents.LOG_ACTIVITY(
|
||||
VPShareActivityLog.getLogFromObject({
|
||||
timestamp: Date.now(),
|
||||
type: logType,
|
||||
info: errorInfo,
|
||||
}),
|
||||
),
|
||||
);
|
||||
}
|
||||
const requestedClaimsByVerifier = useSelector(
|
||||
openID4VPService,
|
||||
selectRequestedClaimsByVerifier,
|
||||
);
|
||||
|
||||
const [errorModal, setErrorModalData] = useState({
|
||||
show: false,
|
||||
title: '',
|
||||
message: '',
|
||||
additionalMessage: '',
|
||||
showRetryButton: false,
|
||||
});
|
||||
|
||||
const isClaimsEmpty =
|
||||
!requestedClaimsByVerifier || requestedClaimsByVerifier.trim() === '';
|
||||
if (noCredentialsMatchingVPRequest) {
|
||||
errorModal.title = isClaimsEmpty
|
||||
? t('errors.noMatchingCredentialsWithMissingClaims.title')
|
||||
: t('errors.noMatchingCredentials.title');
|
||||
errorModal.message = isClaimsEmpty
|
||||
? t('errors.noMatchingCredentialsWithMissingClaims.message')
|
||||
: t('errors.noMatchingCredentials.message', { claims: requestedClaimsByVerifier });
|
||||
generateAndStoreLogMessage(
|
||||
'NO_CREDENTIAL_MATCHING_REQUEST',
|
||||
requestedClaimsByVerifier,
|
||||
);
|
||||
} else if (
|
||||
error.includes('Verifier authentication was unsuccessful') ||
|
||||
error.startsWith('api error')
|
||||
) {
|
||||
errorModal.title = t('errors.invalidVerifier.title');
|
||||
errorModal.message = t('errors.invalidVerifier.message');
|
||||
generateAndStoreLogMessage('VERIFIER_AUTHENTICATION_FAILED');
|
||||
} else if (error.includes('credential mismatch detected')) {
|
||||
errorModal.title = t('errors.credentialsMismatch.title');
|
||||
errorModal.message = t('errors.credentialsMismatch.message', {
|
||||
claims: requestedClaimsByVerifier,
|
||||
});
|
||||
generateAndStoreLogMessage(
|
||||
'CREDENTIAL_MISMATCH_FROM_KEBAB',
|
||||
requestedClaimsByVerifier,
|
||||
);
|
||||
} else if (error.includes('none of the selected VC has image')) {
|
||||
errorModal.title = t('errors.noImage.title');
|
||||
errorModal.message = t('errors.noImage.message');
|
||||
generateAndStoreLogMessage('NO_SELECTED_VC_HAS_IMAGE');
|
||||
} else if (error.includes('invalid_request_uri_method')) {
|
||||
errorModal.title = t('errors.invalidRequestURI.title');
|
||||
errorModal.message = t('errors.invalidRequestURI.message');
|
||||
generateAndStoreLogMessage('INVALID_REQUEST_URI_METHOD');
|
||||
} else if (error.includes('invalid_request')) {
|
||||
errorModal.title = t('errors.invalidQrCode.title');
|
||||
errorModal.message = t('errors.invalidQrCode.message');
|
||||
generateAndStoreLogMessage('INVALID_AUTH_REQUEST');
|
||||
} else if (error.includes('vp_formats_not_supported')) {
|
||||
errorModal.title = t('errors.vpFormatsNotSupported.title');
|
||||
errorModal.message = t('errors.vpFormatsNotSupported.message');
|
||||
generateAndStoreLogMessage('VP_FORMATS_NOT_SUPPORTED');
|
||||
} else if (error.includes('invalid_presentation_definition_uri')) {
|
||||
errorModal.title = t('errors.invalidPresentationDefinitionURI.title');
|
||||
errorModal.message = t('errors.invalidPresentationDefinitionURI.message');
|
||||
generateAndStoreLogMessage('INVALID_PRESENTATION_DEFINITION_URI');
|
||||
} else if (error.includes('invalid_presentation_definition_reference')) {
|
||||
errorModal.title = t('errors.invalidPresentationDefinitionRef.title');
|
||||
errorModal.message = t('errors.invalidPresentationDefinitionRef.message');
|
||||
generateAndStoreLogMessage('INVALID_PRESENTATION_DEFINITION_REFERENCE');
|
||||
} else if (error.startsWith('send vp')) {
|
||||
errorModal.title = t('errors.sendVPError.title');
|
||||
errorModal.message = t('errors.sendVPError.message');
|
||||
errorModal.showRetryButton = true;
|
||||
} else if (error !== '') {
|
||||
errorModal.title = t('errors.genericError.title');
|
||||
errorModal.message = t('errors.genericError.message');
|
||||
generateAndStoreLogMessage('TECHNICAL_ERROR');
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (noCredentialsMatchingVPRequest && !hasLoggedErrorRef.current) {
|
||||
const isClaimsEmpty =
|
||||
!requestedClaimsByVerifier || requestedClaimsByVerifier.trim() === '';
|
||||
setErrorModalData({
|
||||
show: true,
|
||||
title: isClaimsEmpty
|
||||
? t('errors.noMatchingCredentialsWithMissingClaims.title')
|
||||
: t('errors.noMatchingCredentials.title'),
|
||||
message: isClaimsEmpty
|
||||
? t('errors.noMatchingCredentialsWithMissingClaims.message')
|
||||
: t('errors.noMatchingCredentials.message', {
|
||||
claims: requestedClaimsByVerifier,
|
||||
}),
|
||||
additionalMessage: getAdditionalMessage(),
|
||||
showRetryButton: false,
|
||||
});
|
||||
generateAndStoreLogMessage(
|
||||
'NO_CREDENTIAL_MATCHING_REQUEST',
|
||||
requestedClaimsByVerifier,
|
||||
);
|
||||
hasLoggedErrorRef.current = true;
|
||||
} else if (
|
||||
(error.includes('Verifier authentication was unsuccessful') ||
|
||||
error.startsWith('api error')) &&
|
||||
!hasLoggedErrorRef.current
|
||||
) {
|
||||
setErrorModalData({
|
||||
show: true,
|
||||
title: t('errors.invalidVerifier.title'),
|
||||
message: t('errors.invalidVerifier.message'),
|
||||
additionalMessage: getAdditionalMessage(),
|
||||
showRetryButton: false,
|
||||
});
|
||||
generateAndStoreLogMessage('VERIFIER_AUTHENTICATION_FAILED');
|
||||
hasLoggedErrorRef.current = true;
|
||||
} else if (
|
||||
error.includes('credential mismatch detected') &&
|
||||
!hasLoggedErrorRef.current
|
||||
) {
|
||||
setErrorModalData({
|
||||
show: true,
|
||||
title: t('errors.credentialsMismatch.title'),
|
||||
message: t('errors.credentialsMismatch.message', {
|
||||
claims: requestedClaimsByVerifier,
|
||||
}),
|
||||
additionalMessage: getAdditionalMessage(),
|
||||
showRetryButton: false,
|
||||
});
|
||||
generateAndStoreLogMessage(
|
||||
'CREDENTIAL_MISMATCH_FROM_KEBAB',
|
||||
requestedClaimsByVerifier,
|
||||
);
|
||||
hasLoggedErrorRef.current = true;
|
||||
} else if (
|
||||
error.includes('none of the selected VC has image') &&
|
||||
!hasLoggedErrorRef.current
|
||||
) {
|
||||
setErrorModalData({
|
||||
show: true,
|
||||
title: t('errors.noImage.title'),
|
||||
message: t('errors.noImage.message'),
|
||||
additionalMessage: getAdditionalMessage(),
|
||||
showRetryButton: false,
|
||||
});
|
||||
generateAndStoreLogMessage('NO_SELECTED_VC_HAS_IMAGE');
|
||||
hasLoggedErrorRef.current = true;
|
||||
} else if (
|
||||
error.startsWith('vc validation') &&
|
||||
!hasLoggedErrorRef.current
|
||||
) {
|
||||
setErrorModalData({
|
||||
show: true,
|
||||
title: t('errors.invalidQrCode.title'),
|
||||
message: t('errors.invalidQrCode.message'),
|
||||
additionalMessage: getAdditionalMessage(),
|
||||
showRetryButton: false,
|
||||
});
|
||||
generateAndStoreLogMessage('INVALID_AUTH_REQUEST');
|
||||
hasLoggedErrorRef.current = true;
|
||||
} else if (error.startsWith('send vp') && !hasLoggedErrorRef.current) {
|
||||
setErrorModalData({
|
||||
show: true,
|
||||
title: t('errors.genericError.title'),
|
||||
message: t('errors.genericError.message'),
|
||||
additionalMessage: getAdditionalMessage(),
|
||||
showRetryButton: true,
|
||||
});
|
||||
hasLoggedErrorRef.current = true;
|
||||
} else if (error !== '' && !hasLoggedErrorRef.current) {
|
||||
setErrorModalData({
|
||||
show: true,
|
||||
title: t('errors.genericError.title'),
|
||||
message: t('errors.genericError.message'),
|
||||
additionalMessage: getAdditionalMessage(),
|
||||
showRetryButton: false,
|
||||
});
|
||||
generateAndStoreLogMessage('TECHNICAL_ERROR');
|
||||
hasLoggedErrorRef.current = true;
|
||||
} else if (error === '') {
|
||||
setErrorModalData({
|
||||
show: false,
|
||||
title: '',
|
||||
message: '',
|
||||
additionalMessage: '',
|
||||
showRetryButton: false,
|
||||
});
|
||||
hasLoggedErrorRef.current = false;
|
||||
}
|
||||
}, [error, noCredentialsMatchingVPRequest]);
|
||||
|
||||
let overlayDetails: Omit<VPShareOverlayProps, 'isVisible'> | null = null;
|
||||
let vpVerifierName = useSelector(
|
||||
openID4VPService,
|
||||
@@ -401,18 +223,12 @@ export function useSendVPScreen() {
|
||||
checkIfAnyVCHasImage,
|
||||
checkIfAllVCsHasImage,
|
||||
getSelectedVCs,
|
||||
errorModal,
|
||||
error,
|
||||
noCredentialsMatchingVPRequest,
|
||||
requestedClaimsByVerifier,
|
||||
getAdditionalMessage,
|
||||
overlayDetails,
|
||||
RESET_LOGGED_ERROR: () => {
|
||||
hasLoggedErrorRef.current = false;
|
||||
setErrorModalData({
|
||||
show: false,
|
||||
title: '',
|
||||
message: '',
|
||||
additionalMessage: '',
|
||||
showRetryButton: false,
|
||||
});
|
||||
},
|
||||
generateAndStoreLogMessage,
|
||||
scanScreenError: useSelector(scanService, selectIsSendingVPError),
|
||||
vcsMatchingAuthRequest,
|
||||
userSelectedVCs: useSelector(openID4VPService, selectSelectedVCs),
|
||||
|
||||
@@ -19,5 +19,6 @@ export const INITIAL_CONFIG = {
|
||||
faceSdkModelUrl: '',
|
||||
openId4VCIDownloadVCTimeout: '30000',
|
||||
cacheTTLInMilliSeconds: '3600000',
|
||||
disableCredentialOfferVcVerification: false
|
||||
},
|
||||
};
|
||||
|
||||
@@ -129,7 +129,7 @@ export function parseMetadatas(metadataStrings: object[]) {
|
||||
}
|
||||
|
||||
export const getVCMetadata = (context: object, keyType: string) => {
|
||||
const issuer = context.selectedIssuer.credential_issuer;
|
||||
const issuer = context.selectedIssuer.credential_issuer_host ?? context.selectedIssuer.credential_issuer;
|
||||
const credentialId = `${UUID.generate()}_${issuer}`;
|
||||
|
||||
return VCMetadata.fromVC({
|
||||
@@ -147,7 +147,7 @@ export const getVCMetadata = (context: object, keyType: string) => {
|
||||
format: context['credentialWrapper'].format,
|
||||
downloadKeyType: keyType,
|
||||
credentialType: getCredentialType(context.selectedCredentialType),
|
||||
issuerHost: context.selectedIssuer.credential_issuer_host ?? context.selectedIssuer.credential_issuer,
|
||||
issuerHost: issuer
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
@@ -155,6 +155,7 @@ export type IndividualId = {
|
||||
|
||||
export const TECHNICAL_ERROR = 'Technical error';
|
||||
export const NETWORK_REQUEST_FAILED = 'Network request failed';
|
||||
export const NO_INTERNET = 'No internet connection';
|
||||
export const IOS_SIGNIN_FAILED = 'iCloud not available';
|
||||
export const REQUEST_TIMEOUT = 'request timeout';
|
||||
export const BIOMETRIC_CANCELLED = 'User has cancelled biometric';
|
||||
|
||||
193
shared/hooks/useOvpErrorModal.ts
Normal file
193
shared/hooks/useOvpErrorModal.ts
Normal file
@@ -0,0 +1,193 @@
|
||||
import {useEffect, useState} from 'react';
|
||||
|
||||
interface OvpErrorModal {
|
||||
show: boolean;
|
||||
title: string;
|
||||
message: string;
|
||||
additionalMessage: string;
|
||||
showRetryButton: boolean;
|
||||
}
|
||||
|
||||
interface UseOvpErrorModalProps {
|
||||
error: string;
|
||||
noCredentialsMatchingVPRequest: boolean;
|
||||
requestedClaimsByVerifier: string;
|
||||
getAdditionalMessage: () => string;
|
||||
generateAndStoreLogMessage: (logType: string, errorInfo?: string) => void;
|
||||
t: (key: string, options?: any) => string;
|
||||
}
|
||||
export function useOvpErrorModal({
|
||||
error,
|
||||
noCredentialsMatchingVPRequest,
|
||||
requestedClaimsByVerifier,
|
||||
getAdditionalMessage,
|
||||
generateAndStoreLogMessage,
|
||||
t,
|
||||
}: UseOvpErrorModalProps): [OvpErrorModal, () => void] {
|
||||
const [errorModal, setErrorModal] = useState<OvpErrorModal>({
|
||||
show: false,
|
||||
title: '',
|
||||
message: '',
|
||||
additionalMessage: '',
|
||||
showRetryButton: false,
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
const isClaimsEmpty =
|
||||
!requestedClaimsByVerifier || requestedClaimsByVerifier.trim() === '';
|
||||
const additionalMessage = getAdditionalMessage();
|
||||
|
||||
if (noCredentialsMatchingVPRequest) {
|
||||
setErrorModal({
|
||||
show: true,
|
||||
title: isClaimsEmpty
|
||||
? t('errors.noMatchingCredentialsWithMissingClaims.title')
|
||||
: t('errors.noMatchingCredentials.title'),
|
||||
message: isClaimsEmpty
|
||||
? t('errors.noMatchingCredentialsWithMissingClaims.message')
|
||||
: t('errors.noMatchingCredentials.message', {
|
||||
claims: requestedClaimsByVerifier,
|
||||
}),
|
||||
additionalMessage,
|
||||
showRetryButton: false,
|
||||
});
|
||||
generateAndStoreLogMessage(
|
||||
'NO_CREDENTIAL_MATCHING_REQUEST',
|
||||
requestedClaimsByVerifier,
|
||||
);
|
||||
} else if (
|
||||
error.includes('Verifier authentication was unsuccessful') ||
|
||||
error.startsWith('api error')
|
||||
) {
|
||||
setErrorModal({
|
||||
show: true,
|
||||
title: t('errors.invalidVerifier.title'),
|
||||
message: t('errors.invalidVerifier.message'),
|
||||
additionalMessage,
|
||||
showRetryButton: false,
|
||||
});
|
||||
generateAndStoreLogMessage('VERIFIER_AUTHENTICATION_FAILED');
|
||||
} else if (error.includes('credential mismatch detected')) {
|
||||
setErrorModal({
|
||||
show: true,
|
||||
title: t('errors.credentialsMismatch.title'),
|
||||
message: t('errors.credentialsMismatch.message', {
|
||||
claims: requestedClaimsByVerifier,
|
||||
}),
|
||||
additionalMessage,
|
||||
showRetryButton: false,
|
||||
});
|
||||
generateAndStoreLogMessage(
|
||||
'CREDENTIAL_MISMATCH_FROM_KEBAB',
|
||||
requestedClaimsByVerifier,
|
||||
);
|
||||
} else if (error.includes('none of the selected VC has image')) {
|
||||
setErrorModal({
|
||||
show: true,
|
||||
title: t('errors.noImage.title'),
|
||||
message: t('errors.noImage.message'),
|
||||
additionalMessage,
|
||||
showRetryButton: false,
|
||||
});
|
||||
generateAndStoreLogMessage('NO_SELECTED_VC_HAS_IMAGE');
|
||||
} else if (error.includes('invalid_request_uri_method')) {
|
||||
setErrorModal({
|
||||
show: true,
|
||||
title: t('errors.invalidRequestURI.title'),
|
||||
message: t('errors.invalidRequestURI.message'),
|
||||
additionalMessage,
|
||||
showRetryButton: false,
|
||||
});
|
||||
generateAndStoreLogMessage('INVALID_REQUEST_URI_METHOD');
|
||||
} else if (error.includes('invalid_request')) {
|
||||
setErrorModal({
|
||||
show: true,
|
||||
title: t('errors.invalidQrCode.title'),
|
||||
message: t('errors.invalidQrCode.message'),
|
||||
additionalMessage,
|
||||
showRetryButton: false,
|
||||
});
|
||||
generateAndStoreLogMessage('INVALID_AUTH_REQUEST');
|
||||
} else if (error.includes('vp_formats_not_supported')) {
|
||||
setErrorModal({
|
||||
show: true,
|
||||
title: t('errors.vpFormatsNotSupported.title'),
|
||||
message: t('errors.vpFormatsNotSupported.message'),
|
||||
additionalMessage,
|
||||
showRetryButton: false,
|
||||
});
|
||||
generateAndStoreLogMessage('REQUEST_COULD_NOT_BE_PROCESSED');
|
||||
} else if (error.includes('invalid_presentation_definition_uri')) {
|
||||
setErrorModal({
|
||||
show: true,
|
||||
title: t('errors.invalidPresentationDefinitionURI.title'),
|
||||
message: t('errors.invalidPresentationDefinitionURI.message'),
|
||||
additionalMessage,
|
||||
showRetryButton: false,
|
||||
});
|
||||
generateAndStoreLogMessage('INVALID_PRESENTATION_DEFINITION_URI');
|
||||
} else if (error.includes('invalid_presentation_definition_reference')) {
|
||||
setErrorModal({
|
||||
show: true,
|
||||
title: t('errors.invalidPresentationDefinitionRef.title'),
|
||||
message: t('errors.invalidPresentationDefinitionRef.message'),
|
||||
additionalMessage,
|
||||
showRetryButton: false,
|
||||
});
|
||||
generateAndStoreLogMessage('REQUEST_COULD_NOT_BE_PROCESSED');
|
||||
} else if (error.includes('invalid_client')) {
|
||||
setErrorModal({
|
||||
show: true,
|
||||
title: t('errors.invalidQrCode.title'),
|
||||
message: t('errors.invalidQrCode.message'),
|
||||
additionalMessage,
|
||||
showRetryButton: false,
|
||||
});
|
||||
generateAndStoreLogMessage('REQUEST_COULD_NOT_BE_PROCESSED');
|
||||
} else if (error.startsWith('send vp')) {
|
||||
setErrorModal({
|
||||
show: true,
|
||||
title: t('errors.sendVPError.title'),
|
||||
message: t('errors.sendVPError.message'),
|
||||
additionalMessage,
|
||||
showRetryButton: true,
|
||||
});
|
||||
generateAndStoreLogMessage('SEND_VP_ERROR');
|
||||
} else if (error !== '') {
|
||||
setErrorModal({
|
||||
show: true,
|
||||
title: t('errors.genericError.title'),
|
||||
message: t('errors.genericError.message'),
|
||||
additionalMessage,
|
||||
showRetryButton: false,
|
||||
});
|
||||
generateAndStoreLogMessage('TECHNICAL_ERROR');
|
||||
} else {
|
||||
setErrorModal({
|
||||
show: false,
|
||||
title: '',
|
||||
message: '',
|
||||
additionalMessage: '',
|
||||
showRetryButton: false,
|
||||
});
|
||||
}
|
||||
}, [
|
||||
error,
|
||||
noCredentialsMatchingVPRequest,
|
||||
requestedClaimsByVerifier,
|
||||
getAdditionalMessage,
|
||||
t,
|
||||
]);
|
||||
|
||||
const resetErrorModal = () => {
|
||||
setErrorModal({
|
||||
show: false,
|
||||
title: '',
|
||||
message: '',
|
||||
additionalMessage: '',
|
||||
showRetryButton: false,
|
||||
});
|
||||
};
|
||||
|
||||
return [errorModal, resetErrorModal];
|
||||
}
|
||||
@@ -4,7 +4,7 @@ import {
|
||||
SelectedCredentialsForVPSharing,
|
||||
VC,
|
||||
} from '../../machines/VerifiableCredential/VCMetaMachine/vc';
|
||||
import {walletMetadata} from './walletMetadata';
|
||||
import {fallbackWalletMetadata} from './fallbackWalletMetadata';
|
||||
import {getWalletMetadata, isClientValidationRequired} from './OpenID4VPHelper';
|
||||
import {parseJSON} from '../Utils';
|
||||
|
||||
@@ -14,58 +14,66 @@ class OpenID4VP {
|
||||
private static instance: OpenID4VP;
|
||||
private InjiOpenID4VP = NativeModules.InjiOpenID4VP;
|
||||
|
||||
private constructor() {
|
||||
this.InjiOpenID4VP.init(__AppId.getValue());
|
||||
private constructor(walletMetadata: any) {
|
||||
this.InjiOpenID4VP.initSdk(__AppId.getValue(), walletMetadata);
|
||||
}
|
||||
|
||||
public static getInstance(): OpenID4VP {
|
||||
private static async getInstance(): Promise<OpenID4VP> {
|
||||
if (!OpenID4VP.instance) {
|
||||
OpenID4VP.instance = new OpenID4VP();
|
||||
const walletMetadata =
|
||||
(await getWalletMetadata()) || fallbackWalletMetadata;
|
||||
OpenID4VP.instance = new OpenID4VP(walletMetadata);
|
||||
}
|
||||
return OpenID4VP.instance;
|
||||
}
|
||||
|
||||
async authenticateVerifier(
|
||||
static async authenticateVerifier(
|
||||
urlEncodedAuthorizationRequest: string,
|
||||
trustedVerifiersList: any,
|
||||
) {
|
||||
const shouldValidateClient = await isClientValidationRequired();
|
||||
const metadata = (await getWalletMetadata()) || walletMetadata;
|
||||
const openID4VP = await OpenID4VP.getInstance();
|
||||
|
||||
const authenticationResponse =
|
||||
await this.InjiOpenID4VP.authenticateVerifier(
|
||||
await openID4VP.InjiOpenID4VP.authenticateVerifier(
|
||||
urlEncodedAuthorizationRequest,
|
||||
trustedVerifiersList,
|
||||
metadata,
|
||||
shouldValidateClient,
|
||||
);
|
||||
return JSON.parse(authenticationResponse);
|
||||
}
|
||||
|
||||
async constructUnsignedVPToken(
|
||||
static async constructUnsignedVPToken(
|
||||
selectedVCs: Record<string, VC[]>,
|
||||
holderId: string,
|
||||
signatureAlgorithm: string,
|
||||
) {
|
||||
const updatedSelectedVCs = this.processSelectedVCs(selectedVCs);
|
||||
const unSignedVpTokens = await this.InjiOpenID4VP.constructUnsignedVPToken(
|
||||
updatedSelectedVCs,
|
||||
holderId,
|
||||
signatureAlgorithm,
|
||||
);
|
||||
const openID4VP = await OpenID4VP.getInstance();
|
||||
|
||||
const updatedSelectedVCs = openID4VP.processSelectedVCs(selectedVCs);
|
||||
const unSignedVpTokens =
|
||||
await openID4VP.InjiOpenID4VP.constructUnsignedVPToken(
|
||||
updatedSelectedVCs,
|
||||
holderId,
|
||||
signatureAlgorithm,
|
||||
);
|
||||
return parseJSON(unSignedVpTokens);
|
||||
}
|
||||
|
||||
async shareVerifiablePresentation(
|
||||
static async shareVerifiablePresentation(
|
||||
vpTokenSigningResultMap: Record<string, any>,
|
||||
) {
|
||||
return await this.InjiOpenID4VP.shareVerifiablePresentation(
|
||||
const openID4VP = await OpenID4VP.getInstance();
|
||||
|
||||
return await openID4VP.InjiOpenID4VP.shareVerifiablePresentation(
|
||||
vpTokenSigningResultMap,
|
||||
);
|
||||
}
|
||||
|
||||
sendErrorToVerifier(errorMessage: string, errorCode: string) {
|
||||
this.InjiOpenID4VP.sendErrorToVerifier(errorMessage, errorCode);
|
||||
static sendErrorToVerifier(errorMessage: string, errorCode: string) {
|
||||
OpenID4VP.getInstance().then(openID4VP => {
|
||||
openID4VP.InjiOpenID4VP.sendErrorToVerifier(errorMessage, errorCode);
|
||||
});
|
||||
}
|
||||
|
||||
private processSelectedVCs(selectedVCs: Record<string, VC[]>) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
export const walletMetadata = {
|
||||
presentation_definition_uri_supported: true,
|
||||
export const fallbackWalletMetadata = {
|
||||
presentation_definition_uri_supported: false,
|
||||
vp_formats_supported: {
|
||||
ldp_vc: {
|
||||
alg_values_supported: [
|
||||
@@ -1,6 +1,5 @@
|
||||
import base64url from 'base64url';
|
||||
import i18next from 'i18next';
|
||||
import jwtDecode from 'jwt-decode';
|
||||
import jose from 'node-jose';
|
||||
import {NativeModules} from 'react-native';
|
||||
import {vcVerificationBannerDetails} from '../../components/BannerNotificationContainer';
|
||||
@@ -10,11 +9,9 @@ import {
|
||||
DETAIL_VIEW_ADD_ON_FIELDS,
|
||||
getCredentialTypeFromWellKnown,
|
||||
} from '../../components/VC/common/VCUtils';
|
||||
import i18n from '../../i18n';
|
||||
import {displayType, issuerType} from '../../machines/Issuers/IssuersMachine';
|
||||
import {displayType} from '../../machines/Issuers/IssuersMachine';
|
||||
import {
|
||||
Credential,
|
||||
CredentialTypes,
|
||||
CredentialWrapper,
|
||||
VerifiableCredential,
|
||||
} from '../../machines/VerifiableCredential/VCMetaMachine/vc';
|
||||
@@ -22,16 +19,11 @@ import getAllConfigurations, {CACHED_API} from '../api';
|
||||
import {
|
||||
ED25519_PROOF_SIGNING_ALGO,
|
||||
isAndroid,
|
||||
isIOS,
|
||||
JWT_ALG_TO_KEY_TYPE,
|
||||
KEY_TYPE_TO_JWT_ALG,
|
||||
} from '../constants';
|
||||
import {getJWT} from '../cryptoutil/cryptoUtil';
|
||||
import {
|
||||
VerificationErrorMessage,
|
||||
VerificationErrorType,
|
||||
verifyCredential,
|
||||
} from '../vcjs/verifyCredential';
|
||||
import {verifyCredential} from '../vcjs/verifyCredential';
|
||||
import {getVerifiableCredential} from '../../machines/VerifiableCredential/VCItemMachine/VCItemSelectors';
|
||||
import {getErrorEventData, sendErrorEvent} from '../telemetry/TelemetryUtils';
|
||||
import {TelemetryConstants} from '../telemetry/TelemetryConstants';
|
||||
@@ -268,22 +260,21 @@ export enum ErrorMessage {
|
||||
TECHNICAL_DIFFICULTIES = 'technicalDifficulty',
|
||||
CREDENTIAL_TYPE_DOWNLOAD_FAILURE = 'credentialTypeListDownloadFailure',
|
||||
AUTHORIZATION_GRANT_TYPE_NOT_SUPPORTED = 'authorizationGrantTypeNotSupportedByWallet',
|
||||
NETWORK_REQUEST_FAILED = 'networkRequestFailed',
|
||||
}
|
||||
|
||||
export async function constructProofJWT(
|
||||
publicKey: any,
|
||||
privateKey: any,
|
||||
accessToken: string,
|
||||
selectedIssuer: issuerType,
|
||||
selectedIssuer: string,
|
||||
client_id: string | null,
|
||||
keyType: string,
|
||||
proofSigningAlgosSupported: string[] = [],
|
||||
isCredentialOfferFlow: boolean,
|
||||
cNonce?: string,
|
||||
): Promise<string> {
|
||||
const jwk = await getJWK(publicKey, keyType);
|
||||
const decodedToken = jwtDecode(accessToken);
|
||||
const nonce = cNonce ?? decodedToken?.c_nonce;
|
||||
|
||||
const nonce = cNonce;
|
||||
const alg =
|
||||
keyType === KeyTypes.ED25519
|
||||
? resolveEd25519Alg(proofSigningAlgosSupported)
|
||||
@@ -302,9 +293,9 @@ export async function constructProofJWT(
|
||||
};
|
||||
|
||||
const jwtPayload = {
|
||||
iss: selectedIssuer.client_id,
|
||||
...(client_id ? {iss: client_id} : {}),
|
||||
nonce,
|
||||
aud: selectedIssuer.credential_audience ?? selectedIssuer.credential_issuer,
|
||||
aud: selectedIssuer,
|
||||
iat: Math.floor(Date.now() / 1000),
|
||||
exp: Math.floor(Date.now() / 1000) + 18000,
|
||||
};
|
||||
@@ -410,38 +401,9 @@ export function selectCredentialRequestKey(
|
||||
return keyType;
|
||||
}
|
||||
}
|
||||
|
||||
return KeyTypes.ED25519;
|
||||
return keyOrder[0];
|
||||
}
|
||||
|
||||
export const constructIssuerMetaData = (
|
||||
selectedIssuer: issuerType,
|
||||
selectedCredentialType: CredentialTypes,
|
||||
scope: string,
|
||||
): Object => {
|
||||
const issuerMeta: Object = {
|
||||
credentialAudience: selectedIssuer.credential_audience,
|
||||
credentialEndpoint: selectedIssuer.credential_endpoint,
|
||||
credentialFormat: isIOS()
|
||||
? selectedCredentialType.format
|
||||
: selectedCredentialType.format.toUpperCase(),
|
||||
authorizationServers: selectedIssuer['authorization_servers'],
|
||||
tokenEndpoint: selectedIssuer.token_endpoint,
|
||||
scope: scope,
|
||||
};
|
||||
if (selectedCredentialType.format === VCFormat.ldp_vc) {
|
||||
issuerMeta['credentialType'] = selectedCredentialType?.credential_definition
|
||||
?.type ?? ['VerifiableCredential'];
|
||||
if (selectedCredentialType?.credential_definition['@context'])
|
||||
issuerMeta['context'] =
|
||||
selectedCredentialType?.credential_definition['@context'];
|
||||
} else if (selectedCredentialType.format === VCFormat.mso_mdoc) {
|
||||
issuerMeta['doctype'] = selectedCredentialType.doctype;
|
||||
issuerMeta['claims'] = selectedCredentialType.claims;
|
||||
}
|
||||
return issuerMeta;
|
||||
};
|
||||
|
||||
export function getMatchingCredentialIssuerMetadata(
|
||||
wellknown: any,
|
||||
credentialConfigurationId: string,
|
||||
@@ -470,11 +432,11 @@ export async function verifyCredentialData(
|
||||
credential: Credential,
|
||||
credentialFormat: string,
|
||||
) {
|
||||
const verificationResult = await verifyCredential(
|
||||
credential,
|
||||
credentialFormat,
|
||||
);
|
||||
return verificationResult;
|
||||
const verificationResult = await verifyCredential(
|
||||
credential,
|
||||
credentialFormat,
|
||||
);
|
||||
return verificationResult;
|
||||
}
|
||||
function resolveEd25519Alg(proofSigningAlgosSupported: string[]) {
|
||||
return proofSigningAlgosSupported.includes(
|
||||
|
||||
@@ -4,6 +4,8 @@ import {
|
||||
} from '../machines/VerifiableCredential/VCMetaMachine/vc';
|
||||
import {__AppId} from './GlobalVariables';
|
||||
import {MIMOTO_BASE_URL, REQUEST_TIMEOUT} from './constants';
|
||||
import NetInfo from '@react-native-community/netinfo';
|
||||
import { ErrorMessage } from './openId4VCI/Utils';
|
||||
|
||||
export type HTTP_METHOD = 'GET' | 'POST' | 'PATCH' | 'PUT' | 'DELETE';
|
||||
|
||||
@@ -14,6 +16,14 @@ export class BackendResponseError extends Error {
|
||||
}
|
||||
}
|
||||
|
||||
async function assertInternetConnection() {
|
||||
const net = await NetInfo.fetch();
|
||||
if (!net.isConnected || net.isInternetReachable === false) {
|
||||
console.info('No internet');
|
||||
throw new Error('No internet connection');
|
||||
}
|
||||
}
|
||||
|
||||
export async function request(
|
||||
method: HTTP_METHOD,
|
||||
path: `/${string}` | string,
|
||||
@@ -22,66 +32,81 @@ export async function request(
|
||||
headers: Record<string, string> = {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
timeoutMillis?: undefined | number,
|
||||
timeoutMillis?: number | undefined,
|
||||
) {
|
||||
if (path.includes('v1/mimoto')) headers['X-AppId'] = __AppId.getValue();
|
||||
if (path.includes('v1/mimoto')) {
|
||||
headers['X-AppId'] = __AppId.getValue();
|
||||
}
|
||||
|
||||
const requestUrl = path.startsWith('https://') ? path : host + path;
|
||||
let response;
|
||||
const requestUrl = path.indexOf('https://') != -1 ? path : host + path;
|
||||
if (timeoutMillis === undefined) {
|
||||
response = await fetch(requestUrl, {
|
||||
method,
|
||||
headers,
|
||||
body: body ? JSON.stringify(body) : undefined,
|
||||
});
|
||||
} else {
|
||||
console.log(`making a web request to ${requestUrl}`);
|
||||
let controller = new AbortController();
|
||||
setTimeout(() => {
|
||||
controller.abort();
|
||||
}, timeoutMillis);
|
||||
try {
|
||||
|
||||
try {
|
||||
if (timeoutMillis === undefined) {
|
||||
response = await fetch(requestUrl, {
|
||||
method,
|
||||
headers,
|
||||
body: body ? JSON.stringify(body) : undefined,
|
||||
signal: controller.signal,
|
||||
});
|
||||
} catch (error) {
|
||||
console.error(
|
||||
`Error occurred while making request: ${host + path}: ${error}`,
|
||||
);
|
||||
if (error.name === 'AbortError') {
|
||||
throw new Error(REQUEST_TIMEOUT);
|
||||
} else {
|
||||
console.info(`Making a web request to ${requestUrl}`);
|
||||
const controller = new AbortController();
|
||||
const timeoutId = setTimeout(() => controller.abort(), timeoutMillis);
|
||||
|
||||
try {
|
||||
response = await fetch(requestUrl, {
|
||||
method,
|
||||
headers,
|
||||
body: body ? JSON.stringify(body) : undefined,
|
||||
signal: controller.signal,
|
||||
});
|
||||
} catch (error: any) {
|
||||
clearTimeout(timeoutId);
|
||||
console.error(`Request failed: ${requestUrl}:`, error);
|
||||
|
||||
if (error.name === 'AbortError') {
|
||||
throw new Error(REQUEST_TIMEOUT);
|
||||
}
|
||||
|
||||
await assertInternetConnection();
|
||||
throw error;
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
} catch (error: any) {
|
||||
console.error(`Failed to fetch from ${requestUrl}:`, error);
|
||||
await assertInternetConnection();
|
||||
throw error;
|
||||
}
|
||||
|
||||
|
||||
let jsonResponse;
|
||||
try {
|
||||
jsonResponse = await response.json();
|
||||
} catch (jsonError) {
|
||||
console.warn(`Failed to parse JSON from ${requestUrl}`, jsonError);
|
||||
throw new Error(ErrorMessage.NETWORK_REQUEST_FAILED+' Invalid JSON response');
|
||||
}
|
||||
|
||||
const jsonResponse = await response.json();
|
||||
|
||||
if (response.status >= 400) {
|
||||
let backendUrl = host + path;
|
||||
let errorMessage =
|
||||
const backendUrl = host + path;
|
||||
const errorMessage =
|
||||
jsonResponse.message ||
|
||||
(typeof jsonResponse.error === 'object'
|
||||
? JSON.stringify(jsonResponse.error)
|
||||
: jsonResponse.error);
|
||||
|
||||
console.error(
|
||||
`The backend API ${backendUrl} returned error code ${response.status} with message --> ${errorMessage}`,
|
||||
);
|
||||
throw new Error(errorMessage);
|
||||
}
|
||||
|
||||
|
||||
if (jsonResponse.errors && jsonResponse.errors.length) {
|
||||
let backendUrl = host + path;
|
||||
const {errorCode, errorMessage} = jsonResponse.errors.shift();
|
||||
const { errorCode, errorMessage } = jsonResponse.errors.shift();
|
||||
console.error(
|
||||
'The backend API ' +
|
||||
backendUrl +
|
||||
' returned error response --> error code is : ' +
|
||||
errorCode +
|
||||
' error message is : ' +
|
||||
errorMessage,
|
||||
`The backend API ${requestUrl} returned structured error --> error code: ${errorCode}, message: ${errorMessage}`,
|
||||
);
|
||||
throw new BackendResponseError(errorCode, errorMessage);
|
||||
}
|
||||
|
||||
@@ -35,6 +35,15 @@ class VciClient {
|
||||
this.InjiVciClient.sendIssuerTrustResponseFromJS(consent);
|
||||
}
|
||||
|
||||
async sendTokenResponse(json: string) {
|
||||
this.InjiVciClient.sendTokenResponseFromJS(json);
|
||||
}
|
||||
|
||||
async getIssuerMetadata(issuerUri: string): Promise<object> {
|
||||
const response = await this.InjiVciClient.getIssuerMetadata(issuerUri);
|
||||
return JSON.parse(response);
|
||||
}
|
||||
|
||||
async requestCredentialByOffer(
|
||||
credentialOffer: string,
|
||||
getTxCode: (
|
||||
@@ -43,30 +52,29 @@ class VciClient {
|
||||
length: number | undefined,
|
||||
) => void,
|
||||
getProofJwt: (
|
||||
accessToken: string,
|
||||
credentialIssuer: string,
|
||||
cNonce: string | null,
|
||||
issuerMetadata: object,
|
||||
credentialConfigurationId: string,
|
||||
proofSigningAlgosSupported: string[] | null,
|
||||
) => void,
|
||||
navigateToAuthView: (authorizationEndpoint: string) => void,
|
||||
requestTrustIssuerConsent: (issuerMetadata: object) => void,
|
||||
): Promise<VerifiableCredential> {
|
||||
requestTokenResponse: (tokenRequest: object) => void,
|
||||
requestTrustIssuerConsent: (
|
||||
credentialIssuer: string,
|
||||
issuerDisplay: object[],
|
||||
) => void,
|
||||
): Promise<any> {
|
||||
|
||||
const proofListener = emitter.addListener(
|
||||
'onRequestProof',
|
||||
({accessToken, cNonce, issuerMetadata, credentialConfigurationId}) => {
|
||||
getProofJwt(
|
||||
accessToken,
|
||||
cNonce,
|
||||
JSON.parse(issuerMetadata),
|
||||
credentialConfigurationId,
|
||||
);
|
||||
({credentialIssuer, cNonce, proofSigningAlgorithmsSupported}) => {
|
||||
getProofJwt(credentialIssuer, cNonce, JSON.parse(proofSigningAlgorithmsSupported));
|
||||
},
|
||||
);
|
||||
|
||||
const authListener = emitter.addListener(
|
||||
'onRequestAuthCode',
|
||||
({authorizationEndpoint}) => {
|
||||
navigateToAuthView(authorizationEndpoint);
|
||||
({authorizationUrl}) => {
|
||||
navigateToAuthView(authorizationUrl);
|
||||
},
|
||||
);
|
||||
|
||||
@@ -77,21 +85,29 @@ class VciClient {
|
||||
},
|
||||
);
|
||||
|
||||
const tokenResponseListener = emitter.addListener(
|
||||
'onRequestTokenResponse',
|
||||
({tokenRequest}) => {
|
||||
requestTokenResponse(tokenRequest);
|
||||
},
|
||||
);
|
||||
|
||||
const trustIssuerListener = emitter.addListener(
|
||||
'onCheckIssuerTrust',
|
||||
({issuerMetadata}) => {
|
||||
requestTrustIssuerConsent(JSON.parse(issuerMetadata));
|
||||
({credentialIssuer, issuerDisplay}) => {
|
||||
requestTrustIssuerConsent(credentialIssuer, JSON.parse(issuerDisplay));
|
||||
},
|
||||
);
|
||||
|
||||
let response = '';
|
||||
try {
|
||||
const clientMetadata = {
|
||||
clientId: 'wallet',
|
||||
redirectUri: 'io.mosip.residentapp.inji://oauthredirect',
|
||||
};
|
||||
response = await this.InjiVciClient.requestCredentialByOffer(
|
||||
credentialOffer,
|
||||
JSON.stringify({
|
||||
clientId: 'wallet',
|
||||
redirectUri: 'io.mosip.residentapp.inji://oauthredirect',
|
||||
}),
|
||||
JSON.stringify(clientMetadata),
|
||||
);
|
||||
} catch (error) {
|
||||
console.error('Error requesting credential by offer:', error);
|
||||
@@ -100,37 +116,59 @@ class VciClient {
|
||||
proofListener.remove();
|
||||
authListener.remove();
|
||||
txCodeListener.remove();
|
||||
tokenResponseListener.remove();
|
||||
trustIssuerListener.remove();
|
||||
}
|
||||
|
||||
return JSON.parse(response) as VerifiableCredential;
|
||||
const parsedResponse = JSON.parse(response);
|
||||
return {
|
||||
credential: {
|
||||
credential: parsedResponse.credential,
|
||||
} as VerifiableCredential,
|
||||
credentialConfigurationId:
|
||||
parsedResponse.credentialConfigurationId ?? {},
|
||||
credentialIssuer: parsedResponse.credentialIssuer ?? '',
|
||||
};
|
||||
}
|
||||
|
||||
async requestCredentialFromTrustedIssuer(
|
||||
resolvedIssuerMetaData: object,
|
||||
credentialIssuerUri: string,
|
||||
credentialConfigurationId: string,
|
||||
clientMetadata: object,
|
||||
getProofJwt: (accessToken: string, cNonce: string) => void,
|
||||
getProofJwt: (
|
||||
credentialIssuer: string,
|
||||
cNonce: string | null,
|
||||
proofSigningAlgosSupported: string[] | null,
|
||||
) => void,
|
||||
navigateToAuthView: (authorizationEndpoint: string) => void,
|
||||
): Promise<VerifiableCredential> {
|
||||
requestTokenResponse: (tokenRequest: object) => void,
|
||||
): Promise<any> {
|
||||
const proofListener = emitter.addListener(
|
||||
'onRequestProof',
|
||||
({accessToken, cNonce}) => {
|
||||
getProofJwt(accessToken, cNonce);
|
||||
proofListener.remove();
|
||||
({credentialIssuer, cNonce, proofSigningAlgorithmsSupported}) => {
|
||||
getProofJwt(credentialIssuer, cNonce, JSON.parse(proofSigningAlgorithmsSupported));
|
||||
},
|
||||
);
|
||||
|
||||
const authListener = emitter.addListener(
|
||||
'onRequestAuthCode',
|
||||
({authorizationEndpoint}) => {
|
||||
navigateToAuthView(authorizationEndpoint);
|
||||
({authorizationUrl}) => {
|
||||
navigateToAuthView(authorizationUrl);
|
||||
},
|
||||
);
|
||||
|
||||
const tokenResponseListener = emitter.addListener(
|
||||
'onRequestTokenResponse',
|
||||
({tokenRequest}) => {
|
||||
requestTokenResponse(tokenRequest);
|
||||
},
|
||||
);
|
||||
|
||||
let response = '';
|
||||
try {
|
||||
response = await this.InjiVciClient.requestCredentialFromTrustedIssuer(
|
||||
JSON.stringify(resolvedIssuerMetaData),
|
||||
credentialIssuerUri,
|
||||
credentialConfigurationId,
|
||||
JSON.stringify(clientMetadata),
|
||||
);
|
||||
} catch (error) {
|
||||
@@ -139,9 +177,18 @@ class VciClient {
|
||||
} finally {
|
||||
proofListener.remove();
|
||||
authListener.remove();
|
||||
tokenResponseListener.remove();
|
||||
}
|
||||
|
||||
return JSON.parse(response) as VerifiableCredential;
|
||||
const parsedResponse = JSON.parse(response);
|
||||
return {
|
||||
credential: {
|
||||
credential: parsedResponse.credential,
|
||||
} as VerifiableCredential,
|
||||
credentialConfigurationId:
|
||||
parsedResponse.credentialConfigurationId ?? {},
|
||||
credentialIssuer: parsedResponse.credentialIssuer ?? '',
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user