From af920f215201c452b5d0641c4d865f0c076d86f8 Mon Sep 17 00:00:00 2001 From: KiruthikaJeyashankar <81218987+KiruthikaJeyashankar@users.noreply.github.com> Date: Tue, 11 Jun 2024 11:18:54 +0530 Subject: [PATCH 1/2] [INJIMOB-1458] fallback issuers config if wellknown not available (#1507) * [INJIMOB-1458] fallback issuers config if wellknown not available (#1505) * [INJIMOB-1458] fallback to issuers config if well known is not available Signed-off-by: KiruthikaJeyashankar <81218987+KiruthikaJeyashankar@users.noreply.github.com> * [INJIMOB-1458] set vc metadata id as credential ID & displayId as UIN/PolicyNUmber Co-authored-by: Swati Goel Signed-off-by: KiruthikaJeyashankar <81218987+KiruthikaJeyashankar@users.noreply.github.com> --------- Signed-off-by: KiruthikaJeyashankar <81218987+KiruthikaJeyashankar@users.noreply.github.com> Co-authored-by: Swati Goel * [INJIMOB-1458] fix QR login failure due to alias mismatch in activation and QRLogin Signed-off-by: KiruthikaJeyashankar <81218987+KiruthikaJeyashankar@users.noreply.github.com> --------- Signed-off-by: KiruthikaJeyashankar <81218987+KiruthikaJeyashankar@users.noreply.github.com> Co-authored-by: Swati Goel --- .talismanrc | 2 +- .../residentapp/InjiVciClientModule.java | 10 +++- components/ActivityLogEvent.ts | 3 -- components/VC/common/VCUtils.tsx | 3 +- components/openId4VCI/CredentialType.tsx | 16 +++--- machines/Issuers/IssuersActions.ts | 3 +- machines/Issuers/IssuersService.ts | 28 ++++++----- machines/QrLogin/QrLoginServices.ts | 13 ++--- .../VCItemMachine/VCItemActions.ts | 23 +++++---- .../VCItemMachine/VCItemSelectors.ts | 4 -- .../VCItemMachine/VCItemServices.ts | 13 ++--- machines/bleShare/request/requestMachine.ts | 3 +- machines/bleShare/scan/scanActions.ts | 9 ++-- screens/Home/MyVcs/AddVcModalMachine.ts | 49 ++++++++++++------- screens/Home/MyVcs/HistoryTab.tsx | 2 +- screens/Home/MyVcsTab.tsx | 2 +- screens/Scan/SendVcScreenController.ts | 3 +- shared/Utils.ts | 11 +++++ shared/VCMetadata.ts | 37 +++++++++++--- shared/api.ts | 7 --- shared/cryptoutil/cryptoUtil.ts | 12 ++--- shared/openId4VCI/Utils.ts | 3 +- 22 files changed, 148 insertions(+), 108 deletions(-) diff --git a/.talismanrc b/.talismanrc index 632c206b5c..00f6afecf3 100644 --- a/.talismanrc +++ b/.talismanrc @@ -40,7 +40,7 @@ fileignoreconfig: - filename: shared/openId4VCI/Utils.ts checksum: ee4db1768be8d51fac0eb876a7b16fd2ab1806abcc711f01056f672003d11f31 - filename: shared/cryptoutil/cryptoUtil.ts - checksum: 2efef1baca1eee0da60420c8d966a6d58589bc3ac74169ab1cdc19423b630dba + checksum: a8edd1047e33bfc9e37b73945b8edcd294b8e29baf380f86cb0f647b355c8e5a - filename: shared/telemetry/TelemetryConstants.js checksum: fd8dc3a69cdef68855dc5f0531d8e634bfa2621bb4dc22f85b8247512a349c4c - filename: shared/telemetry/TelemetryUtils.js diff --git a/android/app/src/main/java/io/mosip/residentapp/InjiVciClientModule.java b/android/app/src/main/java/io/mosip/residentapp/InjiVciClientModule.java index ebfc485664..40308dbab5 100644 --- a/android/app/src/main/java/io/mosip/residentapp/InjiVciClientModule.java +++ b/android/app/src/main/java/io/mosip/residentapp/InjiVciClientModule.java @@ -41,12 +41,20 @@ public String getName() { @ReactMethod public void requestCredential(ReadableMap issuerMetaData, String jwtProofValue, String accessToken, Promise promise) { try { + CredentialFormat credentialFormat; + switch (issuerMetaData.getString("credentialFormat")) { + case "ldp_vc": + credentialFormat = CredentialFormat.LDP_VC; + break; + default: + credentialFormat = CredentialFormat.LDP_VC; + } CredentialResponse response = vciClient.requestCredential(new IssuerMetaData( issuerMetaData.getString("credentialAudience"), issuerMetaData.getString("credentialEndpoint"), issuerMetaData.getInt("downloadTimeoutInMilliSeconds"), convertReadableArrayToStringArray(issuerMetaData.getArray("credentialType")), - CredentialFormat.LDP_VC), new JWTProof(jwtProofValue) + credentialFormat), new JWTProof(jwtProofValue) , accessToken); promise.resolve(response.toJsonString()); } catch (Exception exception) { diff --git a/components/ActivityLogEvent.ts b/components/ActivityLogEvent.ts index a0b8e9a445..7b7e907b29 100644 --- a/components/ActivityLogEvent.ts +++ b/components/ActivityLogEvent.ts @@ -24,7 +24,6 @@ export class ActivityLog { _vcKey: string; timestamp: number; deviceName: string; - vcLabel: string; type: ActivityLogType; issuer: string; @@ -35,7 +34,6 @@ export class ActivityLog { type = '', timestamp = Date.now(), deviceName = '', - vcLabel = '', issuer = '', } = {}) { this.id = id; @@ -44,7 +42,6 @@ export class ActivityLog { this.type = type; this.timestamp = timestamp; this.deviceName = deviceName; - this.vcLabel = vcLabel; this.issuer = issuer; } diff --git a/components/VC/common/VCUtils.tsx b/components/VC/common/VCUtils.tsx index d9c7f60c5e..73626f6ac4 100644 --- a/components/VC/common/VCUtils.tsx +++ b/components/VC/common/VCUtils.tsx @@ -15,6 +15,7 @@ import {VCVerification} from '../../VCVerification'; import {MIMOTO_BASE_URL} from '../../../shared/constants'; import {VCItemDetailsProps} from '../Views/VCDetailView'; import {getSelectedCredentialTypeDetails} from '../../../shared/openId4VCI/Utils'; +import {parseJSON} from '../../../shared/Utils'; export const CARD_VIEW_DEFAULT_FIELDS = ['fullName']; export const DETAIL_VIEW_DEFAULT_FIELDS = [ @@ -207,7 +208,7 @@ export const getIdType = ( idType !== undefined ) { let supportedCredentialsWellknown; - wellknown = JSON.parse(wellknown) as Object[]; + wellknown = parseJSON(wellknown) as unknown as Object[]; if (!!!wellknown['credentials_supported']) { return i18n.t('VcDetails:nationalCard'); } diff --git a/components/openId4VCI/CredentialType.tsx b/components/openId4VCI/CredentialType.tsx index 82e7380f6c..5485a6b95f 100644 --- a/components/openId4VCI/CredentialType.tsx +++ b/components/openId4VCI/CredentialType.tsx @@ -9,9 +9,10 @@ import {getDisplayObjectForCurrentLanguage} from '../../shared/openId4VCI/Utils' import {CredentialTypes} from '../../machines/VerifiableCredential/VCMetaMachine/vc'; export const CredentialType: React.FC = props => { - const selectedIssuerDisplayObject = getDisplayObjectForCurrentLanguage( - props.item.display, - ); + const selectedIssuerDisplayObject = props.item.display + ? getDisplayObjectForCurrentLanguage(props.item.display) + : {}; + return ( = props => { ] }> - {SvgImage.IssuerIcon({ - ...props, - displayDetails: selectedIssuerDisplayObject, - })} + {selectedIssuerDisplayObject?.logo && + SvgImage.IssuerIcon({ + ...props, + displayDetails: selectedIssuerDisplayObject, + })} { { _vcKey: vcMetadata.getVcKey(), type: 'VC_DOWNLOADED', - id: vcMetadata.id, + id: vcMetadata.displayId, idType: context.credentialWrapper.verifiableCredential.credentialTypes, timestamp: Date.now(), deviceName: '', - vcLabel: vcMetadata.id, issuer: context.selectedIssuerId, }, context.selectedCredentialType, diff --git a/machines/Issuers/IssuersService.ts b/machines/Issuers/IssuersService.ts index 7cb7c48456..5be1e4d0be 100644 --- a/machines/Issuers/IssuersService.ts +++ b/machines/Issuers/IssuersService.ts @@ -40,18 +40,24 @@ export const IssuersService = () => { let issuersConfig = await CACHED_API.fetchIssuerConfig( context.selectedIssuerId, ); - const wellknownResponse = await CACHED_API.fetchIssuerWellknownConfig( - context.selectedIssuerId, - issuersConfig['.well-known'], - ); - issuersConfig.credential_endpoint = - wellknownResponse?.credential_endpoint; - issuersConfig.credential_audience = wellknownResponse?.credential_issuer; - issuersConfig.credentialTypes = wellknownResponse?.credentials_supported; + if (issuersConfig['.well-known']) { + const wellknownResponse = await CACHED_API.fetchIssuerWellknownConfig( + context.selectedIssuerId, + issuersConfig['.well-known'], + ); + if (wellknownResponse) { + issuersConfig.credential_audience = + wellknownResponse.credential_issuer; + issuersConfig.credential_endpoint = + wellknownResponse.credential_endpoint; + issuersConfig.credentials_supported = + wellknownResponse.credentials_supported; + } + } return issuersConfig; }, downloadCredentialTypes: async (context: any) => { - return context.selectedIssuer.credentialTypes; + return context.selectedIssuer.credentials_supported; }, downloadCredential: async (context: any) => { const downloadTimeout = await vcDownloadTimeout(); @@ -61,8 +67,8 @@ export const IssuersService = () => { credentialEndpoint: context.selectedIssuer.credential_endpoint, downloadTimeoutInMilliSeconds: downloadTimeout, credentialType: context.selectedCredentialType?.credential_definition - .type ?? ['VerifiableCredential'], - credentialFormat: 'ldp_vc', + ?.type ?? ['VerifiableCredential'], + credentialFormat: context.selectedCredentialType.format, }; const proofJWT = await constructProofJWT( context.publicKey, diff --git a/machines/QrLogin/QrLoginServices.ts b/machines/QrLogin/QrLoginServices.ts index 0995fb2d31..75ae65ab47 100644 --- a/machines/QrLogin/QrLoginServices.ts +++ b/machines/QrLogin/QrLoginServices.ts @@ -25,7 +25,8 @@ export const QrLoginServices = { sendAuthenticate: async context => { let privateKey; - const individualId = context.selectedVc.vcMetadata.id; + const individualId = context.selectedVc.vcMetadata.displayId; + const alias = context.selectedVc.vcMetadata.id; if (!isHardwareKeystoreExists) { privateKey = await getPrivateKey( context.selectedVc.walletBindingResponse?.walletBindingId, @@ -33,12 +34,12 @@ export const QrLoginServices = { } var config = await getAllConfigurations(); - const header = { + const jwtHeader = { alg: 'RS256', 'x5t#S256': context.thumbprint, }; - const payload = { + const jwtPayload = { iss: config.issuer, sub: individualId, aud: config.audience, @@ -46,7 +47,7 @@ export const QrLoginServices = { exp: Math.floor(new Date().getTime() / 1000) + 18000, }; - const jwt = await getJWT(header, payload, individualId, privateKey); + const jwt = await getJWT(jwtHeader, jwtPayload, alias, privateKey); const response = await request( API_URLS.authenticate.method, @@ -72,7 +73,7 @@ export const QrLoginServices = { sendConsent: async context => { let privateKey; - const individualId = context.selectedVc.vcMetadata.id; + const alias = context.selectedVc.vcMetadata.id; if (!isHardwareKeystoreExists) { privateKey = await getPrivateKey( context.selectedVc.walletBindingResponse?.walletBindingId, @@ -90,7 +91,7 @@ export const QrLoginServices = { permitted_authorized_scopes: context.authorizeScopes, }; - const JWT = await getJWT(header, payload, individualId, privateKey); + const JWT = await getJWT(header, payload, alias, privateKey); const jwtComponents = JWT.split('.'); const detachedSignature = jwtComponents[0] + '.' + jwtComponents[2]; diff --git a/machines/VerifiableCredential/VCItemMachine/VCItemActions.ts b/machines/VerifiableCredential/VCItemMachine/VCItemActions.ts index d82a0d8f91..e96f7fe9e7 100644 --- a/machines/VerifiableCredential/VCItemMachine/VCItemActions.ts +++ b/machines/VerifiableCredential/VCItemMachine/VCItemActions.ts @@ -127,11 +127,18 @@ export const VCItemActions = model => { ), setContext: model.assign((context, event) => { - const vcMetadata = context.vcMetadata; + const vcMetadata = VCMetadata.fromVC(context.vcMetadata); + if (!vcMetadata.id) { + const verifiableCredentialId = event.response.verifiableCredential.id; + const credId = verifiableCredentialId.startsWith('did') + ? verifiableCredentialId.split(':') + : verifiableCredentialId.split('/'); + vcMetadata.id = `${credId[credId.length - 1]} - ${vcMetadata.issuer}`; + } return { ...context, ...event.response, - vcMetadata: VCMetadata.fromVC(vcMetadata), + vcMetadata: vcMetadata, }; }), storeContext: send( @@ -451,12 +458,11 @@ export const VCItemActions = model => { return ActivityLogEvents.LOG_ACTIVITY({ _vcKey: context.vcMetadata.getVcKey(), type: 'VC_DOWNLOADED', - id: context.vcMetadata.id, + id: context.vcMetadata.displayId, issuer: context.vcMetadata.issuer!!, idType: getCredentialTypes(context.verifiableCredential), timestamp: Date.now(), deviceName: '', - vcLabel: data.id, }); }, { @@ -469,12 +475,11 @@ export const VCItemActions = model => { return ActivityLogEvents.LOG_ACTIVITY({ idType: getCredentialTypes(context.verifiableCredential), issuer: vcMetadata.issuer!!, - id: vcMetadata.id, + id: vcMetadata.displayId, _vcKey: vcMetadata.getVcKey(), type: 'VC_REMOVED', timestamp: Date.now(), deviceName: '', - vcLabel: vcMetadata.id, }); }, { @@ -489,10 +494,9 @@ export const VCItemActions = model => { type: 'WALLET_BINDING_SUCCESSFULL', idType: getCredentialTypes(context.verifiableCredential), issuer: vcMetadata.issuer!!, - id: vcMetadata.id, + id: vcMetadata.displayId, timestamp: Date.now(), deviceName: '', - vcLabel: vcMetadata.id, }); }, { @@ -506,12 +510,11 @@ export const VCItemActions = model => { return ActivityLogEvents.LOG_ACTIVITY({ _vcKey: vcMetadata.getVcKey(), type: 'WALLET_BINDING_FAILURE', - id: vcMetadata.id, + id: vcMetadata.displayId, idType: getCredentialTypes(context.verifiableCredential), issuer: vcMetadata.issuer!!, timestamp: Date.now(), deviceName: '', - vcLabel: vcMetadata.id, }); }, { diff --git a/machines/VerifiableCredential/VCItemMachine/VCItemSelectors.ts b/machines/VerifiableCredential/VCItemMachine/VCItemSelectors.ts index d52091cb58..90fdd03cea 100644 --- a/machines/VerifiableCredential/VCItemMachine/VCItemSelectors.ts +++ b/machines/VerifiableCredential/VCItemMachine/VCItemSelectors.ts @@ -133,7 +133,3 @@ export function selectVc(state: State) { const {serviceRefs, ...data} = state.context; return data; } - -export function selectId(state: State) { - return state.context.vcMetadata.id; -} diff --git a/machines/VerifiableCredential/VCItemMachine/VCItemServices.ts b/machines/VerifiableCredential/VCItemMachine/VCItemServices.ts index aaab00d921..f997071b0b 100644 --- a/machines/VerifiableCredential/VCItemMachine/VCItemServices.ts +++ b/machines/VerifiableCredential/VCItemMachine/VCItemServices.ts @@ -67,7 +67,7 @@ export const VCItemServices = model => { request: { authFactorType: 'WLA', format: 'jwt', - individualId: VCMetadata.fromVC(context.vcMetadata).id, + individualId: context.vcMetadata.displayId, transactionId: context.bindingTransactionId, publicKey: context.publicKey, challengeList: [ @@ -80,11 +80,6 @@ export const VCItemServices = model => { }, }, ); - const certificate = response.response.certificate; - await savePrivateKey( - getBindingCertificateConstant(VCMetadata.fromVC(context.vcMetadata).id), - certificate, - ); const walletResponse: WalletBindingResponse = { walletBindingId: response.response.encryptedWalletBindingId, @@ -107,14 +102,13 @@ export const VCItemServices = model => { ); }, requestBindingOTP: async context => { - const vc = getVerifiableCredential(context.verifiableCredential); const response = await request( API_URLS.bindingOtp.method, API_URLS.bindingOtp.buildURL(), { requestTime: String(new Date().toISOString()), request: { - individualId: VCMetadata.fromVC(context.vcMetadata).id, + individualId: context.vcMetadata.displayId, otpChannels: ['EMAIL', 'PHONE'], }, }, @@ -184,7 +178,7 @@ export const VCItemServices = model => { API_URLS.credentialDownload.method, API_URLS.credentialDownload.buildURL(), { - individualId: context.vcMetadata.id, + individualId: context.vcMetadata.displayId, requestId: context.vcMetadata.requestId, }, ); @@ -194,7 +188,6 @@ export const VCItemServices = model => { credential: response.credential, verifiableCredential: response.verifiableCredential, generatedOn: new Date(), - id: context.vcMetadata.id, idType: context.vcMetadata.idType, requestId: context.vcMetadata.requestId, lastVerifiedOn: null, diff --git a/machines/bleShare/request/requestMachine.ts b/machines/bleShare/request/requestMachine.ts index 5385a74c55..79a7178a50 100644 --- a/machines/bleShare/request/requestMachine.ts +++ b/machines/bleShare/request/requestMachine.ts @@ -619,7 +619,7 @@ export const requestMachine = return ActivityLogEvents.LOG_ACTIVITY({ _vcKey: vcMetadata.getVcKey(), type: context.receiveLogType, - id: vcMetadata.id, + id: vcMetadata.displayId, idType: getCredentialTypes( context.incomingVc.verifiableCredential, ), @@ -627,7 +627,6 @@ export const requestMachine = timestamp: Date.now(), deviceName: context.senderInfo.name || context.senderInfo.deviceName, - vcLabel: vcMetadata.id, }); }, {to: context => context.serviceRefs.activityLog}, diff --git a/machines/bleShare/scan/scanActions.ts b/machines/bleShare/scan/scanActions.ts index 9a8a86fe42..2281a500fe 100644 --- a/machines/bleShare/scan/scanActions.ts +++ b/machines/bleShare/scan/scanActions.ts @@ -198,13 +198,12 @@ export const ScanActions = (model: any, QR_LOGIN_REF_ID: any) => { type: context.shareLogType ? context.shareLogType : 'VC_SHARED_WITH_VERIFICATION_CONSENT', - id: vcMetadata.id, + id: vcMetadata.displayId, idType: getCredentialTypes(context.selectedVc.verifiableCredential), issuer: vcMetadata.issuer!!, timestamp: Date.now(), deviceName: context.receiverInfo.name || context.receiverInfo.deviceName, - vcLabel: vcMetadata.id, }); }, {to: context => context.serviceRefs.activityLog}, @@ -218,11 +217,10 @@ export const ScanActions = (model: any, QR_LOGIN_REF_ID: any) => { type: 'PRESENCE_VERIFICATION_FAILED', timestamp: Date.now(), idType: getCredentialTypes(context.selectedVc.verifiableCredential), - id: vcMetadata.id, + id: vcMetadata.displayId, issuer: vcMetadata.issuer!!, deviceName: context.receiverInfo.name || context.receiverInfo.deviceName, - vcLabel: vcMetadata.id, }); }, {to: context => context.serviceRefs.activityLog}, @@ -277,13 +275,12 @@ export const ScanActions = (model: any, QR_LOGIN_REF_ID: any) => { return ActivityLogEvents.LOG_ACTIVITY({ _vcKey: '', - id: vcMetadata.id, + id: vcMetadata.displayId, issuer: vcMetadata.issuer!!, idType: getCredentialTypes(selectedVc.verifiableCredential), type: 'QRLOGIN_SUCCESFULL', timestamp: Date.now(), deviceName: '', - vcLabel: String(vcMetadata.id), }); }, { diff --git a/screens/Home/MyVcs/AddVcModalMachine.ts b/screens/Home/MyVcs/AddVcModalMachine.ts index 134e5b3300..e2be10d0f3 100644 --- a/screens/Home/MyVcs/AddVcModalMachine.ts +++ b/screens/Home/MyVcs/AddVcModalMachine.ts @@ -36,12 +36,13 @@ const model = createModel( phoneNumber: '' as string, email: '' as string, isPinned: false, + displayId: '', }, { events: { SET_INDIVIDUAL_ID: (individualId: IndividualId) => ({ - id: individualId.id, idType: individualId.idType, + displayId: individualId.id, }), INPUT_ID: (id: string) => ({id}), INPUT_OTP: (otp: string) => ({otp}), @@ -73,7 +74,12 @@ export const AddVcModalMachine = initial: 'acceptingIdInput', on: { SET_INDIVIDUAL_ID: { - actions: ['clearIdError', 'clearId', 'setIdType', 'setId'], + actions: [ + 'clearIdError', + 'clearDisplayId', + 'setIdType', + 'setDisplayId', + ], target: '#AddVcModal.acceptingIdInput.idle', }, }, @@ -103,10 +109,15 @@ export const AddVcModalMachine = entry: 'focusInput', on: { SET_INDIVIDUAL_ID: { - actions: ['clearIdError', 'clearId', 'setIdType', 'setId'], + actions: [ + 'clearIdError', + 'clearDisplayId', + 'setIdType', + 'setDisplayId', + ], }, INPUT_ID: { - actions: 'setId', + actions: 'setDisplayId', }, VALIDATE_INPUT: [ { @@ -123,7 +134,7 @@ export const AddVcModalMachine = }, ], SELECT_ID_TYPE: { - actions: ['clearIdError', 'setIdType', 'clearId'], + actions: ['clearIdError', 'setIdType', 'clearDisplayId'], }, }, }, @@ -140,7 +151,7 @@ export const AddVcModalMachine = }, on: { INPUT_ID: { - actions: ['setId', 'clearIdError'], + actions: ['setDisplayId', 'clearIdError'], target: 'idle', }, VALIDATE_INPUT: [ @@ -158,7 +169,7 @@ export const AddVcModalMachine = }, ], SELECT_ID_TYPE: { - actions: ['clearIdError', 'setIdType', 'clearId'], + actions: ['clearIdError', 'setIdType', 'clearDisplayId'], target: 'idle', }, }, @@ -226,7 +237,7 @@ export const AddVcModalMachine = cancelDownload: { on: { CANCEL: { - actions: ['clearId', 'resetIdInputRef', 'forwardToParent'], + actions: ['clearDisplayId', 'resetIdInputRef', 'forwardToParent'], }, WAIT: { target: 'acceptingOtpInput', @@ -265,8 +276,8 @@ export const AddVcModalMachine = actions: { forwardToParent: sendParent('DISMISS'), - setId: model.assign({ - id: (_context, event) => event.id, + setDisplayId: model.assign({ + displayId: (_context, event) => event.id, }), setIdType: model.assign({ @@ -328,7 +339,7 @@ export const AddVcModalMachine = }, }), - clearId: model.assign({id: ''}), + clearDisplayId: model.assign({displayId: ''}), clearIdError: model.assign({idError: ''}), @@ -391,7 +402,7 @@ export const AddVcModalMachine = API_URLS.requestOtp.buildURL(), { id: 'mosip.identity.otp.internal', - individualId: context.id, + individualId: context.displayId, metadata: {}, otpChannel: ['PHONE', 'EMAIL'], requestTime: String(new Date().toISOString()), @@ -408,7 +419,7 @@ export const AddVcModalMachine = API_URLS.credentialRequest.method, API_URLS.credentialRequest.buildURL(), { - individualId: context.id, + individualId: context.displayId, individualIdType: context.idType, otp: context.otp, transactionID: context.transactionId, @@ -419,12 +430,14 @@ export const AddVcModalMachine = }, guards: { - isEmptyId: ({id}) => id?.trim() === '', + isEmptyId: ({displayId}) => displayId?.trim() === '', - isWrongIdFormat: ({idType, id}) => { + isWrongIdFormat: ({idType, displayId}) => { const validIdType = - idType === 'UIN' ? id.length === 10 : id.length === 16; - return !(/^\d{10,16}$/.test(id) && validIdType); + idType === 'UIN' + ? displayId.length === 10 + : displayId.length === 16; + return !(/^\d{10,16}$/.test(displayId) && validIdType); }, isIdInvalid: (_context, event: unknown) => @@ -438,7 +451,7 @@ export const AddVcModalMachine = type State = StateFrom; export function selectId(state: State) { - return state.context.id; + return state.context.displayId; } export function selectIdType(state: State) { diff --git a/screens/Home/MyVcs/HistoryTab.tsx b/screens/Home/MyVcs/HistoryTab.tsx index fd4351271c..b7b292f867 100644 --- a/screens/Home/MyVcs/HistoryTab.tsx +++ b/screens/Home/MyVcs/HistoryTab.tsx @@ -16,7 +16,7 @@ export const HistoryTab: React.FC = props => { return ( <> diff --git a/screens/Home/MyVcsTab.tsx b/screens/Home/MyVcsTab.tsx index 6c4631c0b7..235c2f1b66 100644 --- a/screens/Home/MyVcsTab.tsx +++ b/screens/Home/MyVcsTab.tsx @@ -183,7 +183,7 @@ export const MyVcsTab: React.FC = props => { let failedVCsList = []; controller.downloadFailedVcs.forEach(vc => { - failedVCsList.push(`\n${vc.idType}:${vc.id}`); + failedVCsList.push(`\n${vc.idType}:${vc.displayId}`); }); const isVerificationFailed = controller.verificationErrorMessage !== ''; diff --git a/screens/Scan/SendVcScreenController.ts b/screens/Scan/SendVcScreenController.ts index a2f4bf88c4..40766abdcc 100644 --- a/screens/Scan/SendVcScreenController.ts +++ b/screens/Scan/SendVcScreenController.ts @@ -80,7 +80,8 @@ export function useSendVcScreen() { SELECT_VC_ITEM: (index: number) => (vcRef: ActorRefFrom) => { setSelectedIndex(index); - const {serviceRefs, ...vcData} = vcRef.getSnapshot().context; + const {serviceRefs, wellknownResponse, ...vcData} = + vcRef.getSnapshot().context; scanService.send( ScanEvents.SELECT_VC(vcData, VCShareFlowType.SIMPLE_SHARE), ); diff --git a/shared/Utils.ts b/shared/Utils.ts index 829e1e3938..4a80c45e54 100644 --- a/shared/Utils.ts +++ b/shared/Utils.ts @@ -30,3 +30,14 @@ export interface CommunicationDetails { export const isMosipVC = (issuer: string) => { return issuer === Issuers.Mosip || issuer === Issuers.MosipOtp; }; + +export const parseJSON = (input: any) => { + let result = null; + try { + result = JSON.parse(input); + } catch (e) { + console.warn('Error occurred while parsing JSON ', e); + result = JSON.parse(JSON.stringify(input)); + } + return result; +}; diff --git a/shared/VCMetadata.ts b/shared/VCMetadata.ts index c4b5d4030b..6f5254299e 100644 --- a/shared/VCMetadata.ts +++ b/shared/VCMetadata.ts @@ -1,4 +1,9 @@ -import {VC, VcIdType} from '../machines/VerifiableCredential/VCMetaMachine/vc'; +import { + Credential, + VC, + VcIdType, + VerifiableCredential, +} from '../machines/VerifiableCredential/VCMetaMachine/vc'; import {Protocols} from './openId4VCI/Utils'; import {getMosipIdentifier} from './commonUtil'; @@ -15,6 +20,7 @@ export class VCMetadata { protocol?: string = ''; timestamp?: string = ''; isVerified: boolean = false; + displayId: string = ''; constructor({ idType = '', @@ -25,6 +31,7 @@ export class VCMetadata { protocol = '', timestamp = '', isVerified = false, + displayId = '', } = {}) { this.idType = idType; this.requestId = requestId; @@ -34,6 +41,7 @@ export class VCMetadata { this.issuer = issuer; this.timestamp = timestamp; this.isVerified = isVerified; + this.displayId = displayId; } //TODO: Remove any typing and use appropriate typing @@ -47,6 +55,11 @@ export class VCMetadata { issuer: vc.issuer, timestamp: vc.vcMetadata ? vc.vcMetadata.timestamp : vc.timestamp, isVerified: vc.isVerified, + displayId: vc.displayId + ? vc.displayId + : vc.vcMetadata + ? vc.vcMetadata.displayId + : getDisplayId(vc.verifiableCredential), }); } @@ -94,12 +107,24 @@ export const getVCMetadata = (context: object) => { requestId: credentialId ?? null, issuer: issuer, protocol: protocol, - id: - context.verifiableCredential?.credential.credentialSubject.policyNumber || - getMosipIdentifier( - context.verifiableCredential?.credential.credentialSubject, - ), + id: `${credentialId} + '_' + ${issuer}`, timestamp: context.timestamp ?? '', isVerified: context.vcMetadata.isVerified ?? false, + displayId: getDisplayId(context.verifiableCredential), }); }; + +const getDisplayId = ( + verifiableCredential: VerifiableCredential | Credential, +) => { + if (verifiableCredential?.credential) { + return ( + verifiableCredential.credential?.credentialSubject?.policyNumber || + getMosipIdentifier(verifiableCredential.credential.credentialSubject) + ); + } + return ( + verifiableCredential?.credentialSubject?.policyNumber || + getMosipIdentifier(verifiableCredential.credentialSubject) + ); +}; diff --git a/shared/api.ts b/shared/api.ts index 89e8ff8511..f8f6a869aa 100644 --- a/shared/api.ts +++ b/shared/api.ts @@ -27,12 +27,6 @@ export const API_URLS: ApiUrls = { buildURL: (issuerId: string): `/${string}` => `/residentmobileapp/issuers/${issuerId}`, }, - // TODO: Remove unused api - credentialTypes: { - method: 'GET', - buildURL: (issuerId: string): `/${string}` => - `/residentmobileapp/issuers/${issuerId}/credentialTypes`, - }, issuerWellknownConfig: { method: 'GET', buildURL: (requestUrl: `/${string}`): `/${string}` => requestUrl, @@ -334,7 +328,6 @@ type Api_Params = { type ApiUrls = { issuersList: Api_Params; issuerConfig: Api_Params; - credentialTypes: Api_Params; issuerWellknownConfig: Api_Params; allProperties: Api_Params; getIndividualId: Api_Params; diff --git a/shared/cryptoutil/cryptoUtil.ts b/shared/cryptoutil/cryptoUtil.ts index 79e24f57ae..c7ea4adc4f 100644 --- a/shared/cryptoutil/cryptoUtil.ts +++ b/shared/cryptoutil/cryptoUtil.ts @@ -27,18 +27,14 @@ export const isHardwareKeystoreExists = isCustomSecureKeystore(); export async function getJWT( header: object, payLoad: object, - individualId: string, + alias: string, privateKey: string, ) { try { const header64 = encodeB64(JSON.stringify(header)); const payLoad64 = encodeB64(JSON.stringify(payLoad)); const preHash = header64 + '.' + payLoad64; - const signature64 = await createSignature( - privateKey, - preHash, - individualId, - ); + const signature64 = await createSignature(privateKey, preHash, alias); return header64 + '.' + payLoad64 + '.' + signature64; } catch (e) { console.error('Exception Occurred While Constructing JWT ', e); @@ -49,7 +45,7 @@ export async function getJWT( export async function createSignature( privateKey: string, preHash: string, - individualId: string, + alias: string, ) { let signature64; @@ -62,7 +58,7 @@ export async function createSignature( return encodeB64(signature); } else { try { - signature64 = await RNSecureKeystoreModule.sign(individualId, preHash); + signature64 = await RNSecureKeystoreModule.sign(alias, preHash); } catch (error) { console.error('Error in creating signature:', error); if (error.toString().includes(BIOMETRIC_CANCELLED)) { diff --git a/shared/openId4VCI/Utils.ts b/shared/openId4VCI/Utils.ts index 8c17f26244..2222bd22ec 100644 --- a/shared/openId4VCI/Utils.ts +++ b/shared/openId4VCI/Utils.ts @@ -30,7 +30,6 @@ export const Protocols = { export const Issuers = { MosipOtp: '', - Sunbird: 'Sunbird', Mosip: 'Mosip', }; @@ -47,7 +46,7 @@ export function getVcVerificationDetails( return { statusType: statusType, vcType: idType, - vcNumber: vcMetadata.id, + vcNumber: vcMetadata.displayId, }; } From 02f38ee2932472bd91fa94f1fbeb1e270ea400d3 Mon Sep 17 00:00:00 2001 From: Sreenadh S <32409698+sree96@users.noreply.github.com> Date: Thu, 6 Jun 2024 16:32:56 +0530 Subject: [PATCH 2/2] [INJIMOB-1339] - iOS pipeline fix Signed-off-by: Sreenadh S <32409698+sree96@users.noreply.github.com> --- ios/Inji.xcodeproj/project.pbxproj | 19 +++++++++++++------ ios/Inji/InjiRelease.entitlements | 27 +++++++++++++++++++++++++++ ios/Podfile | 5 +++++ ios/Podfile.lock | 2 +- ios/fastlane/Fastfile | 2 +- 5 files changed, 47 insertions(+), 8 deletions(-) create mode 100644 ios/Inji/InjiRelease.entitlements diff --git a/ios/Inji.xcodeproj/project.pbxproj b/ios/Inji.xcodeproj/project.pbxproj index 0b13659547..946e265f14 100644 --- a/ios/Inji.xcodeproj/project.pbxproj +++ b/ios/Inji.xcodeproj/project.pbxproj @@ -50,6 +50,7 @@ 13B07FB51A68108700A75B9A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = Inji/Images.xcassets; sourceTree = ""; }; 13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = Inji/Info.plist; sourceTree = ""; }; 13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = Inji/main.m; sourceTree = ""; }; + 182671E22C11BFD0007B2B46 /* InjiRelease.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; name = InjiRelease.entitlements; path = Inji/InjiRelease.entitlements; sourceTree = ""; }; 58EEBF8E8E6FB1BC6CAF49B5 /* libPods-Inji.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Inji.a"; sourceTree = BUILT_PRODUCTS_DIR; }; 6C2E3173556A471DD304B334 /* Pods-Inji.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Inji.debug.xcconfig"; path = "Target Support Files/Pods-Inji/Pods-Inji.debug.xcconfig"; sourceTree = ""; }; 7A4D352CD337FB3A3BF06240 /* Pods-Inji.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Inji.release.xcconfig"; path = "Target Support Files/Pods-Inji/Pods-Inji.release.xcconfig"; sourceTree = ""; }; @@ -100,6 +101,7 @@ 13B07FAE1A68108700A75B9A /* Inji */ = { isa = PBXGroup; children = ( + 182671E22C11BFD0007B2B46 /* InjiRelease.entitlements */, BB2F792B24A3F905000567C9 /* Supporting */, 008F07F21AC5B25A0029DE68 /* main.jsbundle */, 13B07FAF1A68108700A75B9A /* AppDelegate.h */, @@ -472,10 +474,11 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = Inji/Inji.entitlements; - CODE_SIGN_IDENTITY = "Apple Development"; + CODE_SIGN_IDENTITY = "Apple Distribution"; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 8; DEVELOPMENT_TEAM = V2ABX7953Z; + "DEVELOPMENT_TEAM[sdk=iphoneos*]" = V2ABX7953Z; ENABLE_BITCODE = NO; "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = arm64; GCC_PREPROCESSOR_DEFINITIONS = ( @@ -498,6 +501,7 @@ PRODUCT_BUNDLE_IDENTIFIER = io.mosip.inji.wallet.mobileid; PRODUCT_NAME = Inji; PROVISIONING_PROFILE_SPECIFIER = ""; + "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = ""; SWIFT_OBJC_BRIDGING_HEADER = ""; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 5.0; @@ -512,11 +516,13 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; - CODE_SIGN_ENTITLEMENTS = Inji/Inji.entitlements; - CODE_SIGN_IDENTITY = "Apple Development"; - CODE_SIGN_STYLE = Automatic; + CODE_SIGN_ENTITLEMENTS = Inji/InjiRelease.entitlements; + CODE_SIGN_IDENTITY = "Apple Distribution"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "Apple Distribution"; + CODE_SIGN_STYLE = Manual; CURRENT_PROJECT_VERSION = 8; - DEVELOPMENT_TEAM = V2ABX7953Z; + DEVELOPMENT_TEAM = ""; + "DEVELOPMENT_TEAM[sdk=iphoneos*]" = V2ABX7953Z; "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = arm64; INFOPLIST_FILE = Inji/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 13.0; @@ -533,7 +539,8 @@ OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_RELEASE"; PRODUCT_BUNDLE_IDENTIFIER = io.mosip.inji.wallet.mobileid; PRODUCT_NAME = Inji; - PROVISIONING_PROFILE_SPECIFIER = ""; + PROVISIONING_PROFILE_SPECIFIER = "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"; diff --git a/ios/Inji/InjiRelease.entitlements b/ios/Inji/InjiRelease.entitlements new file mode 100644 index 0000000000..eca3db956e --- /dev/null +++ b/ios/Inji/InjiRelease.entitlements @@ -0,0 +1,27 @@ + + + + + aps-environment + development + com.apple.developer.applesignin + + Default + + com.apple.developer.icloud-container-identifiers + + iCloud.io.mosip.inji.wallet.mobileid + + com.apple.developer.icloud-services + + CloudDocuments + CloudKit + + com.apple.developer.ubiquity-container-identifiers + + iCloud.io.mosip.inji.wallet.mobileid + + com.apple.developer.ubiquity-kvstore-identifier + $(TeamIdentifierPrefix)$(CFBundleIdentifier) + + \ No newline at end of file diff --git a/ios/Podfile b/ios/Podfile index 00f4c3b4dc..da9b5e71a6 100644 --- a/ios/Podfile +++ b/ios/Podfile @@ -78,6 +78,11 @@ target 'Inji' do end end end + installer.pods_project.targets.each do |target| + target.build_configurations.each do |config| + config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] ||= ['$(inherited)', '_LIBCPP_ENABLE_CXX17_REMOVED_UNARY_BINARY_FUNCTION'] + end + end # Workaround `Cycle inside FBReactNativeSpec` error for react-native 0.64 # Reference: https://github.com/software-mansion/react-native-screens/issues/842#issuecomment-812543933 diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 0fb915668e..fd678683fb 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -1042,6 +1042,6 @@ SPEC CHECKSUMS: Yoga: 065f0b74dba4832d6e328238de46eb72c5de9556 ZXingObjC: fdbb269f25dd2032da343e06f10224d62f537bdb -PODFILE CHECKSUM: ef6fb41f40316f97c32e0b8b38aa320e6f8acf15 +PODFILE CHECKSUM: 44ee7985ac0203f16a6b823b6972530b17704618 COCOAPODS: 1.15.2 diff --git a/ios/fastlane/Fastfile b/ios/fastlane/Fastfile index e0bcf1b04e..01fd3191f9 100644 --- a/ios/fastlane/Fastfile +++ b/ios/fastlane/Fastfile @@ -1,4 +1,4 @@ -xcode_select '/Applications/Xcode_14.2.app' +xcode_select '/Applications/Xcode_15.0.1.app' default_platform(:ios) APP_STORE_CONNECT_TEAM_ID = ENV["APP_STORE_CONNECT_TEAM_ID"]