mirror of
https://github.com/bitwarden/browser
synced 2026-01-08 03:23:50 +00:00
Desktop biometrics support (#119)
* Initial work on windows hello support * Switch to use windows.security.credentials.ui UserConsentVerifier * Fix linting warnings * Remove unessesary supportsBiometric from lock screen * Rename biometric.main to windows.biometric.main. Add abstraction for biometric. * Add support for dynamic biometric text. * Add untested darwin implementation * Rename fingerprintUnlock to biometric * Add new functions to cliPlatformUtils.service.ts. * Hide login if biometric is not supported * Export default for biometric.*.main.ts * Remove @nodert-win10-rs4/windows.security.credentials * Add build requirements to readme * Auto prompt biometric when starting the application. * Ensure we support biometric before trying to auto prompt. * Fix review comments and linting errors
This commit is contained in:
32
src/electron/biometric.darwin.main.ts
Normal file
32
src/electron/biometric.darwin.main.ts
Normal file
@@ -0,0 +1,32 @@
|
||||
import { I18nService, StorageService } from '../abstractions';
|
||||
|
||||
import { ipcMain, systemPreferences } from 'electron';
|
||||
import { BiometricMain } from '../abstractions/biometric.main';
|
||||
import { ConstantsService } from '../services';
|
||||
import { ElectronConstants } from './electronConstants';
|
||||
|
||||
export default class BiometricDarwinMain implements BiometricMain {
|
||||
constructor(private storageService: StorageService, private i18nservice: I18nService) {}
|
||||
|
||||
async init() {
|
||||
this.storageService.save(ElectronConstants.enableBiometric, await this.supportsBiometric());
|
||||
this.storageService.save(ConstantsService.biometricText, 'unlockWithTouchId');
|
||||
|
||||
ipcMain.on('biometric', async (event: any, message: any) => {
|
||||
event.returnValue = await this.requestCreate();
|
||||
});
|
||||
}
|
||||
|
||||
supportsBiometric(): Promise<boolean> {
|
||||
return Promise.resolve(systemPreferences.canPromptTouchID());
|
||||
}
|
||||
|
||||
async requestCreate(): Promise<boolean> {
|
||||
try {
|
||||
await systemPreferences.promptTouchID(this.i18nservice.t('touchIdConsentMessage'));
|
||||
return true;
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
46
src/electron/biometric.windows.main.ts
Normal file
46
src/electron/biometric.windows.main.ts
Normal file
@@ -0,0 +1,46 @@
|
||||
import * as util from 'util';
|
||||
|
||||
import {
|
||||
UserConsentVerificationResult,
|
||||
UserConsentVerifier,
|
||||
UserConsentVerifierAvailability,
|
||||
} from '@nodert-win10-rs4/windows.security.credentials.ui';
|
||||
import { I18nService, StorageService } from '../abstractions';
|
||||
|
||||
import { ipcMain } from 'electron';
|
||||
import { BiometricMain } from '../abstractions/biometric.main';
|
||||
import { ConstantsService } from '../services';
|
||||
import { ElectronConstants } from './electronConstants';
|
||||
|
||||
const requestVerification: any = util.promisify(UserConsentVerifier.requestVerificationAsync);
|
||||
const checkAvailability: any = util.promisify(UserConsentVerifier.checkAvailabilityAsync);
|
||||
|
||||
const AllowedAvailabilities = [
|
||||
UserConsentVerifierAvailability.available,
|
||||
UserConsentVerifierAvailability.deviceBusy,
|
||||
];
|
||||
|
||||
export default class BiometricWindowsMain implements BiometricMain {
|
||||
constructor(private storageService: StorageService, private i18nservice: I18nService) {}
|
||||
|
||||
async init() {
|
||||
this.storageService.save(ElectronConstants.enableBiometric, await this.supportsBiometric());
|
||||
this.storageService.save(ConstantsService.biometricText, 'unlockWithWindowsHello');
|
||||
|
||||
ipcMain.on('biometric', async (event: any, message: any) => {
|
||||
event.returnValue = await this.requestCreate();
|
||||
});
|
||||
}
|
||||
|
||||
async supportsBiometric(): Promise<boolean> {
|
||||
const availability = await checkAvailability();
|
||||
|
||||
return AllowedAvailabilities.includes(availability);
|
||||
}
|
||||
|
||||
async requestCreate(): Promise<boolean> {
|
||||
const verification = await requestVerification(this.i18nservice.t('windowsHelloConsentMessage'));
|
||||
|
||||
return verification === UserConsentVerificationResult.verified;
|
||||
}
|
||||
}
|
||||
@@ -5,4 +5,5 @@ export class ElectronConstants {
|
||||
static readonly enableStartToTrayKey: string = 'enableStartToTrayKey';
|
||||
static readonly enableAlwaysOnTopKey: string = 'enableAlwaysOnTopKey';
|
||||
static readonly minimizeOnCopyToClipboardKey: string = 'minimizeOnCopyToClipboardKey';
|
||||
static readonly enableBiometric: string = 'enabledBiometric';
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import {
|
||||
clipboard,
|
||||
ipcRenderer,
|
||||
remote,
|
||||
shell,
|
||||
} from 'electron';
|
||||
@@ -15,8 +16,10 @@ import { DeviceType } from '../../enums/deviceType';
|
||||
import { I18nService } from '../../abstractions/i18n.service';
|
||||
import { MessagingService } from '../../abstractions/messaging.service';
|
||||
import { PlatformUtilsService } from '../../abstractions/platformUtils.service';
|
||||
import { StorageService } from '../../abstractions/storage.service';
|
||||
|
||||
import { AnalyticsIds } from '../../misc/analytics';
|
||||
import { ElectronConstants } from '../electronConstants';
|
||||
|
||||
export class ElectronPlatformUtilsService implements PlatformUtilsService {
|
||||
identityClientId: string;
|
||||
@@ -25,7 +28,7 @@ export class ElectronPlatformUtilsService implements PlatformUtilsService {
|
||||
private analyticsIdCache: string = null;
|
||||
|
||||
constructor(private i18nService: I18nService, private messagingService: MessagingService,
|
||||
private isDesktopApp: boolean) {
|
||||
private isDesktopApp: boolean, private storageService: StorageService) {
|
||||
this.identityClientId = isDesktopApp ? 'desktop' : 'connector';
|
||||
}
|
||||
|
||||
@@ -203,4 +206,17 @@ export class ElectronPlatformUtilsService implements PlatformUtilsService {
|
||||
const type = options ? options.type : null;
|
||||
return Promise.resolve(clipboard.readText(type));
|
||||
}
|
||||
|
||||
supportsBiometric(): Promise<boolean> {
|
||||
return this.storageService.get(ElectronConstants.enableBiometric);
|
||||
}
|
||||
|
||||
authenticateBiometric(): Promise<boolean> {
|
||||
return new Promise((resolve) => {
|
||||
const val = ipcRenderer.sendSync('biometric', {
|
||||
action: 'authenticate',
|
||||
});
|
||||
resolve(val);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user