summaryrefslogtreecommitdiffstats
path: root/webapp/components/user_settings/user_settings_security.jsx
diff options
context:
space:
mode:
authorJoram Wilander <jwawilander@gmail.com>2016-12-12 08:16:10 -0500
committerenahum <nahumhbl@gmail.com>2016-12-12 10:16:10 -0300
commit30a10d35a8406f4af96fcc8200c4e2173856837d (patch)
treea2cc82592b3c7f6b6901d64fb4a3003180b7b154 /webapp/components/user_settings/user_settings_security.jsx
parentf0d71d87899967335210b9130a7e2b8d180bef46 (diff)
downloadchat-30a10d35a8406f4af96fcc8200c4e2173856837d.tar.gz
chat-30a10d35a8406f4af96fcc8200c4e2173856837d.tar.bz2
chat-30a10d35a8406f4af96fcc8200c4e2173856837d.zip
PLT-4767 Implement MFA Enforcement (#4662)
* Create MFA setup page and remove MFA setup from account settings modal * Add enforce MFA to system console and force redirect * Lockdown mfa required API routes, add localization, other changes * Minor fixes * Fix typo * Fix some unit tests * Fix more unit tests * Minor fix * Updating UI for MFA screen (#4670) * Updating UI for MFA screen * Updating styles for MFA page * Add the ability to switch between email/sso with MFA enabled * Added mfa change email * Minor UI updates for MFA enforcement * Fix unit test * Fix client unit test * Allow switching email to ldap and back when MFA is enabled * Fix unit test * Revert config.json
Diffstat (limited to 'webapp/components/user_settings/user_settings_security.jsx')
-rw-r--r--webapp/components/user_settings/user_settings_security.jsx168
1 files changed, 53 insertions, 115 deletions
diff --git a/webapp/components/user_settings/user_settings_security.jsx b/webapp/components/user_settings/user_settings_security.jsx
index 5f231e499..3484b8183 100644
--- a/webapp/components/user_settings/user_settings_security.jsx
+++ b/webapp/components/user_settings/user_settings_security.jsx
@@ -9,8 +9,6 @@ import ToggleModalButton from '../toggle_modal_button.jsx';
import PreferenceStore from 'stores/preference_store.jsx';
-import {generateMfaSecret} from 'actions/user_actions.jsx';
-
import Client from 'client/web_client.jsx';
import * as AsyncClient from 'utils/async_client.jsx';
import * as Utils from 'utils/utils.jsx';
@@ -18,8 +16,8 @@ import Constants from 'utils/constants.jsx';
import $ from 'jquery';
import React from 'react';
-import {FormattedMessage, FormattedHTMLMessage, FormattedTime, FormattedDate} from 'react-intl';
-import {Link} from 'react-router/es6';
+import {FormattedMessage, FormattedTime, FormattedDate} from 'react-intl';
+import {browserHistory, Link} from 'react-router/es6';
import icon50 from 'images/icon50x50.png';
@@ -28,17 +26,15 @@ export default class SecurityTab extends React.Component {
super(props);
this.submitPassword = this.submitPassword.bind(this);
- this.activateMfa = this.activateMfa.bind(this);
+ this.setupMfa = this.setupMfa.bind(this);
this.deactivateMfa = this.deactivateMfa.bind(this);
this.updateCurrentPassword = this.updateCurrentPassword.bind(this);
this.updateNewPassword = this.updateNewPassword.bind(this);
this.updateConfirmPassword = this.updateConfirmPassword.bind(this);
- this.updateMfaToken = this.updateMfaToken.bind(this);
this.getDefaultState = this.getDefaultState.bind(this);
this.createPasswordSection = this.createPasswordSection.bind(this);
this.createSignInSection = this.createSignInSection.bind(this);
this.createOAuthAppsSection = this.createOAuthAppsSection.bind(this);
- this.showQrCode = this.showQrCode.bind(this);
this.deauthorizeApp = this.deauthorizeApp.bind(this);
this.state = this.getDefaultState();
@@ -51,9 +47,7 @@ export default class SecurityTab extends React.Component {
confirmPassword: '',
passwordError: '',
serverError: '',
- authService: this.props.user.auth_service,
- mfaShowQr: false,
- mfaToken: ''
+ authService: this.props.user.auth_service
};
}
@@ -119,26 +113,9 @@ export default class SecurityTab extends React.Component {
);
}
- activateMfa() {
- Client.updateMfa(
- this.state.mfaToken,
- true,
- () => {
- this.props.updateSection('');
- AsyncClient.getMe();
- this.setState(this.getDefaultState());
- },
- (err) => {
- const state = this.getDefaultState();
- if (err.message) {
- state.serverError = err.message;
- } else {
- state.serverError = err;
- }
- state.mfaError = '';
- this.setState(state);
- }
- );
+ setupMfa(e) {
+ e.preventDefault();
+ browserHistory.push('/mfa/setup');
}
deactivateMfa() {
@@ -146,6 +123,13 @@ export default class SecurityTab extends React.Component {
'',
false,
() => {
+ if (global.window.mm_license.MFA === 'true' &&
+ global.window.mm_config.EnableMultifactorAuthentication === 'true' &&
+ global.window.mm_config.EnforceMultifactorAuthentication === 'true') {
+ window.location.href = '/mfa/setup';
+ return;
+ }
+
this.props.updateSection('');
AsyncClient.getMe();
this.setState(this.getDefaultState());
@@ -157,7 +141,6 @@ export default class SecurityTab extends React.Component {
} else {
state.serverError = err;
}
- state.mfaError = '';
this.setState(state);
}
);
@@ -175,18 +158,6 @@ export default class SecurityTab extends React.Component {
this.setState({confirmPassword: e.target.value});
}
- updateMfaToken(e) {
- this.setState({mfaToken: e.target.value});
- }
-
- showQrCode(e) {
- e.preventDefault();
- generateMfaSecret(
- (data) => this.setState({mfaShowQr: true, secret: data.secret, qrCode: data.qr_code}),
- (err) => this.setState({serverError: err.message})
- );
- }
-
deauthorizeApp(e) {
e.preventDefault();
const appId = e.currentTarget.getAttribute('data-app');
@@ -212,6 +183,39 @@ export default class SecurityTab extends React.Component {
let content;
let extraInfo;
if (this.props.user.mfa_active) {
+ let mfaRemoveHelp;
+ let mfaButtonText;
+
+ if (global.window.mm_config.EnforceMultifactorAuthentication === 'true') {
+ mfaRemoveHelp = (
+ <FormattedMessage
+ id='user.settings.mfa.requiredHelp'
+ defaultMessage='Multi-factor authentication is required on this server. Resetting is only recommended when you need to switch code generation to a new mobile device. You will be required to set it up again immediately.'
+ />
+ );
+
+ mfaButtonText = (
+ <FormattedMessage
+ id='user.settings.mfa.reset'
+ defaultMessage='Reset MFA on your account'
+ />
+ );
+ } else {
+ mfaRemoveHelp = (
+ <FormattedMessage
+ id='user.settings.mfa.removeHelp'
+ defaultMessage='Removing multi-factor authentication means you will no longer require a phone-based passcode to sign-in to your account.'
+ />
+ );
+
+ mfaButtonText = (
+ <FormattedMessage
+ id='user.settings.mfa.remove'
+ defaultMessage='Remove MFA from your account'
+ />
+ );
+ }
+
content = (
<div key='mfaQrCode'>
<a
@@ -219,10 +223,7 @@ export default class SecurityTab extends React.Component {
href='#'
onClick={this.deactivateMfa}
>
- <FormattedMessage
- id='user.settings.mfa.remove'
- defaultMessage='Remove MFA from your account'
- />
+ {mfaButtonText}
</a>
<br/>
</div>
@@ -230,78 +231,16 @@ export default class SecurityTab extends React.Component {
extraInfo = (
<span>
- <FormattedMessage
- id='user.settings.mfa.removeHelp'
- defaultMessage='Removing multi-factor authentication will make your account more vulnerable to attacks.'
- />
+ {mfaRemoveHelp}
</span>
);
- } else if (this.state.mfaShowQr) {
- content = (
- <div key='mfaButton'>
- <div className='form-group'>
- <label className='col-sm-3 control-label'>
- <FormattedMessage
- id='user.settings.mfa.qrCode'
- defaultMessage='Bar Code'
- />
- </label>
- <div className='col-sm-5'>
- <img
- className='qr-code-img'
- src={'data:image/png;base64,' + this.state.qrCode}
- />
- </div>
- </div>
- <div className='form-group'>
- <label className='col-sm-3 control-label'>
- <FormattedMessage
- id='user.settings.mfa.secret'
- defaultMessage='Secret'
- />
- </label>
- <div className='col-sm-9 padding-top'>
- {this.state.secret}
- </div>
- </div>
- <hr/>
- <div className='form-group'>
- <label className='col-sm-5 control-label'>
- <FormattedMessage
- id='user.settings.mfa.enterToken'
- defaultMessage='Token (numbers only)'
- />
- </label>
- <div className='col-sm-7'>
- <input
- className='form-control'
- type='number'
- autoFocus={true}
- onChange={this.updateMfaToken}
- value={this.state.mfaToken}
- />
- </div>
- </div>
- </div>
- );
-
- extraInfo = (
- <span>
- <FormattedMessage
- id='user.settings.mfa.addHelpQr'
- defaultMessage='Please scan the QR code with the Google Authenticator app on your smartphone and fill in the token with one provided by the app. If you are unable to scan the code, you can manually enter the secret provided.'
- />
- </span>
- );
-
- submit = this.activateMfa;
} else {
content = (
<div key='mfaQrCode'>
<a
className='btn btn-primary'
href='#'
- onClick={this.showQrCode}
+ onClick={this.setupMfa}
>
<FormattedMessage
id='user.settings.mfa.add'
@@ -314,9 +253,9 @@ export default class SecurityTab extends React.Component {
extraInfo = (
<span>
- <FormattedHTMLMessage
+ <FormattedMessage
id='user.settings.mfa.addHelp'
- defaultMessage="You can require a smartphone-based token, in addition to your password, to sign into Mattermost.<br/><br/>To enable, download Google Authenticator from <a target='_blank' href='https://itunes.apple.com/us/app/google-authenticator/id388497605?mt=8'>iTunes</a> or <a target='_blank' href='https://play.google.com/store/apps/details?id=com.google.android.apps.authenticator2&hl=en'>Google Play</a> for your phone, then<br/><br/>1. Click the <strong>Add MFA to your account</strong> button above.<br/>2. Use Google Authenticator to scan the QR code that appears or type in the secret manually.<br/>3. Type in the Token generated by Google Authenticator and click <strong>Save</strong>.<br/><br/>When logging in, you will be asked to enter a token from Google Authenticator in addition to your regular credentials."
+ defaultMessage='Adding multi-factor authentication will make your account more secure by requiring a code from your mobile phone each time you sign in.'
/>
</span>
);
@@ -334,7 +273,7 @@ export default class SecurityTab extends React.Component {
updateSectionStatus = function resetSection(e) {
this.props.updateSection('');
- this.setState({mfaToken: '', mfaShowQr: false, mfaError: null, serverError: null});
+ this.setState({serverError: null});
e.preventDefault();
}.bind(this);
@@ -345,7 +284,6 @@ export default class SecurityTab extends React.Component {
extraInfo={extraInfo}
submit={submit}
server_error={this.state.serverError}
- client_error={this.state.mfaError}
updateSection={updateSectionStatus}
width='medium'
/>