Files
inji-wallet/shared/VCMetadata.ts
KiruthikaJeyashankar 82740bcc36 [INJIMOB-2471] set UUID as vc identifier (#1745)
* [INJIMOB-2471] make identifier of Vc as random UUID

Previously, we were relying on the id feild of the Vc to construct the unique identifier for VC component and file name for storing VC, this identifier in now replaced with random generated UUID. This was made since id property of VC is optional field as per w3c data-model 1.1.

We are using UUID version 4 to ensure randomness and collision-resistance.

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

* [INJIMOB-2471] maintain consistency in setting VCMetadata ID

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

* [INJICERT-2471] use VC metadata id as VC key

This VC key will be used for storing file name, component key & other identifier for VCs

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

* [INJIMOB-2471] remove setting identifier field in credential wrapper

The identitifier in credentialWrapper having the value "$issuer:$protocol:$UUID" was used to construct VC metadata id, issuer and protocol field which is already available in context param. This is now replaced with constructing VC metadata with the required fields available in machine context.

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

* [INJIMOB-2471] use context VCMetadata instead of calling function for accessing in issuersMachine

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

* [INJIMOB-2471] optimize import

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

---------

Signed-off-by: KiruthikaJeyashankar <kiruthikavjshankar@gmail.com>
2024-12-24 10:00:27 +05:30

172 lines
5.1 KiB
TypeScript

import {
Credential,
VC,
VcIdType,
VerifiableCredential,
} from '../machines/VerifiableCredential/VCMetaMachine/vc';
import {Protocols} from './openId4VCI/Utils';
import {getMosipIdentifier} from './commonUtil';
import {VCFormat} from './VCFormat';
import {isMosipVC, UUID} from './Utils';
import {getCredentialType} from '../components/VC/common/VCUtils';
const VC_KEY_PREFIX = 'VC';
const VC_ITEM_STORE_KEY_REGEX = '^VC_[a-zA-Z0-9_-]+$';
/** TODO: two identifiers requestId and id
* we have 2 fields in metadata - id, requestID
* requestID -> This will be holding the requestId required for OTP flow VCs and for OIDC flow it holds the generated UUID
* id -> holds UUID for both OTP based & OIDC flow
*/
export class VCMetadata {
static vcKeyRegExp = new RegExp(VC_ITEM_STORE_KEY_REGEX);
idType: VcIdType | string = '';
requestId = '';
isPinned = false;
id: string = '';
issuer?: string = '';
protocol?: string = '';
timestamp?: string = '';
isVerified: boolean = false;
mosipIndividualId: string = '';
format: string = '';
isExpired: boolean = false;
downloadKeyType: string = '';
credentialType: string = '';
issuerHost: string = '';
constructor({
idType = '',
requestId = '',
isPinned = false,
id = '',
issuer = '',
protocol = '',
timestamp = '',
isVerified = false,
mosipIndividualId = '',
format = '',
downloadKeyType = '',
isExpired = false,
credentialType = '',
issuerHost = '',
} = {}) {
this.idType = idType;
this.requestId = requestId;
this.isPinned = isPinned;
this.id = id;
this.protocol = protocol;
this.issuer = issuer;
this.timestamp = timestamp;
this.isVerified = isVerified;
this.mosipIndividualId = mosipIndividualId;
this.format = format;
this.downloadKeyType = downloadKeyType;
this.isExpired = isExpired;
this.credentialType = credentialType;
this.issuerHost = issuerHost;
}
//TODO: Remove any typing and use appropriate typing
static fromVC(vc: Partial<VC> | VCMetadata | any) {
return new VCMetadata({
idType: vc.idType,
format: vc.format || VCFormat.ldp_vc,
requestId: vc.requestId,
isPinned: vc.isPinned || false,
id: vc.id,
protocol: vc.protocol,
issuer: vc.issuer,
timestamp: vc.vcMetadata ? vc.vcMetadata.timestamp : vc.timestamp,
isVerified: vc.isVerified,
isExpired: vc.isExpired,
mosipIndividualId: vc.mosipIndividualId
? vc.mosipIndividualId
: vc.vcMetadata
? vc.vcMetadata.mosipIndividualId
: getMosipIndividualId(vc.verifiableCredential, vc.issuer),
downloadKeyType: vc.downloadKeyType,
credentialType: vc.credentialType,
issuerHost: vc.issuerHost,
});
}
static fromVcMetadataString(vcMetadataStr: string | object) {
try {
if (typeof vcMetadataStr === 'object')
return new VCMetadata(vcMetadataStr);
return new VCMetadata(JSON.parse(vcMetadataStr));
} catch (e) {
console.error('Failed to parse VC Metadata', e);
return new VCMetadata();
}
}
static isVCKey(key: string): boolean {
return VCMetadata.vcKeyRegExp.exec(key) != null;
}
isFromOpenId4VCI() {
return this.protocol === Protocols.OpenId4VCI;
}
// Used for mmkv storage purposes and as a key for components and vc maps
// Update VC_ITEM_STORE_KEY_REGEX in case of changes in vckey
getVcKey(): string {
return this.timestamp !== ''
? `${VC_KEY_PREFIX}_${this.timestamp}_${this.id}`
: `${VC_KEY_PREFIX}_${this.id}`;
}
equals(other: VCMetadata): boolean {
return this.getVcKey() === other.getVcKey();
}
}
export function parseMetadatas(metadataStrings: object[]) {
return metadataStrings.map(o => new VCMetadata(o));
}
export const getVCMetadata = (context: object, keyType: string) => {
const issuer = context.selectedIssuer.credential_issuer;
const credentialId = `${UUID.generate()}_${issuer}`;
return VCMetadata.fromVC({
requestId: credentialId,
issuer: issuer,
protocol: context.selectedIssuer.protocol,
id: credentialId,
timestamp: context.timestamp ?? '',
isVerified: context.vcMetadata.isVerified ?? false,
isExpired: context.vcMetadata.isExpired ?? false,
mosipIndividualId: getMosipIndividualId(
context['verifiableCredential'] as VerifiableCredential,
issuer,
),
format: context['credentialWrapper'].format,
downloadKeyType: keyType,
credentialType: getCredentialType(context.selectedCredentialType),
issuerHost: context.selectedIssuer.credential_issuer_host,
});
};
const getMosipIndividualId = (
verifiableCredential: VerifiableCredential | Credential,
issuer: string,
) => {
try {
const credential = verifiableCredential?.credential
? verifiableCredential.credential
: verifiableCredential;
const credentialSubject = credential?.credentialSubject;
if (isMosipVC(issuer)) {
return credentialSubject ? getMosipIdentifier(credentialSubject) : '';
}
return '';
} catch (error) {
console.error('Error getting the display ID:', error);
return null;
}
};