[MM-14081] Show MFA Prompt after Server returned error for login request (#2599)

* Show MFA Prompt after Server returned error for login request

* eslint

* Hide MFA error on first login attempt
This commit is contained in:
Daniel Schalla 2019-03-01 19:01:10 +01:00 committed by GitHub
parent 8edcbc8390
commit 5794a0da4d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 30 additions and 24 deletions

View file

@ -123,10 +123,6 @@ const state = {
},
},
users: {
checkMfa: {
status: 'not_started',
error: null,
},
login: {
status: 'not_started',
error: null,

View file

@ -8,17 +8,16 @@ import LoginActions from 'app/actions/views/login';
import {getTheme} from 'mattermost-redux/selectors/entities/preferences';
import {getConfig, getLicense} from 'mattermost-redux/selectors/entities/general';
import {checkMfa, login} from 'mattermost-redux/actions/users';
import {login} from 'mattermost-redux/actions/users';
import Login from './login.js';
function mapStateToProps(state) {
const {checkMfa: checkMfaRequest, login: loginRequest} = state.requests.users;
const {login: loginRequest} = state.requests.users;
const config = getConfig(state);
const license = getLicense(state);
return {
...state.views.login,
checkMfaRequest,
loginRequest,
config,
license,
@ -30,7 +29,6 @@ function mapDispatchToProps(dispatch) {
return {
actions: bindActionCreators({
...LoginActions,
checkMfa,
login,
}, dispatch),
};

View file

@ -26,9 +26,12 @@ import {GlobalStyles} from 'app/styles';
import {preventDoubleTap} from 'app/utils/tap';
import tracker from 'app/utils/time_tracker';
import {t} from 'app/utils/i18n';
import {setMfaPreflightDone, getMfaPreflightDone} from 'app/utils/security';
import {RequestStatus} from 'mattermost-redux/constants';
const mfaExpectedErrors = ['mfa.validate_token.authenticate.app_error', 'ent.mfa.validate_token.authenticate.app_error'];
export default class Login extends PureComponent {
static propTypes = {
navigator: PropTypes.object,
@ -38,14 +41,12 @@ export default class Login extends PureComponent {
handlePasswordChanged: PropTypes.func.isRequired,
handleSuccessfulLogin: PropTypes.func.isRequired,
scheduleExpiredNotification: PropTypes.func.isRequired,
checkMfa: PropTypes.func.isRequired,
login: PropTypes.func.isRequired,
}).isRequired,
config: PropTypes.object.isRequired,
license: PropTypes.object.isRequired,
loginId: PropTypes.string.isRequired,
password: PropTypes.string.isRequired,
checkMfaRequest: PropTypes.object.isRequired,
loginRequest: PropTypes.object.isRequired,
};
@ -61,8 +62,9 @@ export default class Login extends PureComponent {
};
}
componentWillMount() {
componentDidMount() {
Dimensions.addEventListener('change', this.orientationDidChange);
setMfaPreflightDone(false);
}
componentWillReceiveProps(nextProps) {
@ -182,16 +184,7 @@ export default class Login extends PureComponent {
return;
}
if (this.props.config.EnableMultifactorAuthentication === 'true') {
const result = await this.props.actions.checkMfa(this.props.loginId);
if (result.data) {
this.goToMfa();
} else {
this.signIn();
}
} else {
this.signIn();
}
this.signIn();
});
});
@ -205,7 +198,13 @@ export default class Login extends PureComponent {
signIn = () => {
const {actions, loginId, loginRequest, password} = this.props;
if (loginRequest.status !== RequestStatus.STARTED) {
actions.login(loginId.toLowerCase(), password);
actions.login(loginId.toLowerCase(), password).then(this.checkLoginResponse);
}
};
checkLoginResponse = (data) => {
if (mfaExpectedErrors.includes(data?.error.server_error_id)) { // eslint-disable-line camelcase
this.goToMfa();
}
};
@ -245,7 +244,6 @@ export default class Login extends PureComponent {
getLoginErrorMessage = () => {
return (
this.getServerErrorForLogin() ||
this.props.checkMfaRequest.error ||
this.state.error
);
};
@ -259,6 +257,9 @@ export default class Login extends PureComponent {
if (!errorId) {
return error.message;
}
if (mfaExpectedErrors.includes(errorId) && !getMfaPreflightDone()) {
return null;
}
if (
errorId === 'store.sql_user.get_for_login.app_error' ||
errorId === 'ent.ldap.do_login.user_not_registered.app_error'

View file

@ -24,6 +24,7 @@ import TextInputWithLocalizedPlaceholder from 'app/components/text_input_with_lo
import {GlobalStyles} from 'app/styles';
import {preventDoubleTap} from 'app/utils/tap';
import {t} from 'app/utils/i18n';
import {setMfaPreflightDone} from 'app/utils/security';
export default class Mfa extends PureComponent {
static propTypes = {
@ -97,7 +98,7 @@ export default class Mfa extends PureComponent {
});
return;
}
setMfaPreflightDone(true);
this.props.actions.login(this.props.loginId, this.props.password, this.state.token);
});

View file

@ -5,6 +5,16 @@ import {Client4} from 'mattermost-redux/client';
import CookieManager from 'react-native-cookies';
import urlParse from 'url-parse';
let mfaPreflightDone = false;
export function setMfaPreflightDone(state) {
mfaPreflightDone = state;
}
export function getMfaPreflightDone() {
return mfaPreflightDone;
}
export function setCSRFFromCookie(url) {
return new Promise((resolve) => {
CookieManager.get(urlParse(url).origin, false).then((res) => {