MM-15643 Fix race condition to prompt for passcode and (#2862)

detect if passcode has been removed while the app in the background
This commit is contained in:
Elias Nahum 2019-06-05 11:08:01 -04:00 committed by GitHub
parent 89c2e66dfd
commit 457413196e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 28 additions and 27 deletions

View file

@ -31,6 +31,7 @@ export default class App {
// Usage: app.js
this.shouldRelaunchWhenActive = false;
this.inBackgroundSince = null;
this.previousAppState = null;
// Usage: screen/entry.js
this.startAppFromPushNotification = false;

View file

@ -49,7 +49,7 @@ import telemetry from 'app/telemetry';
import App from './app';
import './fetch_preconfig';
const AUTHENTICATION_TIMEOUT = 5 * 60 * 1000;
const PROMPT_IN_APP_PIN_CODE_AFTER = 5 * 60 * 1000;
// Hide warnings caused by React Native (https://github.com/facebook/react-native/issues/20841)
YellowBox.ignoreWarnings(['Require cycle: node_modules/react-native/Libraries/Network/fetch.js']);
@ -322,25 +322,27 @@ export const handleManagedConfig = async (eventFromEmmServer = false) => {
return true;
};
const handleAuthentication = async (vendor) => {
const handleAuthentication = async (vendor, prompt = true) => {
app.setPerformingEMMAuthentication(true);
const isSecured = await mattermostManaged.isDeviceSecure();
const translations = app.getTranslations();
if (isSecured) {
try {
mattermostBucket.setPreference('emm', vendor);
await mattermostManaged.authenticate({
reason: translations[t('mobile.managed.secured_by')].replace('{vendor}', vendor),
fallbackToPasscode: true,
suppressEnterPassword: true,
});
if (prompt) {
await mattermostManaged.authenticate({
reason: translations[t('mobile.managed.secured_by')].replace('{vendor}', vendor),
fallbackToPasscode: true,
suppressEnterPassword: true,
});
}
} catch (err) {
mattermostManaged.quitApp();
return false;
}
} else {
await showNotSecuredAlert(vendor);
await showNotSecuredAlert(vendor, translations);
mattermostManaged.quitApp();
return false;
@ -350,9 +352,7 @@ const handleAuthentication = async (vendor) => {
return true;
};
function showNotSecuredAlert(vendor) {
const translations = app.getTranslations();
function showNotSecuredAlert(vendor, translations) {
return new Promise((resolve) => {
const options = [];
@ -425,20 +425,20 @@ const launchChannel = () => {
const handleAppStateChange = (appState) => {
const isActive = appState === 'active';
const isBackground = appState === 'background';
store.dispatch(setAppState(isActive));
if (isActive) {
if (isActive && app.previousAppState === 'background') {
handleAppActive();
return;
} else if (isBackground) {
handleAppInActive();
}
handleAppInActive();
app.previousAppState = appState;
};
const handleAppActive = async () => {
const authExpired = (Date.now() - app.inBackgroundSince) >= AUTHENTICATION_TIMEOUT;
// This handles when the app was started in the background
// cause of an iOS push notification reply
if (Platform.OS === 'ios' && app.shouldRelaunchWhenActive) {
@ -446,16 +446,16 @@ const handleAppActive = async () => {
app.setShouldRelaunchWhenActive(false);
}
// Once the app becomes active after more than 5 minutes in the background and is controlled by an EMM Provider
if (app.emmEnabled && app.inBackgroundSince && authExpired) {
try {
const config = await mattermostManaged.getConfig();
const authNeeded = config.inAppPinCode === 'true';
if (authNeeded) {
await handleAuthentication(config.vendor);
}
} catch (error) {
// do nothing
// if the app is being controlled by an EMM provider
if (app.emmEnabled) {
const config = await mattermostManaged.getConfig();
const authNeeded = config.inAppPinCode === 'true';
const authExpired = (Date.now() - app.inBackgroundSince) >= PROMPT_IN_APP_PIN_CODE_AFTER;
// Once the app becomes active we check if the device needs to have a passcode set
if (authNeeded) {
const prompt = app.inBackgroundSince && authExpired; // if more than 5 minutes have passed prompt for passcode
await handleAuthentication(config.vendor, prompt);
}
}