diff --git a/app/app.js b/app/app.js index 36846618d..f1c491923 100644 --- a/app/app.js +++ b/app/app.js @@ -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; diff --git a/app/mattermost.js b/app/mattermost.js index cb11fe909..0d11b7154 100644 --- a/app/mattermost.js +++ b/app/mattermost.js @@ -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); } }