[Auto-Logout] Refactor LockService and Update Dependencies (#91)

* initial commit for lockService name refactor

* Reverted ConstantsService vault timeout key to legacy string value

Co-authored-by: Vincent Salucci <vsalucci@bitwarden.com>
This commit is contained in:
Vincent Salucci 2020-03-27 09:03:27 -05:00 committed by GitHub
parent 31a257407b
commit 64c54cfb86
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 48 additions and 35 deletions

View File

@ -8,7 +8,6 @@ export { CryptoService } from './crypto.service';
export { EnvironmentService } from './environment.service';
export { FolderService } from './folder.service';
export { I18nService } from './i18n.service';
export { LockService } from './lock.service';
export { LogService } from './log.service';
export { MessagingService } from './messaging.service';
export { PasswordGenerationService } from './passwordGeneration.service';
@ -21,3 +20,4 @@ export { SyncService } from './sync.service';
export { TokenService } from './token.service';
export { TotpService } from './totp.service';
export { UserService } from './user.service';
export { VaultTimeoutService } from './vaultTimeout.service';

View File

@ -14,6 +14,9 @@ export abstract class PlatformUtilsService {
isMacAppStore: () => boolean;
analyticsId: () => string;
isViewOpen: () => Promise<boolean>;
/**
* @deprecated This only ever returns null. Pull from your platform's storage using ConstantsService.vaultTimeoutKey
*/
lockTimeout: () => number;
launchUri: (uri: string, options?: any) => void;
saveFile: (win: Window, blobData: any, blobOptions: any, fileName: string) => void;

View File

@ -1,11 +1,12 @@
import { CipherString } from '../models/domain/cipherString';
export abstract class LockService {
export abstract class VaultTimeoutService {
pinProtectedKey: CipherString;
isLocked: () => Promise<boolean>;
checkLock: () => Promise<void>;
checkVaultTimeout: () => Promise<void>;
lock: (allowSoftLock?: boolean) => Promise<void>;
setLockOption: (lockOption: number) => Promise<void>;
logout: () => Promise<void>;
setVaultTimeoutOptions: (vaultTimeout: number, vaultTimeoutAction: string) => Promise<void>;
isPinLockSet: () => Promise<[boolean, boolean]>;
clear: () => Promise<any>;
}

View File

@ -4,12 +4,12 @@ import { Router } from '@angular/router';
import { CryptoService } from '../../abstractions/crypto.service';
import { EnvironmentService } from '../../abstractions/environment.service';
import { I18nService } from '../../abstractions/i18n.service';
import { LockService } from '../../abstractions/lock.service';
import { MessagingService } from '../../abstractions/messaging.service';
import { PlatformUtilsService } from '../../abstractions/platformUtils.service';
import { StateService } from '../../abstractions/state.service';
import { StorageService } from '../../abstractions/storage.service';
import { UserService } from '../../abstractions/user.service';
import { VaultTimeoutService } from '../../abstractions/vaultTimeout.service';
import { ConstantsService } from '../../services/constants.service';
@ -35,12 +35,12 @@ export class LockComponent implements OnInit {
constructor(protected router: Router, protected i18nService: I18nService,
protected platformUtilsService: PlatformUtilsService, protected messagingService: MessagingService,
protected userService: UserService, protected cryptoService: CryptoService,
protected storageService: StorageService, protected lockService: LockService,
protected storageService: StorageService, protected vaultTimeoutService: VaultTimeoutService,
protected environmentService: EnvironmentService, protected stateService: StateService) { }
async ngOnInit() {
this.pinSet = await this.lockService.isPinLockSet();
this.pinLock = (this.pinSet[0] && this.lockService.pinProtectedKey != null) || this.pinSet[1];
this.pinSet = await this.vaultTimeoutService.isPinLockSet();
this.pinLock = (this.pinSet[0] && this.vaultTimeoutService.pinProtectedKey != null) || this.pinSet[1];
this.email = await this.userService.getEmail();
let vaultUrl = this.environmentService.getWebVaultUrl();
if (vaultUrl == null) {
@ -69,7 +69,7 @@ export class LockComponent implements OnInit {
try {
if (this.pinSet[0]) {
const key = await this.cryptoService.makeKeyFromPin(this.pin, this.email, kdf, kdfIterations,
this.lockService.pinProtectedKey);
this.vaultTimeoutService.pinProtectedKey);
const encKey = await this.cryptoService.getEncKey(key);
const protectedPin = await this.storageService.get<string>(ConstantsService.protectedPin);
const decPin = await this.cryptoService.decryptToUtf8(new CipherString(protectedPin), encKey);
@ -106,7 +106,7 @@ export class LockComponent implements OnInit {
const encKey = await this.cryptoService.getEncKey(key);
const decPin = await this.cryptoService.decryptToUtf8(new CipherString(protectedPin), encKey);
const pinKey = await this.cryptoService.makePinKey(decPin, this.email, kdf, kdfIterations);
this.lockService.pinProtectedKey = await this.cryptoService.encrypt(key.key, pinKey);
this.vaultTimeoutService.pinProtectedKey = await this.cryptoService.encrypt(key.key, pinKey);
}
this.setKeyAndContinue(key);
} else {

View File

@ -6,14 +6,14 @@ import {
RouterStateSnapshot,
} from '@angular/router';
import { LockService } from '../../abstractions/lock.service';
import { MessagingService } from '../../abstractions/messaging.service';
import { UserService } from '../../abstractions/user.service';
import { VaultTimeoutService } from '../../abstractions/vaultTimeout.service';
@Injectable()
export class AuthGuardService implements CanActivate {
constructor(private lockService: LockService, private userService: UserService, private router: Router,
private messagingService: MessagingService) { }
constructor(private vaultTimeoutService: VaultTimeoutService, private userService: UserService,
private router: Router, private messagingService: MessagingService) { }
async canActivate(route: ActivatedRouteSnapshot, routerState: RouterStateSnapshot) {
const isAuthed = await this.userService.isAuthenticated();
@ -22,7 +22,7 @@ export class AuthGuardService implements CanActivate {
return false;
}
const locked = await this.lockService.isLocked();
const locked = await this.vaultTimeoutService.isLocked();
if (locked) {
if (routerState != null) {
this.messagingService.send('lockedUrl', { url: routerState.url });

View File

@ -7,7 +7,8 @@ export class ConstantsService {
static readonly disableFaviconKey: string = 'disableFavicon';
static readonly disableAutoTotpCopyKey: string = 'disableAutoTotpCopy';
static readonly enableAutoFillOnPageLoadKey: string = 'enableAutoFillOnPageLoad';
static readonly lockOptionKey: string = 'lockOption';
static readonly vaultTimeoutKey: string = 'lockOption';
static readonly vaultTimeoutActionKey: string = 'vaultTimeoutAction';
static readonly lastActiveKey: string = 'lastActive';
static readonly neverDomainsKey: string = 'neverDomains';
static readonly installedVersionKey: string = 'installedVersion';
@ -30,7 +31,8 @@ export class ConstantsService {
readonly disableFaviconKey: string = ConstantsService.disableFaviconKey;
readonly disableAutoTotpCopyKey: string = ConstantsService.disableAutoTotpCopyKey;
readonly enableAutoFillOnPageLoadKey: string = ConstantsService.enableAutoFillOnPageLoadKey;
readonly lockOptionKey: string = ConstantsService.lockOptionKey;
readonly vaultTimeoutKey: string = ConstantsService.vaultTimeoutKey;
readonly vaultTimeoutActionKey: string = ConstantsService.vaultTimeoutActionKey;
readonly lastActiveKey: string = ConstantsService.lastActiveKey;
readonly neverDomainsKey: string = ConstantsService.neverDomainsKey;
readonly installedVersionKey: string = ConstantsService.installedVersionKey;

View File

@ -19,10 +19,10 @@ import { Utils } from '../misc/utils';
import { EEFLongWordList } from '../misc/wordlist';
const Keys = {
key: 'key',
key: 'key', // Master Key
encOrgKeys: 'encOrgKeys',
encPrivateKey: 'encPrivateKey',
encKey: 'encKey',
encKey: 'encKey', // Generated Symmetric Key
keyHash: 'keyHash',
};
@ -41,7 +41,7 @@ export class CryptoService implements CryptoServiceAbstraction {
async setKey(key: SymmetricCryptoKey): Promise<any> {
this.key = key;
const option = await this.storageService.get<number>(ConstantsService.lockOptionKey);
const option = await this.storageService.get<number>(ConstantsService.vaultTimeoutKey);
if (option != null) {
// if we have a lock option set, we do not store the key
return;
@ -290,7 +290,7 @@ export class CryptoService implements CryptoServiceAbstraction {
async toggleKey(): Promise<any> {
const key = await this.getKey();
const option = await this.storageService.get(ConstantsService.lockOptionKey);
const option = await this.storageService.get(ConstantsService.vaultTimeoutKey);
if (option != null || option === 0) {
// if we have a lock option set, clear the key
await this.clearKey();

View File

@ -10,7 +10,6 @@ export { CryptoService } from './crypto.service';
export { EnvironmentService } from './environment.service';
export { FolderService } from './folder.service';
export { I18nService } from './i18n.service';
export { LockService } from './lock.service';
export { PasswordGenerationService } from './passwordGeneration.service';
export { SettingsService } from './settings.service';
export { StateService } from './state.service';
@ -18,3 +17,4 @@ export { SyncService } from './sync.service';
export { TokenService } from './token.service';
export { TotpService } from './totp.service';
export { UserService } from './user.service';
export { VaultTimeoutService } from './vaultTimeout.service';

View File

@ -6,10 +6,10 @@ import { NotificationType } from '../enums/notificationType';
import { ApiService } from '../abstractions/api.service';
import { AppIdService } from '../abstractions/appId.service';
import { EnvironmentService } from '../abstractions/environment.service';
import { LockService } from '../abstractions/lock.service';
import { NotificationsService as NotificationsServiceAbstraction } from '../abstractions/notifications.service';
import { SyncService } from '../abstractions/sync.service';
import { UserService } from '../abstractions/user.service';
import { VaultTimeoutService } from '../abstractions/vaultTimeout.service';
import {
NotificationResponse,
@ -27,7 +27,7 @@ export class NotificationsService implements NotificationsServiceAbstraction {
constructor(private userService: UserService, private syncService: SyncService,
private appIdService: AppIdService, private apiService: ApiService,
private lockService: LockService, private logoutCallback: () => Promise<void>) { }
private vaultTimeoutService: VaultTimeoutService, private logoutCallback: () => Promise<void>) { }
async init(environmentService: EnvironmentService): Promise<void> {
this.inited = false;
@ -190,7 +190,7 @@ export class NotificationsService implements NotificationsServiceAbstraction {
private async isAuthedAndUnlocked() {
if (await this.userService.isAuthenticated()) {
const locked = await this.lockService.isLocked();
const locked = await this.vaultTimeoutService.isLocked();
return !locked;
}
return false;

View File

@ -1,8 +1,8 @@
import { LockService } from '../abstractions/lock.service';
import { MessagingService } from '../abstractions/messaging.service';
import { PlatformUtilsService } from '../abstractions/platformUtils.service';
import { StorageService } from '../abstractions/storage.service';
import { SystemService as SystemServiceAbstraction } from '../abstractions/system.service';
import { VaultTimeoutService } from '../abstractions/vaultTimeout.service';
import { ConstantsService } from './constants.service';
@ -13,13 +13,13 @@ export class SystemService implements SystemServiceAbstraction {
private clearClipboardTimeout: any = null;
private clearClipboardTimeoutFunction: () => Promise<any> = null;
constructor(private storageService: StorageService, private lockService: LockService,
constructor(private storageService: StorageService, private vaultTimeoutService: VaultTimeoutService,
private messagingService: MessagingService, private platformUtilsService: PlatformUtilsService,
private reloadCallback: () => Promise<void> = null) {
}
startProcessReload(): void {
if (this.lockService.pinProtectedKey != null || this.reloadInterval != null) {
if (this.vaultTimeoutService.pinProtectedKey != null || this.reloadInterval != null) {
return;
}
this.cancelProcessReload();

View File

@ -4,16 +4,16 @@ import { CipherService } from '../abstractions/cipher.service';
import { CollectionService } from '../abstractions/collection.service';
import { CryptoService } from '../abstractions/crypto.service';
import { FolderService } from '../abstractions/folder.service';
import { LockService as LockServiceAbstraction } from '../abstractions/lock.service';
import { MessagingService } from '../abstractions/messaging.service';
import { PlatformUtilsService } from '../abstractions/platformUtils.service';
import { SearchService } from '../abstractions/search.service';
import { StorageService } from '../abstractions/storage.service';
import { UserService } from '../abstractions/user.service';
import { VaultTimeoutService as VaultTimeoutServiceAbstraction } from '../abstractions/vaultTimeout.service';
import { CipherString } from '../models/domain/cipherString';
export class LockService implements LockServiceAbstraction {
export class VaultTimeoutService implements VaultTimeoutServiceAbstraction {
pinProtectedKey: CipherString = null;
private inited = false;
@ -32,8 +32,8 @@ export class LockService implements LockServiceAbstraction {
this.inited = true;
if (checkOnInterval) {
this.checkLock();
setInterval(() => this.checkLock(), 10 * 1000); // check every 10 seconds
this.checkVaultTimeout();
setInterval(() => this.checkVaultTimeout(), 10 * 1000); // check every 10 seconds
}
}
@ -42,12 +42,13 @@ export class LockService implements LockServiceAbstraction {
return !hasKey;
}
async checkLock(): Promise<void> {
async checkVaultTimeout(): Promise<void> {
if (await this.platformUtilsService.isViewOpen()) {
// Do not lock
return;
}
// "is logged out check" - similar to isLocked, below
const authed = await this.userService.isAuthenticated();
if (!authed) {
return;
@ -59,7 +60,7 @@ export class LockService implements LockServiceAbstraction {
let lockOption = this.platformUtilsService.lockTimeout();
if (lockOption == null) {
lockOption = await this.storageService.get<number>(ConstantsService.lockOptionKey);
lockOption = await this.storageService.get<number>(ConstantsService.vaultTimeoutKey);
}
if (lockOption == null || lockOption < 0) {
return;
@ -70,6 +71,7 @@ export class LockService implements LockServiceAbstraction {
return;
}
// TODO update with vault timeout name and pivot based on action saved
const lockOptionSeconds = lockOption * 60;
const diffSeconds = ((new Date()).getTime() - lastActive) / 1000;
if (diffSeconds >= lockOptionSeconds) {
@ -101,8 +103,13 @@ export class LockService implements LockServiceAbstraction {
}
}
async setLockOption(lockOption: number): Promise<void> {
await this.storageService.save(ConstantsService.lockOptionKey, lockOption);
async logout(): Promise<void> {
// TODO Add logic for loggedOutCallback
}
async setVaultTimeoutOptions(vaultTimeout: number, vaultTimeoutAction: string): Promise<void> {
await this.storageService.save(ConstantsService.vaultTimeoutKey, vaultTimeout);
// TODO Add logic for vaultTimeoutAction
await this.cryptoService.toggleKey();
}