mirror of
https://github.com/bitwarden/browser
synced 2026-02-07 20:24:01 +00:00
Apply more fixes
This commit is contained in:
@@ -2180,6 +2180,9 @@
|
||||
"lockScreenDesktopRunningButLoggedOut": {
|
||||
"message": "User account synchronization is enabled, but the active account is logged out in the desktop app."
|
||||
},
|
||||
"lockScreenDesktopRunningButNotTrusted": {
|
||||
"message": "The connection fingerprint verification was denied in the desktop app."
|
||||
},
|
||||
"unlockWithBiometrics": {
|
||||
"message": "Unlock with biometrics"
|
||||
},
|
||||
|
||||
@@ -85,6 +85,7 @@ export default class RuntimeBackground {
|
||||
SyncedUnlockStateCommands.GetUserKeyFromDesktop,
|
||||
SyncedUnlockStateCommands.GetUserStatusFromDesktop,
|
||||
SyncedUnlockStateCommands.FocusDesktopApp,
|
||||
SyncedUnlockStateCommands.IsConnectionTrusted,
|
||||
"getUseTreeWalkerApiForPageDetailsCollectionFeatureFlag",
|
||||
"getUserPremiumStatus",
|
||||
];
|
||||
@@ -225,6 +226,9 @@ export default class RuntimeBackground {
|
||||
case SyncedUnlockStateCommands.FocusDesktopApp: {
|
||||
return await this.main.syncedUnlockService.focusDesktopApp();
|
||||
}
|
||||
case SyncedUnlockStateCommands.IsConnectionTrusted: {
|
||||
return await this.main.syncedUnlockService.isConnectionTrusted();
|
||||
}
|
||||
case "getUseTreeWalkerApiForPageDetailsCollectionFeatureFlag": {
|
||||
return await this.configService.getFeatureFlag(
|
||||
FeatureFlag.UseTreeWalkerApiForPageDetailsCollection,
|
||||
|
||||
@@ -18,8 +18,14 @@ import {
|
||||
|
||||
import { NativeMessagingBackground } from "../../background/nativeMessaging.background";
|
||||
|
||||
const SYNC_INTERVAL = 1000; // 1 second
|
||||
const TRUST_DENIED_TIMEOUT = 30000; // 30 seconds
|
||||
const STATUS_TIMEOUT = 5000; // 5 seconds
|
||||
|
||||
@Injectable()
|
||||
export class BackgroundSyncedUnlockService extends SyncedUnlockService {
|
||||
private hasTrustDenied = false;
|
||||
|
||||
constructor(
|
||||
private nativeMessagingBackground: () => NativeMessagingBackground,
|
||||
private logService: LogService,
|
||||
@@ -30,7 +36,7 @@ export class BackgroundSyncedUnlockService extends SyncedUnlockService {
|
||||
private syncedUnlockStateService: SyncedUnlockStateServiceAbstraction,
|
||||
) {
|
||||
super();
|
||||
timer(0, 1000)
|
||||
timer(0, SYNC_INTERVAL)
|
||||
.pipe(
|
||||
concatMap(async () => {
|
||||
const isConnected = await this.isConnected();
|
||||
@@ -47,15 +53,12 @@ export class BackgroundSyncedUnlockService extends SyncedUnlockService {
|
||||
const desktopAccountStatus = await Promise.race([
|
||||
this.getUserStatusFromDesktop(activeAccount.id),
|
||||
new Promise((resolve) =>
|
||||
setTimeout(() => resolve(AuthenticationStatus.Locked), 5000),
|
||||
setTimeout(() => resolve(AuthenticationStatus.Locked), STATUS_TIMEOUT),
|
||||
),
|
||||
]);
|
||||
const localAccountStatus = await firstValueFrom(
|
||||
this.authService.authStatusFor$(activeAccount.id),
|
||||
);
|
||||
this.logService.info(
|
||||
`Synced unlock: ${activeAccount.id} - Desktop: ${desktopAccountStatus} - Local: ${localAccountStatus}`,
|
||||
);
|
||||
if (
|
||||
desktopAccountStatus === AuthenticationStatus.Locked &&
|
||||
localAccountStatus === AuthenticationStatus.Unlocked
|
||||
@@ -66,9 +69,16 @@ export class BackgroundSyncedUnlockService extends SyncedUnlockService {
|
||||
desktopAccountStatus === AuthenticationStatus.Unlocked &&
|
||||
localAccountStatus === AuthenticationStatus.Locked
|
||||
) {
|
||||
this.logService.info("Asking for user key from desktop");
|
||||
const userKey = await this.getUserKeyFromDesktop(activeAccount.id);
|
||||
if (userKey) {
|
||||
if (userKey != null) {
|
||||
await this.keyService.setUserKey(userKey, activeAccount.id);
|
||||
} else {
|
||||
this.hasTrustDenied = true;
|
||||
// this means the user has denied access to the key on connection fingerprint verification
|
||||
// Wait 30 seconds
|
||||
await new Promise((resolve) => setTimeout(resolve, TRUST_DENIED_TIMEOUT));
|
||||
this.hasTrustDenied = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -117,4 +127,8 @@ export class BackgroundSyncedUnlockService extends SyncedUnlockService {
|
||||
command: SyncedUnlockStateCommands.FocusDesktopApp,
|
||||
});
|
||||
}
|
||||
|
||||
async isConnectionTrusted(): Promise<boolean> {
|
||||
return !this.hasTrustDenied && this.isConnected();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,4 +69,15 @@ export class ForegroundSyncedUnlockService extends SyncedUnlockService {
|
||||
throw response.error;
|
||||
}
|
||||
}
|
||||
|
||||
async isConnectionTrusted(): Promise<boolean> {
|
||||
const response = await BrowserApi.sendMessageWithResponse<{
|
||||
result: boolean;
|
||||
error: string;
|
||||
}>(SyncedUnlockStateCommands.IsConnectionTrusted);
|
||||
if (response.result == null) {
|
||||
throw response.error;
|
||||
}
|
||||
return response.result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -276,6 +276,14 @@ export class BiometricMessageHandlerService {
|
||||
case SyncedUnlockStateCommands.GetUserKeyFromDesktop: {
|
||||
if (!(await this.validateFingerprint(appId))) {
|
||||
this.logService.info("[Native Messaging IPC] Fingerprint validation failed.");
|
||||
return await this.send(
|
||||
{
|
||||
command: SyncedUnlockStateCommands.GetUserKeyFromDesktop,
|
||||
messageId,
|
||||
response: null,
|
||||
},
|
||||
appId,
|
||||
);
|
||||
}
|
||||
|
||||
const userId = message.userId as UserId;
|
||||
|
||||
@@ -8,4 +8,5 @@ export abstract class SyncedUnlockService {
|
||||
abstract getUserStatusFromDesktop(userId: UserId): Promise<AuthenticationStatus>;
|
||||
abstract getUserKeyFromDesktop(userId: UserId): Promise<UserKey | null>;
|
||||
abstract focusDesktopApp(): Promise<void>;
|
||||
abstract isConnectionTrusted(): Promise<boolean>;
|
||||
}
|
||||
|
||||
@@ -24,4 +24,8 @@ export class NoopSyncedUnlockService extends SyncedUnlockService {
|
||||
focusDesktopApp(): Promise<void> {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
isConnectionTrusted(): Promise<boolean> {
|
||||
return Promise.resolve(false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,11 +16,8 @@
|
||||
</form>
|
||||
</ng-container>
|
||||
<ng-container *ngIf="showLocalUnlockOptions">
|
||||
<bit-hint class="tw-text-center tw-mb-3" *ngIf="unlockViaDesktop && !activeUserLoggedOut">
|
||||
{{ "lockScreenDesktopNotRunning" | i18n }}
|
||||
</bit-hint>
|
||||
<bit-hint class="tw-text-center tw-mb-3" *ngIf="unlockViaDesktop && activeUserLoggedOut">
|
||||
{{ "lockScreenDesktopRunningButLoggedOut" | i18n }}
|
||||
<bit-hint class="tw-text-center tw-mb-3" *ngIf="unlockViaDesktop">
|
||||
{{ synchronizedUnlockUnavailabilityReason }}
|
||||
</bit-hint>
|
||||
|
||||
<!-- Biometrics Unlock -->
|
||||
|
||||
@@ -139,8 +139,10 @@ export class LockComponent implements OnInit, OnDestroy {
|
||||
|
||||
unlockViaDesktop = false;
|
||||
isDesktopOpen = false;
|
||||
isDesktopConnectionTrusted = false;
|
||||
activeUserLoggedOut = false;
|
||||
showLocalUnlockOptions = true;
|
||||
synchronizedUnlockUnavailabilityReason: string = "";
|
||||
desktopUnlockFormGroup: FormGroup = new FormGroup({});
|
||||
|
||||
constructor(
|
||||
@@ -224,14 +226,41 @@ export class LockComponent implements OnInit, OnDestroy {
|
||||
}
|
||||
|
||||
this.isDesktopOpen = await this.syncedUnlockService.isConnected();
|
||||
this.isDesktopConnectionTrusted = await this.syncedUnlockService.isConnectionTrusted();
|
||||
this.activeUserLoggedOut =
|
||||
(await this.syncedUnlockService.getUserStatusFromDesktop(activeAccount.id)) ===
|
||||
AuthenticationStatus.LoggedOut;
|
||||
this.showLocalUnlockOptions = !(
|
||||
this.isDesktopOpen &&
|
||||
this.unlockViaDesktop &&
|
||||
!this.activeUserLoggedOut
|
||||
);
|
||||
|
||||
// Synchronized unlock not enabled
|
||||
if (!this.unlockViaDesktop) {
|
||||
this.showLocalUnlockOptions = true;
|
||||
this.synchronizedUnlockUnavailabilityReason = "";
|
||||
return;
|
||||
}
|
||||
|
||||
// Synchronized unlock enabled, but cannot be used
|
||||
if (!this.isDesktopOpen) {
|
||||
this.showLocalUnlockOptions = true;
|
||||
this.synchronizedUnlockUnavailabilityReason = this.i18nService.t(
|
||||
"lockScreenDesktopNotRunning",
|
||||
);
|
||||
return;
|
||||
} else if (this.activeUserLoggedOut) {
|
||||
this.showLocalUnlockOptions = true;
|
||||
this.synchronizedUnlockUnavailabilityReason = this.i18nService.t(
|
||||
"lockScreenDesktopRunningButLoggedOut",
|
||||
);
|
||||
return;
|
||||
} else if (!this.isDesktopConnectionTrusted) {
|
||||
this.showLocalUnlockOptions = true;
|
||||
this.synchronizedUnlockUnavailabilityReason = this.i18nService.t(
|
||||
"lockScreenDesktopRunningButNotTrusted",
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
this.showLocalUnlockOptions = false;
|
||||
this.synchronizedUnlockUnavailabilityReason = "";
|
||||
} catch (e) {
|
||||
this.logService.error(e);
|
||||
}
|
||||
|
||||
@@ -6,4 +6,5 @@ export enum SyncedUnlockStateCommands {
|
||||
GetUserKeyFromDesktop = "getUserKeyFromDesktop",
|
||||
GetUserStatusFromDesktop = "getUserStatusFromDesktop",
|
||||
FocusDesktopApp = "focusDesktopApp",
|
||||
IsConnectionTrusted = "isConnectionTrusted",
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user