Files
inji-wallet/shared/vciClient/VciClient.ts
KiruthikaJeyashankar 5305e7d7ea [INJIMOB-3392] add token request logic in wallet for vci flow (#2014)
* [INJIMOB-3392] add token request logic in wallet for vci flow

Signed-off-by: Abhishek Paul <paul.apaul.abhishek.ap@gmail.com>

* [INJIMOB-3392] chore: update integration of VCIClient native module

Changes are updated as per new changes in the library

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

* [INJIMOB-3390] refactor: event structure of token request

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

* [INJIMOB-3392] fix tokenEndpoint method and refactorings

Signed-off-by: Abhishek Paul <paul.apaul.abhishek.ap@gmail.com>

* [INJIMOB-3392] cnonce decode from accesstoken and credential response destructuring fix

Signed-off-by: Abhishek Paul <paul.apaul.abhishek.ap@gmail.com>

* [INJIMOB-3390] add: getIssuerMetadata in kotlin NativeModule

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

* [INJIMOB-3393] fix: auth callback in android

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

* [INJIMOB-3390] fix: proofJwt issue in download flow

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

* [INJIMOB-3392] fix credentialofferflow

Signed-off-by: Abhishek Paul <paul.apaul.abhishek.ap@gmail.com>

* [INJIMOB-3392]fix format issues in bridge layer

Signed-off-by: Abhishek Paul <paul.apaul.abhishek.ap@gmail.com>

* [INJIMOB-3392]fix activity log texts on application reopen

Signed-off-by: Abhishek Paul <paul.apaul.abhishek.ap@gmail.com>

* [INJIMOB-3392]cache issuer metadata by key: issuerhost

Signed-off-by: Abhishek Paul <paul.apaul.abhishek.ap@gmail.com>

* [INJIMOB-3392] fix error scenarios and cleanup issuermachine

Signed-off-by: Abhishek Paul <paul.apaul.abhishek.ap@gmail.com>

* [INJIMOB-3392] refactor request method to handle missing error scenarios

Signed-off-by: Abhishek Paul <paul.apaul.abhishek.ap@gmail.com>

* [INJIMOB-3392] fix max lines for txcode description to 2

Signed-off-by: Abhishek Paul <paul.apaul.abhishek.ap@gmail.com>

* [INJIMOB-3392] rename credentialissueruri to credentialissuer

Signed-off-by: Abhishek Paul <paul.apaul.abhishek.ap@gmail.com>

* [INJIMOB-3392] take cnonce from outside accesstoken

Signed-off-by: Abhishek Paul <paul.apaul.abhishek.ap@gmail.com>

* [INJIMOB-3392] declare random-values at entry file

Signed-off-by: Abhishek Paul <paul.apaul.abhishek.ap@gmail.com>

* [INJIMOB-3392] set fallback keytype to user priority first

Signed-off-by: Abhishek Paul <paul.apaul.abhishek.ap@gmail.com>

* [INJIMOB-3392] add locales for network request failed error

Signed-off-by: Abhishek Paul <paul.apaul.abhishek.ap@gmail.com>

* [INJIMOB-3392] remove console log

Signed-off-by: Abhishek Paul <paul.apaul.abhishek.ap@gmail.com>

* [INJIMOB-3392] refactor and clean up code

Signed-off-by: Abhishek Paul <paul.apaul.abhishek.ap@gmail.com>

---------

Signed-off-by: Abhishek Paul <paul.apaul.abhishek.ap@gmail.com>
Signed-off-by: KiruthikaJeyashankar <kiruthikavjshankar@gmail.com>
Co-authored-by: Abhishek Paul <paul.apaul.abhishek.ap@gmail.com>
2025-07-24 11:42:00 +05:30

196 lines
5.5 KiB
TypeScript

import {NativeModules, NativeEventEmitter} from 'react-native';
import {__AppId} from '../GlobalVariables';
import {VerifiableCredential} from '../../machines/VerifiableCredential/VCMetaMachine/vc';
const emitter = new NativeEventEmitter(NativeModules.InjiVciClient);
class VciClient {
private static instance: VciClient;
private InjiVciClient = NativeModules.InjiVciClient;
private constructor() {
this.InjiVciClient.init(__AppId.getValue());
}
static getInstance(): VciClient {
if (!VciClient.instance) {
VciClient.instance = new VciClient();
}
return VciClient.instance;
}
async sendProof(jwt: string) {
this.InjiVciClient.sendProofFromJS(jwt);
}
async sendAuthCode(authCode: string) {
this.InjiVciClient.sendAuthCodeFromJS(authCode);
}
async sendTxCode(code: string) {
this.InjiVciClient.sendTxCodeFromJS(code);
}
async sendIssuerConsent(consent: boolean) {
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: (
inputMode: string | undefined,
description: string | undefined,
length: number | undefined,
) => void,
getProofJwt: (
credentialIssuer: string,
cNonce: string | null,
proofSigningAlgosSupported: string[] | null,
) => void,
navigateToAuthView: (authorizationEndpoint: string) => void,
requestTokenResponse: (tokenRequest: object) => void,
requestTrustIssuerConsent: (
credentialIssuer: string,
issuerDisplay: object[],
) => void,
): Promise<any> {
const proofListener = emitter.addListener(
'onRequestProof',
({credentialIssuer, cNonce, proofSigningAlgorithmsSupported}) => {
getProofJwt(credentialIssuer, cNonce, JSON.parse(proofSigningAlgorithmsSupported));
},
);
const authListener = emitter.addListener(
'onRequestAuthCode',
({authorizationUrl}) => {
navigateToAuthView(authorizationUrl);
},
);
const txCodeListener = emitter.addListener(
'onRequestTxCode',
({inputMode, description, length}) => {
getTxCode(inputMode, description, length);
},
);
const tokenResponseListener = emitter.addListener(
'onRequestTokenResponse',
({tokenRequest}) => {
requestTokenResponse(tokenRequest);
},
);
const trustIssuerListener = emitter.addListener(
'onCheckIssuerTrust',
({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(clientMetadata),
);
} catch (error) {
console.error('Error requesting credential by offer:', error);
throw error;
} finally {
proofListener.remove();
authListener.remove();
txCodeListener.remove();
tokenResponseListener.remove();
trustIssuerListener.remove();
}
const parsedResponse = JSON.parse(response);
return {
credential: {
credential: parsedResponse.credential,
} as VerifiableCredential,
credentialConfigurationId:
parsedResponse.credentialConfigurationId ?? {},
credentialIssuer: parsedResponse.credentialIssuer ?? '',
};
}
async requestCredentialFromTrustedIssuer(
credentialIssuerUri: string,
credentialConfigurationId: string,
clientMetadata: object,
getProofJwt: (
credentialIssuer: string,
cNonce: string | null,
proofSigningAlgosSupported: string[] | null,
) => void,
navigateToAuthView: (authorizationEndpoint: string) => void,
requestTokenResponse: (tokenRequest: object) => void,
): Promise<any> {
const proofListener = emitter.addListener(
'onRequestProof',
({credentialIssuer, cNonce, proofSigningAlgorithmsSupported}) => {
getProofJwt(credentialIssuer, cNonce, JSON.parse(proofSigningAlgorithmsSupported));
},
);
const authListener = emitter.addListener(
'onRequestAuthCode',
({authorizationUrl}) => {
navigateToAuthView(authorizationUrl);
},
);
const tokenResponseListener = emitter.addListener(
'onRequestTokenResponse',
({tokenRequest}) => {
requestTokenResponse(tokenRequest);
},
);
let response = '';
try {
response = await this.InjiVciClient.requestCredentialFromTrustedIssuer(
credentialIssuerUri,
credentialConfigurationId,
JSON.stringify(clientMetadata),
);
} catch (error) {
console.error('Error requesting credential from trusted issuer:', error);
throw error;
} finally {
proofListener.remove();
authListener.remove();
tokenResponseListener.remove();
}
const parsedResponse = JSON.parse(response);
return {
credential: {
credential: parsedResponse.credential,
} as VerifiableCredential,
credentialConfigurationId:
parsedResponse.credentialConfigurationId ?? {},
credentialIssuer: parsedResponse.credentialIssuer ?? '',
};
}
}
export default VciClient;