diff --git a/jslib/angular/src/services/auth-guard.service.ts b/jslib/angular/src/services/auth-guard.service.ts index 18011a90..a2d2ed89 100644 --- a/jslib/angular/src/services/auth-guard.service.ts +++ b/jslib/angular/src/services/auth-guard.service.ts @@ -4,12 +4,10 @@ import { ActivatedRouteSnapshot, Router, RouterStateSnapshot } from "@angular/ro import { KeyConnectorService } from "@/jslib/common/src/abstractions/keyConnector.service"; import { MessagingService } from "@/jslib/common/src/abstractions/messaging.service"; import { StateService } from "@/jslib/common/src/abstractions/state.service"; -import { VaultTimeoutService } from "@/jslib/common/src/abstractions/vaultTimeout.service"; @Injectable() export class AuthGuardService { constructor( - private vaultTimeoutService: VaultTimeoutService, private router: Router, private messagingService: MessagingService, private keyConnectorService: KeyConnectorService, @@ -23,15 +21,6 @@ export class AuthGuardService { return false; } - const locked = await this.vaultTimeoutService.isLocked(); - if (locked) { - if (routerState != null) { - this.messagingService.send("lockedUrl", { url: routerState.url }); - } - this.router.navigate(["lock"], { queryParams: { promptBiometric: true } }); - return false; - } - if ( !routerState.url.includes("remove-password") && (await this.keyConnectorService.getConvertAccountRequired()) diff --git a/jslib/angular/src/services/jslib-services.module.ts b/jslib/angular/src/services/jslib-services.module.ts index 78eeed54..bceb507d 100644 --- a/jslib/angular/src/services/jslib-services.module.ts +++ b/jslib/angular/src/services/jslib-services.module.ts @@ -28,7 +28,6 @@ import { SyncService as SyncServiceAbstraction } from "@/jslib/common/src/abstra import { TokenService as TokenServiceAbstraction } from "@/jslib/common/src/abstractions/token.service"; import { TwoFactorService as TwoFactorServiceAbstraction } from "@/jslib/common/src/abstractions/twoFactor.service"; import { UserVerificationService as UserVerificationServiceAbstraction } from "@/jslib/common/src/abstractions/userVerification.service"; -import { VaultTimeoutService as VaultTimeoutServiceAbstraction } from "@/jslib/common/src/abstractions/vaultTimeout.service"; import { StateFactory } from "@/jslib/common/src/factories/stateFactory"; import { Account } from "@/jslib/common/src/models/domain/account"; import { GlobalState } from "@/jslib/common/src/models/domain/globalState"; @@ -53,7 +52,6 @@ import { SyncService } from "@/jslib/common/src/services/sync.service"; import { TokenService } from "@/jslib/common/src/services/token.service"; import { TwoFactorService } from "@/jslib/common/src/services/twoFactor.service"; import { UserVerificationService } from "@/jslib/common/src/services/userVerification.service"; -import { VaultTimeoutService } from "@/jslib/common/src/services/vaultTimeout.service"; import { AuthGuardService } from "./auth-guard.service"; import { BroadcasterService } from "./broadcaster.service"; @@ -194,42 +192,6 @@ import { ValidationService } from "./validation.service"; useClass: SettingsService, deps: [StateServiceAbstraction], }, - { - provide: VaultTimeoutServiceAbstraction, - useFactory: ( - cryptoService: CryptoServiceAbstraction, - platformUtilsService: PlatformUtilsServiceAbstraction, - messagingService: MessagingServiceAbstraction, - searchService: SearchServiceAbstraction, - tokenService: TokenServiceAbstraction, - policyService: PolicyServiceAbstraction, - keyConnectorService: KeyConnectorServiceAbstraction, - stateService: StateServiceAbstraction, - ) => - new VaultTimeoutService( - cryptoService, - platformUtilsService, - messagingService, - searchService, - tokenService, - policyService, - keyConnectorService, - stateService, - null, - async (userId?: string) => - messagingService.send("logout", { expired: false, userId: userId }), - ), - deps: [ - CryptoServiceAbstraction, - PlatformUtilsServiceAbstraction, - MessagingServiceAbstraction, - SearchServiceAbstraction, - TokenServiceAbstraction, - PolicyServiceAbstraction, - KeyConnectorServiceAbstraction, - StateServiceAbstraction, - ], - }, { provide: StateServiceAbstraction, useFactory: ( @@ -276,7 +238,6 @@ import { ValidationService } from "./validation.service"; syncService: SyncServiceAbstraction, appIdService: AppIdServiceAbstraction, apiService: ApiServiceAbstraction, - vaultTimeoutService: VaultTimeoutServiceAbstraction, environmentService: EnvironmentServiceAbstraction, messagingService: MessagingServiceAbstraction, logService: LogService, @@ -286,7 +247,6 @@ import { ValidationService } from "./validation.service"; syncService, appIdService, apiService, - vaultTimeoutService, environmentService, async () => messagingService.send("logout", { expired: true }), logService, @@ -296,7 +256,6 @@ import { ValidationService } from "./validation.service"; SyncServiceAbstraction, AppIdServiceAbstraction, ApiServiceAbstraction, - VaultTimeoutServiceAbstraction, EnvironmentServiceAbstraction, MessagingServiceAbstraction, LogService, diff --git a/jslib/angular/src/services/lock-guard.service.ts b/jslib/angular/src/services/lock-guard.service.ts index 886320dc..ada7fd7c 100644 --- a/jslib/angular/src/services/lock-guard.service.ts +++ b/jslib/angular/src/services/lock-guard.service.ts @@ -2,23 +2,17 @@ import { Injectable } from "@angular/core"; import { Router } from "@angular/router"; import { StateService } from "@/jslib/common/src/abstractions/state.service"; -import { VaultTimeoutService } from "@/jslib/common/src/abstractions/vaultTimeout.service"; @Injectable() export class LockGuardService { protected homepage = "vault"; protected loginpage = "login"; constructor( - private vaultTimeoutService: VaultTimeoutService, private router: Router, private stateService: StateService, ) {} async canActivate() { - if (await this.vaultTimeoutService.isLocked()) { - return true; - } - const redirectUrl = (await this.stateService.getIsAuthenticated()) ? [this.homepage] : [this.loginpage]; diff --git a/jslib/angular/src/services/unauth-guard.service.ts b/jslib/angular/src/services/unauth-guard.service.ts index cae8d5a8..f1f95291 100644 --- a/jslib/angular/src/services/unauth-guard.service.ts +++ b/jslib/angular/src/services/unauth-guard.service.ts @@ -2,13 +2,11 @@ import { Injectable } from "@angular/core"; import { Router } from "@angular/router"; import { StateService } from "@/jslib/common/src/abstractions/state.service"; -import { VaultTimeoutService } from "@/jslib/common/src/abstractions/vaultTimeout.service"; @Injectable() export class UnauthGuardService { protected homepage = "vault"; constructor( - private vaultTimeoutService: VaultTimeoutService, private router: Router, private stateService: StateService, ) {} @@ -16,12 +14,7 @@ export class UnauthGuardService { async canActivate() { const isAuthed = await this.stateService.getIsAuthenticated(); if (isAuthed) { - const locked = await this.vaultTimeoutService.isLocked(); - if (locked) { - this.router.navigate(["lock"]); - } else { - this.router.navigate([this.homepage]); - } + this.router.navigate([this.homepage]); return false; } return true; diff --git a/jslib/common/src/abstractions/vaultTimeout.service.ts b/jslib/common/src/abstractions/vaultTimeout.service.ts deleted file mode 100644 index 2c2b2521..00000000 --- a/jslib/common/src/abstractions/vaultTimeout.service.ts +++ /dev/null @@ -1,11 +0,0 @@ -export abstract class VaultTimeoutService { - isLocked: (userId?: string) => Promise; - checkVaultTimeout: () => Promise; - lock: (allowSoftLock?: boolean, userId?: string) => Promise; - logOut: (userId?: string) => Promise; - setVaultTimeoutOptions: (vaultTimeout: number, vaultTimeoutAction: string) => Promise; - getVaultTimeout: () => Promise; - isPinLockSet: () => Promise<[boolean, boolean]>; - isBiometricLockSet: () => Promise; - clear: (userId?: string) => Promise; -} diff --git a/jslib/common/src/services/notifications.service.ts b/jslib/common/src/services/notifications.service.ts index 258ab389..d12bc4ad 100644 --- a/jslib/common/src/services/notifications.service.ts +++ b/jslib/common/src/services/notifications.service.ts @@ -8,7 +8,6 @@ import { LogService } from "../abstractions/log.service"; import { NotificationsService as NotificationsServiceAbstraction } from "../abstractions/notifications.service"; import { StateService } from "../abstractions/state.service"; import { SyncService } from "../abstractions/sync.service"; -import { VaultTimeoutService } from "../abstractions/vaultTimeout.service"; import { NotificationType } from "../enums/notificationType"; import { NotificationResponse, @@ -26,7 +25,6 @@ export class NotificationsService implements NotificationsServiceAbstraction { private syncService: SyncService, private appIdService: AppIdService, private apiService: ApiService, - private vaultTimeoutService: VaultTimeoutService, private environmentService: EnvironmentService, private logoutCallback: () => Promise, private logService: LogService, @@ -182,11 +180,7 @@ export class NotificationsService implements NotificationsServiceAbstraction { } private async isAuthedAndUnlocked() { - if (await this.stateService.getIsAuthenticated()) { - const locked = await this.vaultTimeoutService.isLocked(); - return !locked; - } - return false; + return await this.stateService.getIsAuthenticated() } private random(min: number, max: number) { diff --git a/jslib/common/src/services/vaultTimeout.service.ts b/jslib/common/src/services/vaultTimeout.service.ts deleted file mode 100644 index 503c96df..00000000 --- a/jslib/common/src/services/vaultTimeout.service.ts +++ /dev/null @@ -1,215 +0,0 @@ -import { firstValueFrom } from "rxjs"; - -import { CryptoService } from "../abstractions/crypto.service"; -import { KeyConnectorService } from "../abstractions/keyConnector.service"; -import { MessagingService } from "../abstractions/messaging.service"; -import { PlatformUtilsService } from "../abstractions/platformUtils.service"; -import { PolicyService } from "../abstractions/policy.service"; -import { SearchService } from "../abstractions/search.service"; -import { StateService } from "../abstractions/state.service"; -import { TokenService } from "../abstractions/token.service"; -import { VaultTimeoutService as VaultTimeoutServiceAbstraction } from "../abstractions/vaultTimeout.service"; -import { KeySuffixOptions } from "../enums/keySuffixOptions"; -import { PolicyType } from "../enums/policyType"; - -export class VaultTimeoutService implements VaultTimeoutServiceAbstraction { - private inited = false; - - constructor( - private cryptoService: CryptoService, - protected platformUtilsService: PlatformUtilsService, - private messagingService: MessagingService, - private searchService: SearchService, - private tokenService: TokenService, - private policyService: PolicyService, - private keyConnectorService: KeyConnectorService, - private stateService: StateService, - private lockedCallback: (userId?: string) => Promise = null, - private loggedOutCallback: (userId?: string) => Promise = null, - ) {} - - init(checkOnInterval: boolean) { - if (this.inited) { - return; - } - - this.inited = true; - if (checkOnInterval) { - this.startCheck(); - } - } - - startCheck() { - this.checkVaultTimeout(); - setInterval(() => this.checkVaultTimeout(), 10 * 1000); // check every 10 seconds - } - - // Keys aren't stored for a device that is locked or logged out. - async isLocked(userId?: string): Promise { - const neverLock = - (await this.cryptoService.hasKeyStored(KeySuffixOptions.Auto, userId)) && - !(await this.stateService.getEverBeenUnlocked({ userId: userId })); - if (neverLock) { - // TODO: This also _sets_ the key so when we check memory in the next line it finds a key. - // We should refactor here. - await this.cryptoService.getKey(KeySuffixOptions.Auto, userId); - } - - return !(await this.cryptoService.hasKeyInMemory(userId)); - } - - async checkVaultTimeout(): Promise { - if (await this.platformUtilsService.isViewOpen()) { - return; - } - - const accounts = await firstValueFrom(this.stateService.accounts$); - for (const userId in accounts) { - if (userId != null && (await this.shouldLock(userId))) { - await this.executeTimeoutAction(userId); - } - } - } - - async lock(allowSoftLock = false, userId?: string): Promise { - const authed = await this.stateService.getIsAuthenticated({ userId: userId }); - if (!authed) { - return; - } - - if (await this.keyConnectorService.getUsesKeyConnector()) { - const pinSet = await this.isPinLockSet(); - const pinLock = - (pinSet[0] && (await this.stateService.getDecryptedPinProtected()) != null) || pinSet[1]; - - if (!pinLock && !(await this.isBiometricLockSet())) { - await this.logOut(userId); - } - } - - if (userId == null || userId === (await this.stateService.getUserId())) { - this.searchService.clearIndex(); - } - - await this.stateService.setEverBeenUnlocked(true, { userId: userId }); - await this.stateService.setBiometricLocked(true, { userId: userId }); - await this.stateService.setCryptoMasterKeyAuto(null, { userId: userId }); - - await this.cryptoService.clearKey(false, userId); - await this.cryptoService.clearOrgKeys(true, userId); - await this.cryptoService.clearKeyPair(true, userId); - await this.cryptoService.clearEncKey(true, userId); - - this.messagingService.send("locked", { userId: userId }); - - if (this.lockedCallback != null) { - await this.lockedCallback(userId); - } - } - - async logOut(userId?: string): Promise { - if (this.loggedOutCallback != null) { - await this.loggedOutCallback(userId); - } - } - - async setVaultTimeoutOptions(timeout: number, action: string): Promise { - await this.stateService.setVaultTimeout(timeout); - - // We swap these tokens from being on disk for lock actions, and in memory for logout actions - // Get them here to set them to their new location after changing the timeout action and clearing if needed - const token = await this.tokenService.getToken(); - const refreshToken = await this.tokenService.getRefreshToken(); - const clientId = await this.tokenService.getClientId(); - const clientSecret = await this.tokenService.getClientSecret(); - - const currentAction = await this.stateService.getVaultTimeoutAction(); - if ((timeout != null || timeout === 0) && action === "logOut" && action !== currentAction) { - // if we have a vault timeout and the action is log out, reset tokens - await this.tokenService.clearToken(); - } - - await this.stateService.setVaultTimeoutAction(action); - - await this.tokenService.setToken(token); - await this.tokenService.setRefreshToken(refreshToken); - await this.tokenService.setClientId(clientId); - await this.tokenService.setClientSecret(clientSecret); - - await this.cryptoService.toggleKey(); - } - - async isPinLockSet(): Promise<[boolean, boolean]> { - const protectedPin = await this.stateService.getProtectedPin(); - const pinProtectedKey = await this.stateService.getEncryptedPinProtected(); - return [protectedPin != null, pinProtectedKey != null]; - } - - async isBiometricLockSet(): Promise { - return await this.stateService.getBiometricUnlock(); - } - - async getVaultTimeout(userId?: string): Promise { - const vaultTimeout = await this.stateService.getVaultTimeout({ userId: userId }); - - if ( - await this.policyService.policyAppliesToUser(PolicyType.MaximumVaultTimeout, null, userId) - ) { - const policy = await this.policyService.getAll(PolicyType.MaximumVaultTimeout, userId); - // Remove negative values, and ensure it's smaller than maximum allowed value according to policy - let timeout = Math.min(vaultTimeout, policy[0].data.minutes); - - if (vaultTimeout == null || timeout < 0) { - timeout = policy[0].data.minutes; - } - - // We really shouldn't need to set the value here, but multiple services relies on this value being correct. - if (vaultTimeout !== timeout) { - await this.stateService.setVaultTimeout(timeout, { userId: userId }); - } - - return timeout; - } - - return vaultTimeout; - } - - async clear(userId?: string): Promise { - await this.stateService.setEverBeenUnlocked(false, { userId: userId }); - await this.stateService.setDecryptedPinProtected(null, { userId: userId }); - await this.stateService.setProtectedPin(null, { userId: userId }); - } - - private async isLoggedOut(userId?: string): Promise { - return !(await this.stateService.getIsAuthenticated({ userId: userId })); - } - - private async shouldLock(userId: string): Promise { - if (await this.isLoggedOut(userId)) { - return false; - } - - if (await this.isLocked(userId)) { - return false; - } - - const vaultTimeout = await this.getVaultTimeout(userId); - if (vaultTimeout == null || vaultTimeout < 0) { - return false; - } - - const lastActive = await this.stateService.getLastActive({ userId: userId }); - if (lastActive == null) { - return false; - } - - const vaultTimeoutSeconds = vaultTimeout * 60; - const diffSeconds = (new Date().getTime() - lastActive) / 1000; - return diffSeconds >= vaultTimeoutSeconds; - } - - private async executeTimeoutAction(userId: string): Promise { - const timeoutAction = await this.stateService.getVaultTimeoutAction({ userId: userId }); - timeoutAction === "logOut" ? await this.logOut(userId) : await this.lock(true, userId); - } -}