Browse Source
* 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 errorspull/135/head
19 changed files with 300 additions and 6 deletions
@ -0,0 +1,5 @@
@@ -0,0 +1,5 @@
|
||||
export abstract class BiometricMain { |
||||
init: () => Promise<void>; |
||||
supportsBiometric: () => Promise<boolean>; |
||||
requestCreate: () => Promise<boolean>; |
||||
} |
||||
@ -0,0 +1,32 @@
@@ -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; |
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,46 @@
@@ -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; |
||||
} |
||||
} |
||||
@ -1,3 +1,104 @@
@@ -1,3 +1,104 @@
|
||||
declare function escape(s: string): string; |
||||
declare function unescape(s: string): string; |
||||
declare module 'duo_web_sdk'; |
||||
|
||||
/* tslint:disable */ |
||||
declare module '@nodert-win10-rs4/windows.security.credentials.ui' { |
||||
export enum AuthenticationProtocol { |
||||
basic, |
||||
digest, |
||||
ntlm, |
||||
kerberos, |
||||
negotiate, |
||||
credSsp, |
||||
custom, |
||||
} |
||||
|
||||
export enum CredentialSaveOption { |
||||
unselected, |
||||
selected, |
||||
hidden, |
||||
} |
||||
|
||||
export enum UserConsentVerifierAvailability { |
||||
available, |
||||
deviceNotPresent, |
||||
notConfiguredForUser, |
||||
disabledByPolicy, |
||||
deviceBusy, |
||||
} |
||||
|
||||
export enum UserConsentVerificationResult { |
||||
verified, |
||||
deviceNotPresent, |
||||
notConfiguredForUser, |
||||
disabledByPolicy, |
||||
deviceBusy, |
||||
retriesExhausted, |
||||
canceled, |
||||
} |
||||
|
||||
export class CredentialPickerOptions { |
||||
targetName: String; |
||||
previousCredential: Object; |
||||
message: String; |
||||
errorCode: Number; |
||||
customAuthenticationProtocol: String; |
||||
credentialSaveOption: CredentialSaveOption; |
||||
caption: String; |
||||
callerSavesCredential: Boolean; |
||||
authenticationProtocol: AuthenticationProtocol; |
||||
alwaysDisplayDialog: Boolean; |
||||
constructor(); |
||||
} |
||||
|
||||
export class CredentialPickerResults { |
||||
credential: Object; |
||||
credentialDomainName: String; |
||||
credentialPassword: String; |
||||
credentialSaveOption: CredentialSaveOption; |
||||
credentialSaved: Boolean; |
||||
credentialUserName: String; |
||||
errorCode: Number; |
||||
constructor(); |
||||
} |
||||
|
||||
export class CredentialPicker { |
||||
constructor(); |
||||
|
||||
static pickAsync( |
||||
options: CredentialPickerOptions, |
||||
callback: (error: Error, result: CredentialPickerResults) => void |
||||
): void; |
||||
static pickAsync( |
||||
targetName: String, |
||||
message: String, |
||||
callback: (error: Error, result: CredentialPickerResults) => void |
||||
): void; |
||||
static pickAsync( |
||||
targetName: String, |
||||
message: String, |
||||
caption: String, |
||||
callback: (error: Error, result: CredentialPickerResults) => void |
||||
): void; |
||||
} |
||||
|
||||
export class UserConsentVerifier { |
||||
constructor(); |
||||
|
||||
static checkAvailabilityAsync( |
||||
callback: ( |
||||
error: Error, |
||||
result: UserConsentVerifierAvailability |
||||
) => void |
||||
): void; |
||||
|
||||
static requestVerificationAsync( |
||||
message: String, |
||||
callback: ( |
||||
error: Error, |
||||
result: UserConsentVerificationResult |
||||
) => void |
||||
): void; |
||||
} |
||||
} |
||||
|
||||
Loading…
Reference in new issue