Skip to content
This repository has been archived by the owner on Jun 7, 2023. It is now read-only.

Commit

Permalink
Shared: Remove 2FA from all versions (#1292)
Browse files Browse the repository at this point in the history
* Mobile: Remove 2FA

* Shared: Remove 2FA strings and actions/reducers

* Desktop: Remove 2fa

* Desktop: Revert shrinkwrap changes

* Desktop: Add initVault method

* Update lockfiles
  • Loading branch information
cvarley100 committed Apr 15, 2019
1 parent 917d90b commit e10f6d0
Show file tree
Hide file tree
Showing 32 changed files with 16,596 additions and 17,420 deletions.
6 changes: 0 additions & 6 deletions src/desktop/native/Menu.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ let language = {
node: 'Node',
currency: 'Currency',
theme: 'Theme',
twoFA: 'Two-factor authentication',
changePassword: 'Change password',
advanced: 'Advanced settings',
hide: 'Hide',
Expand Down Expand Up @@ -207,11 +206,6 @@ export const initMenu = (app, getWindowFunc) => {
{
type: 'separator',
},
{
label: language.twoFA,
enabled: state.authorised && state.enabled,
click: () => navigate('settings/twoFa'),
},
{
label: language.changePassword,
enabled: state.authorised && state.enabled,
Expand Down
1 change: 0 additions & 1 deletion src/desktop/native/preload/Electron.js
Original file line number Diff line number Diff line change
Expand Up @@ -530,7 +530,6 @@ const Electron = {
node: t('node'),
currency: t('settings:currency'),
theme: t('settings:theme'),
twoFA: t('settings:twoFA'),
changePassword: t('settings:changePassword'),
advanced: t('settings:advanced'),
hide: t('settings:hide'),
Expand Down
32,246 changes: 16,563 additions & 15,683 deletions src/desktop/npm-shrinkwrap.json

Large diffs are not rendered by default.

1 change: 0 additions & 1 deletion src/desktop/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,6 @@
"@babel/register": "7.4.0",
"@ledgerhq/hw-transport-node-hid": "4.50.0",
"argon2": "rihardsgravis/node-argon2#ae1a860",
"authenticator": "1.1.5",
"babel-polyfill": "6.26.0",
"bugsnag-js": "4.7.3",
"bugsnag-react": "1.1.1",
Expand Down
21 changes: 6 additions & 15 deletions src/desktop/src/libs/crypto.js
Original file line number Diff line number Diff line change
Expand Up @@ -96,22 +96,15 @@ export const decrypt = async (cipherText, hash) => {
};

/**
* Set Two-Factor authentication key
* Sets up main account in keychain
* @param {string} Password - Plain text password for decryption
* @param {string} Key - Two-factor authentication key
* @returns {boolean} Two-Factor key set success state
* @returns {boolean}
*/
export const setTwoFA = async (password, key) => {
export const initVault = async (password) => {
try {
const vault = await Electron.readKeychain(ACC_MAIN);
const decryptedVault = vault === null ? {} : await decrypt(vault, password);

if (key) {
decryptedVault.twoFaKey = key;
} else {
delete decryptedVault.twoFaKey;
}

const updatedVault = await encrypt(decryptedVault, password);

await Electron.setKeychain(ACC_MAIN, updatedVault);
Expand All @@ -135,18 +128,16 @@ export const initKeychain = async () => {
/**
* Check for valid vault key
* @param {array} Key - Account decryption key
* @returns {boolean | string} - Returns a Two-Factor authentication code or boolean of none set
* @returns {boolean | string}
*/
export const authorize = async (key) => {
const vault = await Electron.readKeychain(ACC_MAIN);

if (!vault) {
throw new Error('Local storage not available');
}
try {
const decryptedVault = await decrypt(vault, key);
if (decryptedVault.twoFaKey) {
return decryptedVault.twoFaKey;
}
await decrypt(vault, key);
return true;
} catch (err) {
throw err;
Expand Down
62 changes: 4 additions & 58 deletions src/desktop/src/ui/components/modal/Password.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,11 @@ import React, { PureComponent } from 'react';
import PropTypes from 'prop-types';
import { withI18n } from 'react-i18next';
import { connect } from 'react-redux';
import authenticator from 'authenticator';

import { hash, authorize } from 'libs/crypto';

import { generateAlert } from 'actions/alerts';
import { TWOFA_TOKEN_LENGTH } from 'libs/utils';

import Text from 'ui/components/input/Text';
import Password from 'ui/components/input/Password';
import Button from 'ui/components/Button';
import Modal from 'ui/components/modal/Modal';
Expand All @@ -29,8 +26,6 @@ class ModalPassword extends PureComponent {
isOpen: PropTypes.bool,
/** Should the dialog be without a cancel option */
isForced: PropTypes.bool,
/** Should 2fa authorisation be skipped */
skip2fa: PropTypes.bool,
/** Modal inline style state */
inline: PropTypes.bool,
/** On dialog close event */
Expand Down Expand Up @@ -59,8 +54,6 @@ class ModalPassword extends PureComponent {

state = {
password: '',
code: '',
verifyTwoFA: false,
};

componentWillReceiveProps(nextProps) {
Expand All @@ -75,17 +68,9 @@ class ModalPassword extends PureComponent {
setTimeout(() => Electron.garbageCollect(), 1000);
}

/**
* Update 2fa code value and trigger authentication once necessary length is reached
* @param {string} value - Code value
*/
setCode = (value) => {
this.setState({ code: value }, () => value.length === TWOFA_TOKEN_LENGTH && this.handleSubmit());
};

handleSubmit = async (e) => {
const { password, code, verifyTwoFA } = this.state;
const { skip2fa, onSuccess, onSubmit, generateAlert, t } = this.props;
const { password } = this.state;
const { onSuccess, onSubmit, generateAlert, t } = this.props;

if (e) {
e.preventDefault();
Expand All @@ -95,25 +80,10 @@ class ModalPassword extends PureComponent {
return onSubmit(password);
}

let authorised = false;

const passwordHash = await hash(password);

try {
authorised = await authorize(passwordHash);

if (!skip2fa && typeof authorised === 'string' && !authenticator.verifyToken(authorised, code)) {
if (verifyTwoFA) {
generateAlert('error', t('twoFA:wrongCode'), t('twoFA:wrongCodeExplanation'));
}

this.setState({
verifyTwoFA: true,
code: '',
});

return;
}
await authorize(passwordHash);
} catch (err) {
generateAlert(
'error',
Expand Down Expand Up @@ -155,36 +125,12 @@ class ModalPassword extends PureComponent {
);
};

twoFaContent = () => {
const { isForced, onClose, t } = this.props;
const { code } = this.state;
return (
<React.Fragment>
<p>{t('twoFA:enterCode')}</p>
<form onSubmit={(e) => this.handleSubmit(e)}>
<Text value={code} focus label={t('twoFA:code')} onChange={this.setCode} />
<footer>
{!isForced && (
<Button onClick={() => onClose()} variant="dark">
{t('cancel')}
</Button>
)}
<Button type="submit" variant="primary">
{t('login:login')}
</Button>
</footer>
</form>
</React.Fragment>
);
};

render() {
const { isOpen, isForced, inline, onClose } = this.props;
const { verifyTwoFA } = this.state;

return (
<Modal variant="confirm" isOpen={isOpen} inline={inline} isForced={isForced} onClose={() => onClose()}>
{verifyTwoFA ? this.twoFaContent() : this.passwordContent()}
{this.passwordContent()}
</Modal>
);
}
Expand Down
2 changes: 1 addition & 1 deletion src/desktop/src/ui/global/Idle.js
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ class Idle extends React.Component {
if (!this.state.locked) {
return null;
}
return <ModalPassword isOpen isForced skip2fa content={{}} onSuccess={(password) => this.unlock(password)} />;
return <ModalPassword isOpen isForced content={{}} onSuccess={(password) => this.unlock(password)} />;
}
}

Expand Down
4 changes: 2 additions & 2 deletions src/desktop/src/ui/views/onboarding/AccountPassword.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { generateAlert } from 'actions/alerts';
import { setPassword } from 'actions/wallet';

import SeedStore from 'libs/SeedStore';
import { hash, initKeychain, setTwoFA } from 'libs/crypto';
import { hash, initKeychain, initVault } from 'libs/crypto';
import { passwordReasons } from 'libs/password';

import Button from 'ui/components/Button';
Expand Down Expand Up @@ -95,7 +95,7 @@ class AccountPassword extends React.PureComponent {

const passwordHash = await hash(password);

await setTwoFA(passwordHash, null);
await initVault(passwordHash);
setPassword(passwordHash);

this.props.setAccountInfoDuringSetup({
Expand Down
54 changes: 3 additions & 51 deletions src/desktop/src/ui/views/onboarding/Login.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import React from 'react';
import PropTypes from 'prop-types';
import { withI18n } from 'react-i18next';
import { connect } from 'react-redux';
import authenticator from 'authenticator';

import { generateAlert } from 'actions/alerts';
import { getMarketData, getChartData, getPrice } from 'actions/marketData';
Expand All @@ -12,17 +11,14 @@ import { getAccountInfo, getFullAccountInfo } from 'actions/accounts';
import { clearWalletData, setPassword } from 'actions/wallet';

import { getSelectedAccountName, getSelectedAccountMeta, isSettingUpNewAccount } from 'selectors/accounts';
import { TWOFA_TOKEN_LENGTH } from 'libs/utils';

import { capitalize } from 'libs/iota/converter';
import { hash, authorize } from 'libs/crypto';
import SeedStore from 'libs/SeedStore';

import PasswordInput from 'ui/components/input/Password';
import Text from 'ui/components/input/Text';
import Button from 'ui/components/Button';
import Loading from 'ui/components/Loading';
import Modal from 'ui/components/modal/Modal';

import Migration from 'ui/global/Migration';

Expand Down Expand Up @@ -76,8 +72,6 @@ class Login extends React.Component {
};

state = {
verifyTwoFA: false,
code: '',
password: '',
shouldMigrate: false,
};
Expand Down Expand Up @@ -105,14 +99,6 @@ class Login extends React.Component {
setTimeout(() => Electron.garbageCollect(), 1000);
}

/**
* Update 2fa code value and trigger authentication once necessary length is reached
* @param {string} value - Code value
*/
setCode = (value) => {
this.setState({ code: value }, () => value.length === TWOFA_TOKEN_LENGTH && this.handleSubmit());
};

/**
* Update current input password value
* @param {string} password - Password value
Expand Down Expand Up @@ -163,7 +149,7 @@ class Login extends React.Component {
};

/**
* Verify password and 2fa code, trigger account setup
* Verify password and trigger account setup
* @param {event} Event - Form submit event
* @returns {undefined}
*/
Expand All @@ -172,7 +158,7 @@ class Login extends React.Component {
e.preventDefault();
}

const { password, code, verifyTwoFA } = this.state;
const { password } = this.state;
const { setPassword, generateAlert, t, completedMigration } = this.props;

let passwordHash = null;
Expand All @@ -186,19 +172,6 @@ class Login extends React.Component {

try {
authorised = await authorize(passwordHash);

if (typeof authorised === 'string' && !authenticator.verifyToken(authorised, code)) {
if (verifyTwoFA) {
generateAlert('error', t('twoFA:wrongCode'), t('twoFA:wrongCodeExplanation'));
}

this.setState({
verifyTwoFA: true,
code: '',
});

return;
}
} catch (err) {
generateAlert('error', t('unrecognisedPassword'), t('unrecognisedPasswordExplanation'));
}
Expand All @@ -208,8 +181,6 @@ class Login extends React.Component {

this.setState({
password: '',
code: '',
verifyTwoFA: false,
});

if (!completedMigration) {
Expand All @@ -231,7 +202,7 @@ class Login extends React.Component {

render() {
const { forceUpdate, t, addingAdditionalAccount, ui, completedMigration } = this.props;
const { verifyTwoFA, code, shouldMigrate } = this.state;
const { shouldMigrate } = this.state;

if (ui.isFetchingAccountInfo) {
return (
Expand Down Expand Up @@ -269,25 +240,6 @@ class Login extends React.Component {
</Button>
</footer>
</form>
<Modal variant="confirm" isOpen={verifyTwoFA} onClose={() => this.setState({ verifyTwoFA: false })}>
<p>{t('twoFA:enterCode')}</p>
<form onSubmit={(e) => this.handleSubmit(e)}>
<Text value={code} focus={verifyTwoFA} label={t('twoFA:code')} onChange={this.setCode} />
<footer>
<Button
onClick={() => {
this.setState({ verifyTwoFA: false });
}}
variant="dark"
>
{t('back')}
</Button>
<Button type="submit" variant="primary">
{t('login:login')}
</Button>
</footer>
</form>
</Modal>
</React.Fragment>
);
}
Expand Down
5 changes: 0 additions & 5 deletions src/desktop/src/ui/views/settings/Index.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ import Currency from 'ui/views/settings/Currency';
import Password from 'ui/views/settings/Password';
import Mode from 'ui/views/settings/Mode';
import Advanced from 'ui/views/settings/Advanced';
import TwoFA from 'ui/views/settings/TwoFA';

import AccountName from 'ui/views/settings/account/Name';
import AccountSeed from 'ui/views/settings/account/Seed';
Expand Down Expand Up @@ -94,9 +93,6 @@ class Settings extends React.PureComponent {
<Icon icon="password" size={16} />{' '}
<strong>{t('settings:changePassword')}</strong>
</NavLink>
<NavLink to="/settings/twoFa">
<Icon icon="twoFA" size={16} /> <strong>{t('settings:twoFA')}</strong>
</NavLink>
<hr />
<NavLink to="/settings/mode">
<Icon icon="mode" size={16} /> <strong>{t('settings:mode')}</strong>
Expand Down Expand Up @@ -167,7 +163,6 @@ class Settings extends React.PureComponent {
<Route path="/settings/node" component={SetNode} />
<Route path="/settings/currency" component={Currency} />
<Route path="/settings/password" component={Password} />
<Route path="/settings/twoFa" component={TwoFA} />
<Route path="/settings/mode" component={Mode} />
<Route path="/settings/advanced" component={Advanced} />
<Route
Expand Down
Loading

0 comments on commit e10f6d0

Please sign in to comment.