Add support for browser biometrics on Firefox >= 87 (#1668)
This commit is contained in:
parent
d0b307d36a
commit
faf4c3e94a
|
@ -58,7 +58,6 @@ function dist(browserName, manifest) {
|
||||||
function distFirefox() {
|
function distFirefox() {
|
||||||
return dist('firefox', (manifest) => {
|
return dist('firefox', (manifest) => {
|
||||||
delete manifest.content_security_policy;
|
delete manifest.content_security_policy;
|
||||||
delete manifest.optional_permissions;
|
|
||||||
removeShortcuts(manifest);
|
removeShortcuts(manifest);
|
||||||
return manifest;
|
return manifest;
|
||||||
});
|
});
|
||||||
|
|
|
@ -1441,18 +1441,18 @@
|
||||||
"biometricsNotSupportedDesc": {
|
"biometricsNotSupportedDesc": {
|
||||||
"message": "Browser biometrics is not supported on this device."
|
"message": "Browser biometrics is not supported on this device."
|
||||||
},
|
},
|
||||||
"nativeMessagingPermissionPromptTitle": {
|
|
||||||
"message": "Additional Permission required"
|
|
||||||
},
|
|
||||||
"nativeMessagingPermissionPromptDesc": {
|
|
||||||
"message": "To enable browser biometrics we need to request an additional permission. Once allowed, the browser extension will reload and you may need to unlock your vault again."
|
|
||||||
},
|
|
||||||
"nativeMessaginPermissionErrorTitle": {
|
"nativeMessaginPermissionErrorTitle": {
|
||||||
"message": "Permission not provided"
|
"message": "Permission not provided"
|
||||||
},
|
},
|
||||||
"nativeMessaginPermissionErrorDesc": {
|
"nativeMessaginPermissionErrorDesc": {
|
||||||
"message": "Without permission to communicate with the Bitwarden Desktop Application we cannot provide biometrics in the browser extension. Please try again."
|
"message": "Without permission to communicate with the Bitwarden Desktop Application we cannot provide biometrics in the browser extension. Please try again."
|
||||||
},
|
},
|
||||||
|
"nativeMessaginPermissionSidebarTitle": {
|
||||||
|
"message": "Permission request error"
|
||||||
|
},
|
||||||
|
"nativeMessaginPermissionSidebarDesc": {
|
||||||
|
"message": "This action cannot be done in the sidebar, please retry the action in the popup or popout."
|
||||||
|
},
|
||||||
"personalOwnershipSubmitError": {
|
"personalOwnershipSubmitError": {
|
||||||
"message": "Due to an Enterprise Policy, you are restricted from saving items to your personal vault. Change the Ownership option to an organization and choose from available Collections."
|
"message": "Due to an Enterprise Policy, you are restricted from saving items to your personal vault. Change the Ownership option to an organization and choose from available Collections."
|
||||||
},
|
},
|
||||||
|
|
|
@ -167,4 +167,13 @@ export class BrowserApi {
|
||||||
return chrome.runtime.connectNative(application);
|
return chrome.runtime.connectNative(application);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static requestPermission(permission: any) {
|
||||||
|
if (BrowserApi.isWebExtensionsApi) {
|
||||||
|
return browser.permissions.request(permission);
|
||||||
|
}
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
chrome.permissions.request(permission, resolve);
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,7 @@ import { PlatformUtilsService } from 'jslib/abstractions/platformUtils.service';
|
||||||
import { StorageService } from 'jslib/abstractions/storage.service';
|
import { StorageService } from 'jslib/abstractions/storage.service';
|
||||||
import { UserService } from 'jslib/abstractions/user.service';
|
import { UserService } from 'jslib/abstractions/user.service';
|
||||||
import { VaultTimeoutService } from 'jslib/abstractions/vaultTimeout.service';
|
import { VaultTimeoutService } from 'jslib/abstractions/vaultTimeout.service';
|
||||||
|
import { PopupUtilsService } from '../services/popup-utils.service';
|
||||||
|
|
||||||
const RateUrls = {
|
const RateUrls = {
|
||||||
[DeviceType.ChromeExtension]:
|
[DeviceType.ChromeExtension]:
|
||||||
|
@ -59,7 +60,8 @@ export class SettingsComponent implements OnInit {
|
||||||
private analytics: Angulartics2, private vaultTimeoutService: VaultTimeoutService,
|
private analytics: Angulartics2, private vaultTimeoutService: VaultTimeoutService,
|
||||||
private storageService: StorageService, public messagingService: MessagingService,
|
private storageService: StorageService, public messagingService: MessagingService,
|
||||||
private router: Router, private environmentService: EnvironmentService,
|
private router: Router, private environmentService: EnvironmentService,
|
||||||
private cryptoService: CryptoService, private userService: UserService) {
|
private cryptoService: CryptoService, private userService: UserService,
|
||||||
|
private popupUtilsService: PopupUtilsService) {
|
||||||
}
|
}
|
||||||
|
|
||||||
async ngOnInit() {
|
async ngOnInit() {
|
||||||
|
@ -212,31 +214,30 @@ export class SettingsComponent implements OnInit {
|
||||||
async updateBiometric() {
|
async updateBiometric() {
|
||||||
if (this.biometric && this.supportsBiometric) {
|
if (this.biometric && this.supportsBiometric) {
|
||||||
|
|
||||||
// Request permission to use the optional permission for nativeMessaging
|
let granted;
|
||||||
if (!this.platformUtilsService.isFirefox()) {
|
try {
|
||||||
const hasPermission = await new Promise(resolve => {
|
granted = await BrowserApi.requestPermission({ permissions: ['nativeMessaging'] });
|
||||||
chrome.permissions.contains({ permissions: ['nativeMessaging'] }, resolve);
|
} catch (e) {
|
||||||
});
|
// tslint:disable-next-line
|
||||||
|
console.error(e);
|
||||||
|
|
||||||
if (!hasPermission) {
|
if (this.platformUtilsService.isFirefox() && this.popupUtilsService.inSidebar(window)) {
|
||||||
await this.platformUtilsService.showDialog(
|
await this.platformUtilsService.showDialog(
|
||||||
this.i18nService.t('nativeMessagingPermissionPromptDesc'), this.i18nService.t('nativeMessagingPermissionPromptTitle'),
|
this.i18nService.t('nativeMessaginPermissionSidebarDesc'), this.i18nService.t('nativeMessaginPermissionSidebarTitle'),
|
||||||
this.i18nService.t('ok'), null);
|
this.i18nService.t('ok'), null);
|
||||||
|
this.biometric = false;
|
||||||
const granted = await new Promise((resolve, reject) => {
|
return;
|
||||||
chrome.permissions.request({ permissions: ['nativeMessaging'] }, resolve);
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!granted) {
|
|
||||||
await this.platformUtilsService.showDialog(
|
|
||||||
this.i18nService.t('nativeMessaginPermissionErrorDesc'), this.i18nService.t('nativeMessaginPermissionErrorTitle'),
|
|
||||||
this.i18nService.t('ok'), null);
|
|
||||||
this.biometric = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!granted) {
|
||||||
|
await this.platformUtilsService.showDialog(
|
||||||
|
this.i18nService.t('nativeMessaginPermissionErrorDesc'), this.i18nService.t('nativeMessaginPermissionErrorTitle'),
|
||||||
|
this.i18nService.t('ok'), null);
|
||||||
|
this.biometric = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const submitted = Swal.fire({
|
const submitted = Swal.fire({
|
||||||
heightAuto: false,
|
heightAuto: false,
|
||||||
buttonsStyling: false,
|
buttonsStyling: false,
|
||||||
|
|
|
@ -292,8 +292,9 @@ export default class BrowserPlatformUtilsService implements PlatformUtilsService
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
supportsBiometric() {
|
async supportsBiometric() {
|
||||||
return Promise.resolve(!this.isFirefox() && !this.isSafari());
|
const isUnsuportedFirefox = this.isFirefox() && parseInt((await browser.runtime.getBrowserInfo()).version.split('.')[0], 10) < 87;
|
||||||
|
return !isUnsuportedFirefox && !this.isSafari();
|
||||||
}
|
}
|
||||||
|
|
||||||
authenticateBiometric() {
|
authenticateBiometric() {
|
||||||
|
|
Loading…
Reference in New Issue