Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions app/lib/rocketchat/services/getServerTimeSync.ts
Original file line number Diff line number Diff line change
@@ -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<undefined>(res => setTimeout(res, 2000))
]);
if (response?.data) {
return parseInt(response.data);
}
return null;
} catch {
return null;
}
};
29 changes: 21 additions & 8 deletions app/utils/localAuthentication.ts
Original file line number Diff line number Diff line change
@@ -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,
Expand All @@ -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<void> => {
export const saveLastLocalAuthenticationSession = async (
server: string,
serverRecord?: TServerModel,
timesync?: number | null
): Promise<void> => {
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
Expand Down Expand Up @@ -103,6 +113,9 @@ export const localAuthenticate = async (server: string): Promise<void> => {

// 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();
Expand All @@ -116,10 +129,10 @@ export const localAuthenticate = async (server: string): Promise<void> => {
// `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));

Expand All @@ -141,7 +154,7 @@ export const localAuthenticate = async (server: string): Promise<void> => {
}

await resetAttempts();
await saveLastLocalAuthenticationSession(server, serverRecord);
await saveLastLocalAuthenticationSession(server, serverRecord, timesync);
}
};

Expand Down