From 5b61d00533a1b73ad0e2f634a3a13bf98630d9a7 Mon Sep 17 00:00:00 2001 From: Matthew Hodgson Date: Tue, 24 Jan 2017 22:36:55 +0100 Subject: [PATCH 1/4] warn users that changing/resetting password will nuke E2E keys --- .../structures/login/ForgotPassword.js | 24 +++++++-- .../views/settings/ChangePassword.js | 53 ++++++++++++------- 2 files changed, 55 insertions(+), 22 deletions(-) diff --git a/src/components/structures/login/ForgotPassword.js b/src/components/structures/login/ForgotPassword.js index 5037136b1d..2c10052b98 100644 --- a/src/components/structures/login/ForgotPassword.js +++ b/src/components/structures/login/ForgotPassword.js @@ -87,10 +87,26 @@ module.exports = React.createClass({ this.showErrorDialog("New passwords must match each other."); } else { - this.submitPasswordReset( - this.state.enteredHomeserverUrl, this.state.enteredIdentityServerUrl, - this.state.email, this.state.password - ); + var QuestionDialog = sdk.getComponent("dialogs.QuestionDialog"); + Modal.createDialog(QuestionDialog, { + title: "Warning", + description: +
+ Resetting password will currently reset any end-to-end encryption keys on all devices, + making encrypted chat history unreadable. + In future this may be improved, + but for now be warned. +
, + button: "Continue", + onFinished: (confirmed) => { + if (confirmed) { + this.submitPasswordReset( + this.state.enteredHomeserverUrl, this.state.enteredIdentityServerUrl, + this.state.email, this.state.password + ); + } + }, + }); } }, diff --git a/src/components/views/settings/ChangePassword.js b/src/components/views/settings/ChangePassword.js index a011d5262e..8a3c46bcfd 100644 --- a/src/components/views/settings/ChangePassword.js +++ b/src/components/views/settings/ChangePassword.js @@ -18,6 +18,7 @@ limitations under the License. var React = require('react'); var MatrixClientPeg = require("../../../MatrixClientPeg"); +var Modal = require("../../../Modal"); var sdk = require("../../../index"); module.exports = React.createClass({ @@ -65,26 +66,42 @@ module.exports = React.createClass({ changePassword: function(old_password, new_password) { var cli = MatrixClientPeg.get(); - var authDict = { - type: 'm.login.password', - user: cli.credentials.userId, - password: old_password - }; + var QuestionDialog = sdk.getComponent("dialogs.QuestionDialog"); + Modal.createDialog(QuestionDialog, { + title: "Warning", + description: +
+ Changing password will currently reset any end-to-end encryption keys on all devices, + making encrypted chat history unreadable. + This will be improved shortly, + but for now be warned. +
, + button: "Continue", + onFinished: (confirmed) => { + if (confirmed) { + var authDict = { + type: 'm.login.password', + user: cli.credentials.userId, + password: old_password + }; - this.setState({ - phase: this.Phases.Uploading + this.setState({ + phase: this.Phases.Uploading + }); + + var self = this; + cli.setPassword(authDict, new_password).then(function() { + self.props.onFinished(); + }, function(err) { + self.props.onError(err); + }).finally(function() { + self.setState({ + phase: self.Phases.Edit + }); + }).done(); + } + }, }); - - var self = this; - cli.setPassword(authDict, new_password).then(function() { - self.props.onFinished(); - }, function(err) { - self.props.onError(err); - }).finally(function() { - self.setState({ - phase: self.Phases.Edit - }); - }).done(); }, onClickChange: function() { From b148619c527b4ee416b6e886846841d692a816ca Mon Sep 17 00:00:00 2001 From: Matthew Hodgson Date: Tue, 24 Jan 2017 22:47:03 +0100 Subject: [PATCH 2/4] warn on logout too --- src/Lifecycle.js | 43 ++++++++++++++++++++++++++++++------------- 1 file changed, 30 insertions(+), 13 deletions(-) diff --git a/src/Lifecycle.js b/src/Lifecycle.js index 493bbf12aa..64d22bd04c 100644 --- a/src/Lifecycle.js +++ b/src/Lifecycle.js @@ -22,6 +22,7 @@ import Notifier from './Notifier'; import UserActivity from './UserActivity'; import Presence from './Presence'; import dis from './dispatcher'; +import Modal from './Modal'; import DMRoomMap from './utils/DMRoomMap'; /** @@ -289,19 +290,35 @@ export function logout() { return; } - return MatrixClientPeg.get().logout().then(onLoggedOut, - (err) => { - // Just throwing an error here is going to be very unhelpful - // if you're trying to log out because your server's down and - // you want to log into a different server, so just forget the - // access token. It's annoying that this will leave the access - // token still valid, but we should fix this by having access - // tokens expire (and if you really think you've been compromised, - // change your password). - console.log("Failed to call logout API: token will not be invalidated"); - onLoggedOut(); - } - ); + var QuestionDialog = sdk.getComponent("dialogs.QuestionDialog"); + Modal.createDialog(QuestionDialog, { + title: "Warning", + description: +
+ For security, logging out will delete any end-to-end encryption keys from this browser, + making previous encrypted chat history unreadable if you log back in. + In future this will be improved, + but for now be warned. +
, + button: "Continue", + onFinished: (confirmed) => { + if (confirmed) { + MatrixClientPeg.get().logout().then(onLoggedOut, + (err) => { + // Just throwing an error here is going to be very unhelpful + // if you're trying to log out because your server's down and + // you want to log into a different server, so just forget the + // access token. It's annoying that this will leave the access + // token still valid, but we should fix this by having access + // tokens expire (and if you really think you've been compromised, + // change your password). + console.log("Failed to call logout API: token will not be invalidated"); + onLoggedOut(); + } + ); + } + }, + }); } /** From 6e55bb4956cd0e5d62352970f3f9ba892bd6b7fb Mon Sep 17 00:00:00 2001 From: Matthew Hodgson Date: Tue, 24 Jan 2017 23:15:00 +0100 Subject: [PATCH 3/4] actually, move signout warning to UserSettings.js also, kill off the inexplicably useless LogoutPrompt in favour of a normal QuestionDialog. This in turn fixes https://github.com/vector-im/riot-web/issues/2152 --- src/components/views/dialogs/LogoutPrompt.js | 61 -------------------- 1 file changed, 61 deletions(-) delete mode 100644 src/components/views/dialogs/LogoutPrompt.js diff --git a/src/components/views/dialogs/LogoutPrompt.js b/src/components/views/dialogs/LogoutPrompt.js deleted file mode 100644 index c4bd7a0474..0000000000 --- a/src/components/views/dialogs/LogoutPrompt.js +++ /dev/null @@ -1,61 +0,0 @@ -/* -Copyright 2015, 2016 OpenMarket Ltd - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ -var React = require('react'); -var dis = require("../../../dispatcher"); - -module.exports = React.createClass({ - displayName: 'LogoutPrompt', - - propTypes: { - onFinished: React.PropTypes.func, - }, - - logOut: function() { - dis.dispatch({action: 'logout'}); - if (this.props.onFinished) { - this.props.onFinished(); - } - }, - - cancelPrompt: function() { - if (this.props.onFinished) { - this.props.onFinished(); - } - }, - - onKeyDown: function(e) { - if (e.keyCode === 27) { // escape - e.stopPropagation(); - e.preventDefault(); - this.cancelPrompt(); - } - }, - - render: function() { - return ( -
-
- Sign out? -
-
- - -
-
- ); - } -}); - From 6a40abbbf063638e1008090a39e4735c9964a754 Mon Sep 17 00:00:00 2001 From: Matthew Hodgson Date: Tue, 24 Jan 2017 23:18:25 +0100 Subject: [PATCH 4/4] actually, move signout warning to UserSettings.js also, kill off the inexplicably useless LogoutPrompt in favour of a normal QuestionDialog. This in turn fixes https://github.com/vector-im/riot-web/issues/2152 --- src/Lifecycle.js | 43 +++++++---------------- src/component-index.js | 2 -- src/components/structures/UserSettings.js | 22 ++++++++++-- 3 files changed, 33 insertions(+), 34 deletions(-) diff --git a/src/Lifecycle.js b/src/Lifecycle.js index 64d22bd04c..493bbf12aa 100644 --- a/src/Lifecycle.js +++ b/src/Lifecycle.js @@ -22,7 +22,6 @@ import Notifier from './Notifier'; import UserActivity from './UserActivity'; import Presence from './Presence'; import dis from './dispatcher'; -import Modal from './Modal'; import DMRoomMap from './utils/DMRoomMap'; /** @@ -290,35 +289,19 @@ export function logout() { return; } - var QuestionDialog = sdk.getComponent("dialogs.QuestionDialog"); - Modal.createDialog(QuestionDialog, { - title: "Warning", - description: -
- For security, logging out will delete any end-to-end encryption keys from this browser, - making previous encrypted chat history unreadable if you log back in. - In future this will be improved, - but for now be warned. -
, - button: "Continue", - onFinished: (confirmed) => { - if (confirmed) { - MatrixClientPeg.get().logout().then(onLoggedOut, - (err) => { - // Just throwing an error here is going to be very unhelpful - // if you're trying to log out because your server's down and - // you want to log into a different server, so just forget the - // access token. It's annoying that this will leave the access - // token still valid, but we should fix this by having access - // tokens expire (and if you really think you've been compromised, - // change your password). - console.log("Failed to call logout API: token will not be invalidated"); - onLoggedOut(); - } - ); - } - }, - }); + return MatrixClientPeg.get().logout().then(onLoggedOut, + (err) => { + // Just throwing an error here is going to be very unhelpful + // if you're trying to log out because your server's down and + // you want to log into a different server, so just forget the + // access token. It's annoying that this will leave the access + // token still valid, but we should fix this by having access + // tokens expire (and if you really think you've been compromised, + // change your password). + console.log("Failed to call logout API: token will not be invalidated"); + onLoggedOut(); + } + ); } /** diff --git a/src/component-index.js b/src/component-index.js index e83de8739d..99882e784f 100644 --- a/src/component-index.js +++ b/src/component-index.js @@ -79,8 +79,6 @@ import views$dialogs$ErrorDialog from './components/views/dialogs/ErrorDialog'; views$dialogs$ErrorDialog && (module.exports.components['views.dialogs.ErrorDialog'] = views$dialogs$ErrorDialog); import views$dialogs$InteractiveAuthDialog from './components/views/dialogs/InteractiveAuthDialog'; views$dialogs$InteractiveAuthDialog && (module.exports.components['views.dialogs.InteractiveAuthDialog'] = views$dialogs$InteractiveAuthDialog); -import views$dialogs$LogoutPrompt from './components/views/dialogs/LogoutPrompt'; -views$dialogs$LogoutPrompt && (module.exports.components['views.dialogs.LogoutPrompt'] = views$dialogs$LogoutPrompt); import views$dialogs$NeedToRegisterDialog from './components/views/dialogs/NeedToRegisterDialog'; views$dialogs$NeedToRegisterDialog && (module.exports.components['views.dialogs.NeedToRegisterDialog'] = views$dialogs$NeedToRegisterDialog); import views$dialogs$QuestionDialog from './components/views/dialogs/QuestionDialog'; diff --git a/src/components/structures/UserSettings.js b/src/components/structures/UserSettings.js index 4a1332be8c..0231bc5038 100644 --- a/src/components/structures/UserSettings.js +++ b/src/components/structures/UserSettings.js @@ -228,8 +228,26 @@ module.exports = React.createClass({ }, onLogoutClicked: function(ev) { - var LogoutPrompt = sdk.getComponent('dialogs.LogoutPrompt'); - this.logoutModal = Modal.createDialog(LogoutPrompt); + var QuestionDialog = sdk.getComponent("dialogs.QuestionDialog"); + Modal.createDialog(QuestionDialog, { + title: "Sign out?", + description: +
+ For security, logging out will delete any end-to-end encryption keys from this browser, + making previous encrypted chat history unreadable if you log back in. + In future this will be improved, + but for now be warned. +
, + button: "Sign out", + onFinished: (confirmed) => { + if (confirmed) { + dis.dispatch({action: 'logout'}); + if (this.props.onFinished) { + this.props.onFinished(); + } + } + }, + }); }, onPasswordChangeError: function(err) {