Skip to content

Commit

Permalink
A0-3946: Fix password saving function not working properly
Browse files Browse the repository at this point in the history
  • Loading branch information
Roberts committed Feb 2, 2024
1 parent 77b1b52 commit 311133b
Show file tree
Hide file tree
Showing 2 changed files with 75 additions and 13 deletions.
29 changes: 16 additions & 13 deletions packages/extension-base/src/background/handlers/Extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import type { SubjectInfo } from '@polkadot/ui-keyring/observable/types';
import type { KeypairType } from '@polkadot/util-crypto/types';
import type { AccountJson, AllowedPath, MessageTypes, RequestAccountChangePassword, RequestAccountCreateHardware, RequestAccountCreateSuri, RequestAccountEdit, RequestAccountExport, RequestAccountForget, RequestAccountShow, RequestAccountTie, RequestAccountValidate, RequestActiveTabUrlUpdate, RequestAuthorizeApprove, RequestAuthorizeReject, RequestBatchRestore, RequestDeriveCreate, RequestDeriveValidate, RequestJsonRestore, RequestMetadataApprove, RequestMetadataReject, RequestSeedCreate, RequestSeedValidate, RequestSigningApprovePassword, RequestSigningApproveSignature, RequestSigningCancel, RequestSigningIsLocked, RequestTypes, RequestUpdateAuthorizedAccounts, ResponseAccountExport, ResponseAuthorizeList, ResponseDeriveValidate, ResponseJsonGetAccountInfo, ResponseSeedCreate, ResponseSeedValidate, ResponseSigningIsLocked } from '../types';

import { ALLOWED_PATH, PASSWORD_EXPIRY_MS } from '@polkadot/extension-base/defaults';
import { ALLOWED_PATH } from '@polkadot/extension-base/defaults';
import { isJsonAuthentic, signJson } from '@polkadot/extension-base/utils/accountJsonIntegrity';
import { metadataExpand } from '@polkadot/extension-chains';
import { wrapBytes } from '@polkadot/extension-dapp';
Expand All @@ -18,13 +18,12 @@ import { accounts as accountsObservable } from '@polkadot/ui-keyring/observable/
import { assert, isHex, u8aToHex } from '@polkadot/util';
import { keyExtractSuri, mnemonicGenerate, mnemonicValidate } from '@polkadot/util-crypto';

import chromeStorage from './chromeStorage';
import { POPUP_CREATE_WINDOW_DATA } from './consts';
import { openCenteredWindow } from './helpers';
import State from './State';
import { createSubscription, unsubscribe } from './subscriptions';

type CachedUnlocks = Record<string, number>;

type GetContentPort = (tabId: number) => chrome.runtime.Port

const SEED_DEFAULT_LENGTH = 12;
Expand All @@ -40,12 +39,9 @@ function isJsonPayload (value: SignerPayloadJSON | SignerPayloadRaw): value is S
}

export default class Extension {
readonly #cachedUnlocks: CachedUnlocks;

readonly #state: State;

constructor (state: State) {
this.#cachedUnlocks = {};
this.#state = state;
}

Expand Down Expand Up @@ -137,14 +133,15 @@ export default class Extension {
return true;
}

private refreshAccountPasswordCache (pair: KeyringPair): number {
private async refreshAccountPasswordCache (pair: KeyringPair): Promise<number> {
const { address } = pair;

const savedExpiry = this.#cachedUnlocks[address] || 0;
const savedExpiry = await chromeStorage.getPasswordExpiry(address);

const remainingTime = savedExpiry - Date.now();

if (remainingTime < 0) {
this.#cachedUnlocks[address] = 0;
await chromeStorage.removePassword(address);
pair.lock();

return 0;
Expand Down Expand Up @@ -351,7 +348,7 @@ export default class Extension {
throw error;
}

this.refreshAccountPasswordCache(pair);
await this.refreshAccountPasswordCache(pair);

// if the keyring pair is locked, the password is needed
if (pair.isLocked && !password) {
Expand Down Expand Up @@ -412,9 +409,15 @@ export default class Extension {
// unlike queued.account.address the following
// address is encoded with the default prefix
// which what is used for password caching mapping
this.#cachedUnlocks[pair.address] = Date.now() + PASSWORD_EXPIRY_MS;
await chromeStorage.setPassword(pair.address);
} else {
pair.lock();
const savedExpiry = await chromeStorage.getPasswordExpiry(pair.address);

const remainingTime = savedExpiry - Date.now();

if (remainingTime <= 0) {
pair.lock();
}
}

await this.#state.removeSignRequest(id);
Expand Down Expand Up @@ -449,7 +452,7 @@ export default class Extension {

assert(pair, 'Unable to find pair');

const remainingTime = this.refreshAccountPasswordCache(pair);
const remainingTime = await this.refreshAccountPasswordCache(pair);

return {
isLocked: pair.isLocked,
Expand Down
59 changes: 59 additions & 0 deletions packages/extension-base/src/background/handlers/chromeStorage.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import { z } from 'zod';

import { PASSWORD_EXPIRY_MS } from '../../defaults';

const addressSchema = z.string();
const passwordSchema = z.record(z.string(), z.number());

async function getPasswordExpiry (address: string): Promise<number> {
if (addressSchema.safeParse(address).success) {
const { savePass } = await chrome.storage.session.get('savePass');

const pass = passwordSchema.safeParse(savePass);

if (pass.success) {
return pass.data[address];
} else {
return 0;
}
} else {
return 0;
}
}

async function setPassword (address: string): Promise<void> {
if (addressSchema.safeParse(address).success) {
const { savePass } = await chrome.storage.session.get('savePass');

const savedPasswords = passwordSchema.safeParse(savePass);

if (savedPasswords.success) {
await chrome.storage.session.set({ savePass: { ...savedPasswords.data, [address]: Date.now() + PASSWORD_EXPIRY_MS } });
} else {
await chrome.storage.session.set({ savePass: { [address]: Date.now() + PASSWORD_EXPIRY_MS } });
}
} else {
console.error('Provided address did not pass validation');
}
}

async function removePassword (address: string): Promise<void> {
if (addressSchema.safeParse(address).success) {
const { savePass } = await chrome.storage.session.get('savePass');

const pass = passwordSchema.safeParse(savePass);

if (pass.success) {
delete pass.data[address];
await chrome.storage.session.set({ savePass: pass.data });
}
}
}

const chromeStorage = {
setPassword,
getPasswordExpiry,
removePassword
};

export default chromeStorage;

0 comments on commit 311133b

Please sign in to comment.