From afb91b49dbf708da998aee8d181babfc886357ab Mon Sep 17 00:00:00 2001 From: Reinaldo Neto <47038980+reinaldonetof@users.noreply.github.com> Date: Mon, 21 Feb 2022 13:38:49 -0300 Subject: [PATCH] [FIX] Differ to Last Session Authenticated (#3667) * [FIX] Differ to Last Session Authenticated * Added timesync * [FIX] Differ to Last Session Authenticated * Added timesync * timesync tweaks * refactor diffLastLocalSession and saveLastLocalAuthentication * did a race * Update comment in app/utils/localAuthentication.ts Co-authored-by: Diego Mello * refactor getServerTimeSync and when use this route * tweak Co-authored-by: Diego Mello --- .../rocketchat/services/getServerTimeSync.ts | 16 ++++++++++ app/utils/localAuthentication.ts | 29 ++++++++++++++----- 2 files changed, 37 insertions(+), 8 deletions(-) create mode 100644 app/lib/rocketchat/services/getServerTimeSync.ts diff --git a/app/lib/rocketchat/services/getServerTimeSync.ts b/app/lib/rocketchat/services/getServerTimeSync.ts new file mode 100644 index 00000000..da50c07e --- /dev/null +++ b/app/lib/rocketchat/services/getServerTimeSync.ts @@ -0,0 +1,16 @@ +import RNFetchBlob from 'rn-fetch-blob'; + +export const getServerTimeSync = async (server: string) => { + try { + const response = await Promise.race([ + RNFetchBlob.fetch('GET', `${server}/_timesync`), + new Promise(res => setTimeout(res, 2000)) + ]); + if (response?.data) { + return parseInt(response.data); + } + return null; + } catch { + return null; + } +}; diff --git a/app/utils/localAuthentication.ts b/app/utils/localAuthentication.ts index b3b51ba8..141268b4 100644 --- a/app/utils/localAuthentication.ts +++ b/app/utils/localAuthentication.ts @@ -1,12 +1,13 @@ import * as LocalAuthentication from 'expo-local-authentication'; -import moment from 'moment'; import RNBootSplash from 'react-native-bootsplash'; import AsyncStorage from '@react-native-community/async-storage'; import { sha256 } from 'js-sha256'; +import moment from 'moment'; import UserPreferences from '../lib/userPreferences'; import { store } from '../lib/auxStore'; import database from '../lib/database'; +import { getServerTimeSync } from '../lib/rocketchat/services/getServerTimeSync'; import { ATTEMPTS_KEY, BIOMETRY_ENABLED_KEY, @@ -21,16 +22,25 @@ import { TServerModel } from '../definitions/IServer'; import EventEmitter from './events'; import { isIOS } from './deviceInfo'; -export const saveLastLocalAuthenticationSession = async (server: string, serverRecord?: TServerModel): Promise => { +export const saveLastLocalAuthenticationSession = async ( + server: string, + serverRecord?: TServerModel, + timesync?: number | null +): Promise => { + if (!timesync) { + timesync = new Date().getTime(); + } + const serversDB = database.servers; const serversCollection = serversDB.get('servers'); await serversDB.write(async () => { try { if (!serverRecord) { - serverRecord = (await serversCollection.find(server)) as TServerModel; + serverRecord = await serversCollection.find(server); } + const time = timesync || 0; await serverRecord.update(record => { - record.lastLocalAuthenticatedSession = new Date(); + record.lastLocalAuthenticatedSession = new Date(time); }); } catch (e) { // Do nothing @@ -103,6 +113,9 @@ export const localAuthenticate = async (server: string): Promise => { // if screen lock is enabled if (serverRecord?.autoLock) { + // Get time from server + const timesync = await getServerTimeSync(server); + // Make sure splash screen has been hidden try { await RNBootSplash.hide(); @@ -116,10 +129,10 @@ export const localAuthenticate = async (server: string): Promise => { // `checkHasPasscode` results newPasscode = true if a passcode has been set if (!result?.newPasscode) { // diff to last authenticated session - const diffToLastSession = moment().diff(serverRecord?.lastLocalAuthenticatedSession, 'seconds'); + const diffToLastSession = moment(timesync).diff(serverRecord?.lastLocalAuthenticatedSession, 'seconds'); - // if last authenticated session is older than configured auto lock time, authentication is required - if (diffToLastSession >= serverRecord.autoLockTime!) { + // if it was not possible to get `timesync` from server or the last authenticated session is older than the configured auto lock time, authentication is required + if (!timesync || (serverRecord?.autoLockTime && diffToLastSession >= serverRecord.autoLockTime)) { // set isLocalAuthenticated to false store.dispatch(setLocalAuthenticated(false)); @@ -141,7 +154,7 @@ export const localAuthenticate = async (server: string): Promise => { } await resetAttempts(); - await saveLastLocalAuthenticationSession(server, serverRecord); + await saveLastLocalAuthenticationSession(server, serverRecord, timesync); } };