1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-20 18:23:31 +00:00

Biometric support (#470)

* Initial work on windows hello support

* Hide login button if not enabled

* Add windows.security.credentials.ui dependency to desktop as well.

* Only enable biometric on windows.

* Add support for dynamic biometric text.

* Add untested darwin implementation

* Ensure we support biometric before showing login with windows hello / touchid.

* Ensure compatability with latest jslib

* Only require module on use.

* Add windows.security.credentials.ui to src/package.json.

* Update requirements

* Update consent messages for biometrics
This commit is contained in:
Oscar Hinton
2020-07-23 19:32:36 +02:00
committed by GitHub
parent 560b58f9de
commit 26b023a3cb
12 changed files with 89 additions and 6 deletions

View File

@@ -36,5 +36,10 @@
{{'logOut' | i18n}}
</button>
</div>
<div class="button" *ngIf="supportsBiometric && biometricLock">
<a class="btn primary block" appBlurClick (click)="unlockBiometric()">
<i class="fa fa-unlock-alt" aria-hidden="true"></i> <b>{{biometricText | i18n}}</b>
</a>
</div>
</div>
</form>

View File

@@ -1,6 +1,7 @@
import { Component } from '@angular/core';
import { Router } from '@angular/router';
import { ApiService } from 'jslib/abstractions/api.service';
import { CryptoService } from 'jslib/abstractions/crypto.service';
import { EnvironmentService } from 'jslib/abstractions/environment.service';
import { I18nService } from 'jslib/abstractions/i18n.service';
@@ -22,8 +23,8 @@ export class LockComponent extends BaseLockComponent {
platformUtilsService: PlatformUtilsService, messagingService: MessagingService,
userService: UserService, cryptoService: CryptoService,
storageService: StorageService, vaultTimeoutService: VaultTimeoutService,
environmentService: EnvironmentService, stateService: StateService) {
environmentService: EnvironmentService, stateService: StateService, apiService: ApiService) {
super(router, i18nService, platformUtilsService, messagingService, userService, cryptoService,
storageService, vaultTimeoutService, environmentService, stateService);
storageService, vaultTimeoutService, environmentService, stateService, apiService);
}
}

View File

@@ -44,6 +44,14 @@
</label>
</div>
</div>
<div class="form-group" *ngIf="supportsBiometric">
<div class="checkbox">
<label for="biometric">
<input id="biometric" type="checkbox" name="biometric" [checked]="biometric" (change)="updateBiometric()">
{{biometricText | i18n}}
</label>
</div>
</div>
</div>
</div>
<div class="box">

View File

@@ -48,6 +48,9 @@ export class SettingsComponent implements OnInit {
clearClipboardOptions: any[];
enableTrayText: string;
enableTrayDescText: string;
supportsBiometric: boolean;
biometric: boolean;
biometricText: string;
constructor(private analytics: Angulartics2, private toasterService: ToasterService,
private i18nService: I18nService, private platformUtilsService: PlatformUtilsService,
@@ -125,6 +128,9 @@ export class SettingsComponent implements OnInit {
this.clearClipboard = await this.storageService.get<number>(ConstantsService.clearClipboardKey);
this.minimizeOnCopyToClipboard = await this.storageService.get<boolean>(
ElectronConstants.minimizeOnCopyToClipboardKey);
this.supportsBiometric = await this.platformUtilsService.supportsBiometric();
this.biometric = await this.vaultTimeoutService.isBiometricLockSet();
this.biometricText = await this.storageService.get<string>(ConstantsService.biometricText);
}
async saveVaultTimeoutOptions() {
@@ -201,6 +207,25 @@ export class SettingsComponent implements OnInit {
}
}
async updateBiometric() {
const current = this.biometric;
if (this.biometric) {
this.biometric = false;
} else if (this.supportsBiometric) {
this.biometric = await this.platformUtilsService.authenticateBiometric();
}
if (this.biometric === current) {
return;
}
if (this.biometric) {
await this.storageService.save(ConstantsService.biometricUnlockKey, true);
} else {
await this.storageService.remove(ConstantsService.biometricUnlockKey);
}
this.vaultTimeoutService.biometricLocked = false;
await this.cryptoService.toggleKey();
}
async saveFavicons() {
await this.storageService.save(ConstantsService.disableFaviconKey, this.disableFavicons);
await this.stateService.save(ConstantsService.disableFaviconKey, this.disableFavicons);

View File

@@ -231,6 +231,7 @@ export class AppComponent implements OnInit {
this.policyService.clear(userId),
]);
this.vaultTimeoutService.biometricLocked = true;
this.searchService.clearIndex();
this.authService.logOut(async () => {
this.analytics.eventTrack.next({ action: 'Logged Out' });

View File

@@ -89,8 +89,8 @@ const i18nService = new I18nService(window.navigator.language, './locales');
const stateService = new StateService();
const broadcasterService = new BroadcasterService();
const messagingService = new ElectronRendererMessagingService(broadcasterService);
const platformUtilsService = new ElectronPlatformUtilsService(i18nService, messagingService, true);
const storageService: StorageServiceAbstraction = new ElectronStorageService(remote.app.getPath('userData'));
const platformUtilsService = new ElectronPlatformUtilsService(i18nService, messagingService, true, storageService);
const secureStorageService: StorageServiceAbstraction = new ElectronRendererSecureStorageService();
const cryptoFunctionService: CryptoFunctionServiceAbstraction = new WebCryptoFunctionService(window,
platformUtilsService);
@@ -118,8 +118,8 @@ const syncService = new SyncService(userService, apiService, settingsService,
const passwordGenerationService = new PasswordGenerationService(cryptoService, storageService, policyService);
const totpService = new TotpService(storageService, cryptoFunctionService);
const containerService = new ContainerService(cryptoService);
const authService = new AuthService(cryptoService, apiService,
userService, tokenService, appIdService, i18nService, platformUtilsService, messagingService);
const authService = new AuthService(cryptoService, apiService, userService, tokenService, appIdService,
i18nService, platformUtilsService, messagingService, vaultTimeoutService);
const exportService = new ExportService(folderService, cipherService, apiService);
const auditService = new AuditService(cryptoFunctionService, apiService);
const notificationsService = new NotificationsService(userService, syncService, appIdService,