[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:
parent
8edcbc8390
commit
5794a0da4d
5 changed files with 30 additions and 24 deletions
|
|
@ -123,10 +123,6 @@ const state = {
|
|||
},
|
||||
},
|
||||
users: {
|
||||
checkMfa: {
|
||||
status: 'not_started',
|
||||
error: null,
|
||||
},
|
||||
login: {
|
||||
status: 'not_started',
|
||||
error: null,
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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'
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -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) => {
|
||||
|
|
|
|||
Loading…
Reference in a new issue