Skip to content
Snippets Groups Projects

908 account recovery ability to add contacts to trusted contacts list for account recovery

Compare and
7 files
+ 1353
70
Compare changes
  • Side-by-side
  • Inline
Files
7
@@ -41,6 +41,12 @@ import {
STATUS_USER_BLOCKED
} from "../constants/statuses";
import generateQrCode from "../utilities/generateQrCode";
import {
generateRecoveryKey,
getRecoveryKeyShares,
checkRecoveryKeyCombine,
encryptShare
} from "../utilities/secrets";
const penpalMethods = require("../../temp/penpal-methods").default;
const WopiAPI = require("./wopiapi-iframe");
@@ -271,14 +277,13 @@ window.lastTimeGetProfile = 0;
let iframeParent = null;
const handleIdentityLogin = (identity, uuid, token) => {
const { loadedIdentities, viamApi } = window;
const { viamApi } = window;
const { publicKey } = identity.authentication;
viamApi.setSessionData(uuid, token);
localStorage.setItem("uuid", uuid);
localStorage.setItem("token", token);
localStorage.setItem("authenticatedIdentity", publicKey);
window.currentlyAuthenticatedIdentity = loadedIdentities[publicKey];
window.currentlyAuthenticatedIdentity = identity;
window.lastTimeGetProfile = 0;
setKeyForUUID(uuid, publicKey);
};
@@ -348,6 +353,7 @@ async function executeRestfulFunction(type, that, fn, config, ...args) {
null,
"previousaddeddevice"
);
if (loginResponse.data.code !== "200") {
return loginResponse.data;
}
@@ -434,7 +440,7 @@ function getCertificateForPassport(passportUUID, internal) {
const passportIdentity = window.currentlyAuthenticatedIdentity;
const passport = passportIdentity.getPassport(passportUUID);
if (passport === undefined || passport === null) {
createPassportCertificate(passportUUID).then(function(keys) {
createPassportCertificate(passportUUID).then(function (keys) {
const cryptoData = new CryptoData();
cryptoData.setPublicKey(keys["publicKeyPEM"]);
cryptoData.setPrivateKey(keys["privateKeyPEM"]);
@@ -552,7 +558,7 @@ const connection = Penpal.connectToParent({
...penpalMethods,
createIdentity(pinCode) {
return new Penpal.Promise(result => {
createPassportCertificate(makeid()).then(function(keys) {
createPassportCertificate(makeid()).then(function (keys) {
const newIdentity = new Identity();
const cryptoData = new CryptoData();
cryptoData.setPublicKey(keys["publicKeyPEM"]);
@@ -562,6 +568,10 @@ const connection = Penpal.connectToParent({
newIdentity.setPinCode(pinCode);
window.currentlyLoadedIdentity = newIdentity;
localStorage.setItem(
"currentlyLoadedIdentity",
JSON.stringify(newIdentity)
);
const { publicKey, x509Certificate } = newIdentity.authentication;
window.loadedIdentities[publicKey] = newIdentity;
@@ -724,10 +734,7 @@ const connection = Penpal.connectToParent({
});
});
},
finalizeEmployeeRegistration: async (
identity,
identifier
) => {
finalizeEmployeeRegistration: async (identity, identifier) => {
viamApi.setIdentity(identity.authentication.publicKey);
return executeRestfulFunction(
"public",
@@ -812,16 +819,9 @@ const connection = Penpal.connectToParent({
const responseToClient = Object.assign({}, identityLoginResponse);
if (code === "200") {
if (
mode === LOGIN_MODES.SMS ||
mode === LOGIN_MODES.PREVIOUSLY_ADDED_DEVICE
) {
if (mode === LOGIN_MODES.PREVIOUSLY_ADDED_DEVICE) {
handleIdentityLogin(loginIdentity, data.Uuid, data.Session);
await getProfileData(loginIdentity);
if (mode === LOGIN_MODES.SMS) {
await setIdentityInLocalStorage(loginIdentity);
}
} else if (mode === LOGIN_MODES.NEW_DEVICE) {
const dataUrl = await generateQrCode(
`${data.ActionID},${data.QrCode}`
@@ -977,6 +977,156 @@ const connection = Penpal.connectToParent({
});
});
},
identityInitiateSocialRecovery: async accessToken => {
const response = await executeRestfulFunction(
"public",
viamApi,
viamApi.identityInitiateSocialRecovery,
null,
accessToken
);
return response;
},
contactsCheckAccountRecoveryStatus: async () => {
const currentlyLoadedIdentity = localStorage.getItem(
"currentlyLoadedIdentity"
);
const parsedIdentity = JSON.parse(currentlyLoadedIdentity);
window.currentlyLoadedIdentity = parsedIdentity;
const { publicKey } = parsedIdentity.authentication;
window.loadedIdentities[publicKey] = parsedIdentity;
window.viamAnonymousApi.setIdentity(publicKey);
window.viamApi.setSessionData("", "");
window.viamApi.setIdentity(publicKey);
const timeout = ms => new Promise(resolve => setTimeout(resolve, ms));
async function checkAccountRecoveryStatus() {
const response = await executeRestfulFunction(
"public",
viamApi,
viamApi.contactsCheckAccountRecoveryStatus,
null
);
if (response.data === 0) {
await timeout(1000);
await checkAccountRecoveryStatus();
return;
}
const deviceHash = await createDeviceHash(publicKey);
window.viamApi.setDeviceHash(deviceHash);
const identityLoginResponse = await executeRestfulFunction(
"public",
window.viamApi,
window.viamApi.identityLogin,
null,
"previousaddeddevice"
);
const { code, data } = identityLoginResponse;
if (code === "200") {
await setIdentityInLocalStorage(parsedIdentity);
handleIdentityLogin(parsedIdentity, data.Uuid, data.Session);
await getProfileData(parsedIdentity);
localStorage.removeItem("currentlyLoadedIdentity");
}
}
await checkAccountRecoveryStatus();
},
contactsGetTrusteeContactsPublicKeys: async () => {
try {
const response = await executeRestfulFunction(
"private",
window.viamApi,
window.viamApi.contactsGetTrusteeContactsPublicKeys,
null
);
console.log({ response });
if (response.code !== "200") {
return response;
}
const responseData = response.data;
const trusteesDevices = Object.values(responseData);
/** Check if there are new trustees without added secret part */
const hasNewTrustees = trusteesDevices.some(device => {
const deviceData = Object.values(device);
return deviceData.some(data => data.hasShamir === "0");
});
console.log({ hasNewTrustees });
if (!hasNewTrustees) {
return response;
}
// Generate and split recovery key
const trusteesUuids = Object.keys(responseData);
const trusteesToDevices = Object.entries(responseData);
const sharesNumber = trusteesUuids.length;
const recoveryKey = generateRecoveryKey();
const recoveryKeyShares = getRecoveryKeyShares(
recoveryKey,
sharesNumber
);
console.log({ recoveryKeyShares });
const sanityCheckResponse = checkRecoveryKeyCombine(
recoveryKey,
recoveryKeyShares
);
console.log({ sanityCheckResponse });
if (sanityCheckResponse.code !== "200") {
return sanityCheckResponse;
}
// Encrypt each share with every publicKey of each contact device
const shamirPartsList = await Promise.all(
trusteesToDevices.map(async ([contactUuid, device], index) => {
const deviceIdsToPublicKeys = Object.entries(device);
// Encrypt secret shares in parallel
const deviceIdsToEncryptedPartsList = await Promise.all(
deviceIdsToPublicKeys.map(async ([deviceId, { content }]) => {
const encryptedShare = await encryptShare(
recoveryKeyShares[index],
content
);
return [deviceId, encryptedShare];
})
);
// Turn deviceIdsToEncryptedPartsList array to object
const deviceIdsToEncryptedParts = Object.fromEntries(
deviceIdsToEncryptedPartsList
);
return [contactUuid, deviceIdsToEncryptedParts];
})
);
// Turn shamirPartsList array to object
const shamirParts = Object.fromEntries(shamirPartsList);
// Save Shamir parts to database
const saveShamirPartsResponse = await executeRestfulFunction(
"private",
window.viamApi,
window.viamApi.contactsSaveShamirParts,
null,
shamirParts
);
if (saveShamirPartsResponse !== "200") {
return saveShamirPartsResponse;
}
return response;
} catch (error) {
return encodeResponse("400", "", error.message);
}
},
parseSMIME,
getCurrentlyLoggedInUUID() {
return new Penpal.Promise(result => {
@@ -1074,7 +1224,7 @@ const connection = Penpal.connectToParent({
emailArg,
passportPrivateKey,
passportCertificate
).then(function(keys) {
).then(function (keys) {
const publicKeyOneTime = keys["publicKeyPEM"];
const privateKeyOneTime = keys["privateKeyPEM"];
const certificateOneTime = keys["certificatePEM"];
@@ -1417,10 +1567,7 @@ const connection = Penpal.connectToParent({
vCardImageClaimValue = vCardClaimResponse.data;
}
if (
vCardImageClaimValue &&
"state" in vCardImageClaimValue
) {
if (vCardImageClaimValue && "state" in vCardImageClaimValue) {
return encodeResponse("200", vCardImageClaimValue.state, "OK");
}
@@ -1480,14 +1627,13 @@ message SignatureData {
return encodeResponse("400", "", "Identity not authenticated");
}
// Get vCard and QR Code Coordinates
let vCardImageData;
let vCardImageClaimValue;
let qrCodeImageData;
let qrCodeCoordinates = {fromL: -1, fromR: -1, toL: -1, toR: -1};
let qrCodeCoordinates = { fromL: -1, fromR: -1, toL: -1, toR: -1 };
if (signatureData) {
const vCardImageClaimName = "vCardImage";
@@ -1673,7 +1819,7 @@ message SignatureData {
let vCardImageClaimValue;
let qrCodeImageData;
let qrCodeCoordinates = {fromL: -1, fromR: -1, toL: -1, toR: -1};
let qrCodeCoordinates = { fromL: -1, fromR: -1, toL: -1, toR: -1 };
const vCardImageClaimName = "vCardImage";
const defaultTagName = "notag";
@@ -1809,7 +1955,6 @@ message SignatureData {
passportChain.reverse();
const signVCardResponse = await executeRestfulFunction(
"private",
window.viamApi,
@@ -1927,7 +2072,7 @@ message SignatureData {
return encodeResponse("200", response.data, "Document created");
},
getVcardWithQrCode: async (passportUUID, QRCodeContent = null) =>{
getVcardWithQrCode: async (passportUUID, QRCodeContent = null) => {
//TODO: IMPLEMENT QR CODE backend method needed
const authenticationPublicKey = localStorage.getItem(
"authenticatedIdentity"
@@ -1995,7 +2140,7 @@ message SignatureData {
);
}
}
return encodeResponse("200",vCardImageData, 'vCard got');
return encodeResponse("200", vCardImageData, "vCard got");
},
documentPutDocument: async (
passportUUID,
@@ -2413,7 +2558,7 @@ connection.promise.then(parent => {
let previousLocalStorageToken;
let previousLocalStorageIdentity;
setInterval(async function() {
setInterval(async function () {
if (window.currentlyAuthenticatedIdentity) {
const { authentication } = window.currentlyAuthenticatedIdentity;
const pinCode = getPincode(authentication.publicKey);
@@ -2458,6 +2603,8 @@ connection.promise.then(parent => {
identityAuthenticatedEvent = false;
window.currentlyLoadedIdentity = null;
}
localStorage.removeItem("currentlyLoadedIdentity");
}
if (window.currentlyLoadedIdentity) {
Loading