From fc4b3294f1c2c9cb02cd0a3116de74b8943381a5 Mon Sep 17 00:00:00 2001 From: Tom Hacohen Date: Wed, 20 Nov 2019 16:46:42 +0200 Subject: [PATCH] Login screen: gracefully handle wrong encryption passwords. --- src/LoginGate.tsx | 37 ++++++++++++++++++++++++++----------- 1 file changed, 26 insertions(+), 11 deletions(-) diff --git a/src/LoginGate.tsx b/src/LoginGate.tsx index 03f6cc5..facb47e 100644 --- a/src/LoginGate.tsx +++ b/src/LoginGate.tsx @@ -1,5 +1,7 @@ import * as React from 'react'; +import { Action } from 'redux-actions'; + import Container from './widgets/Container'; import ExternalLink from './widgets/ExternalLink'; import SyncGate from './SyncGate'; @@ -9,22 +11,24 @@ import EncryptionLoginForm from './components/EncryptionLoginForm'; import { store, CredentialsType } from './store'; import { deriveKey, fetchCredentials, fetchUserInfo } from './store/actions'; +import * as EteSync from 'etesync'; import * as C from './constants'; import SignedPagesBadge from './images/signed-pages-badge.svg'; import LoadingIndicator from './widgets/LoadingIndicator'; -function EncryptionPart(props: { credentials: CredentialsType, onEncryptionFormSubmit: (encryptionPassword: string) => void }) { +function EncryptionPart(props: { credentials: CredentialsType }) { const [fetched, setFetched] = React.useState(false); - const [isNewUser, setIsNewUser] = React.useState(false); + const [userInfo, setUserInfo] = React.useState(); + const [error, setError] = React.useState(); const credentials = props.credentials.value!; React.useEffect(() => { // FIXME: verify the error is a 404 - store.dispatch(fetchUserInfo(credentials, credentials.credentials.email)).catch(() => { - setIsNewUser(true); + store.dispatch(fetchUserInfo(credentials, credentials.credentials.email)).then((fetchedUserInfo: Action) => { + setUserInfo(fetchedUserInfo.payload); }).finally(() => { setFetched(true); }); @@ -34,6 +38,21 @@ function EncryptionPart(props: { credentials: CredentialsType, onEncryptionFormS return ; } + function onEncryptionFormSubmit(encryptionPassword: string) { + const derivedAction = deriveKey(props.credentials.value!.credentials.email, encryptionPassword); + if (userInfo) { + const userInfoCryptoManager = userInfo.getCryptoManager(derivedAction.payload!); + try { + userInfo.verify(userInfoCryptoManager); + } catch (e) { + setError(new EteSync.EncryptionPasswordError('Wrong encryption password')); + return; + } + } + store.dispatch(derivedAction); + } + + const isNewUser = !userInfo; return ( @@ -53,7 +72,8 @@ function EncryptionPart(props: { credentials: CredentialsType, onEncryptionFormS } ); @@ -68,7 +88,6 @@ class LoginGate extends React.Component { constructor(props: any) { super(props); this.onFormSubmit = this.onFormSubmit.bind(this); - this.onEncryptionFormSubmit = this.onEncryptionFormSubmit.bind(this); } public onFormSubmit(username: string, password: string, serviceApiUrl?: string) { @@ -76,10 +95,6 @@ class LoginGate extends React.Component { store.dispatch(fetchCredentials(username, password, serviceApiUrl)); } - public onEncryptionFormSubmit(encryptionPassword: string) { - store.dispatch(deriveKey(this.props.credentials.value!.credentials.email, encryptionPassword)); - } - public render() { if (this.props.credentials.value === null) { const style = { @@ -118,7 +133,7 @@ class LoginGate extends React.Component { ); } else if (this.props.credentials.value.encryptionKey === null) { return ( - + ); }