diff --git a/apps/desktop/desktop_native/macos_provider/src/assertion.rs b/apps/desktop/desktop_native/macos_provider/src/assertion.rs index c31601b1f6d..a530bb26a22 100644 --- a/apps/desktop/desktop_native/macos_provider/src/assertion.rs +++ b/apps/desktop/desktop_native/macos_provider/src/assertion.rs @@ -11,6 +11,7 @@ pub struct PasskeyAssertionRequest { client_data_hash: Vec, user_verification: UserVerification, allowed_credentials: Vec>, + window_xy: Vec, //extension_input: Vec, TODO: Implement support for extensions } @@ -24,6 +25,7 @@ pub struct PasskeyAssertionWithoutUserInterfaceRequest { record_identifier: Option, client_data_hash: Vec, user_verification: UserVerification, + window_xy: Vec, } #[derive(uniffi::Record, Serialize, Deserialize)] diff --git a/apps/desktop/desktop_native/macos_provider/src/registration.rs b/apps/desktop/desktop_native/macos_provider/src/registration.rs index d484af58b6c..89260c2defc 100644 --- a/apps/desktop/desktop_native/macos_provider/src/registration.rs +++ b/apps/desktop/desktop_native/macos_provider/src/registration.rs @@ -13,6 +13,7 @@ pub struct PasskeyRegistrationRequest { client_data_hash: Vec, user_verification: UserVerification, supported_algorithms: Vec, + window_xy: Vec, } #[derive(uniffi::Record, Serialize, Deserialize)] diff --git a/apps/desktop/desktop_native/napi/index.d.ts b/apps/desktop/desktop_native/napi/index.d.ts index 79dccab6afe..1bf64596700 100644 --- a/apps/desktop/desktop_native/napi/index.d.ts +++ b/apps/desktop/desktop_native/napi/index.d.ts @@ -136,6 +136,7 @@ export declare namespace autofill { clientDataHash: Array userVerification: UserVerification supportedAlgorithms: Array + windowXy: Array } export interface PasskeyRegistrationResponse { rpId: string @@ -148,6 +149,7 @@ export declare namespace autofill { clientDataHash: Array userVerification: UserVerification allowedCredentials: Array> + windowXy: Array } export interface PasskeyAssertionWithoutUserInterfaceRequest { rpId: string @@ -157,6 +159,7 @@ export declare namespace autofill { recordIdentifier?: string clientDataHash: Array userVerification: UserVerification + windowXy: Array } export interface PasskeyAssertionResponse { rpId: string diff --git a/apps/desktop/desktop_native/napi/src/lib.rs b/apps/desktop/desktop_native/napi/src/lib.rs index a59833669a7..7edea7308af 100644 --- a/apps/desktop/desktop_native/napi/src/lib.rs +++ b/apps/desktop/desktop_native/napi/src/lib.rs @@ -592,6 +592,7 @@ pub mod autofill { pub client_data_hash: Vec, pub user_verification: UserVerification, pub supported_algorithms: Vec, + pub window_xy: Vec, } #[napi(object)] @@ -612,6 +613,7 @@ pub mod autofill { pub client_data_hash: Vec, pub user_verification: UserVerification, pub allowed_credentials: Vec>, + pub window_xy: Vec, //extension_input: Vec, TODO: Implement support for extensions } @@ -626,6 +628,7 @@ pub mod autofill { pub record_identifier: Option, pub client_data_hash: Vec, pub user_verification: UserVerification, + pub window_xy: Vec, } #[napi(object)] diff --git a/apps/desktop/macos/autofill-extension/Base.lproj/CredentialProviderViewController.xib b/apps/desktop/macos/autofill-extension/Base.lproj/CredentialProviderViewController.xib index 6bcbd589ce3..1e47cc54de2 100644 --- a/apps/desktop/macos/autofill-extension/Base.lproj/CredentialProviderViewController.xib +++ b/apps/desktop/macos/autofill-extension/Base.lproj/CredentialProviderViewController.xib @@ -44,7 +44,7 @@ Gw - + diff --git a/apps/desktop/macos/autofill-extension/CredentialProviderViewController.swift b/apps/desktop/macos/autofill-extension/CredentialProviderViewController.swift index 8c2aa15550f..1b2786baca7 100644 --- a/apps/desktop/macos/autofill-extension/CredentialProviderViewController.swift +++ b/apps/desktop/macos/autofill-extension/CredentialProviderViewController.swift @@ -17,10 +17,50 @@ class CredentialProviderViewController: ASCredentialProviderViewController { // // If instead I make this a static, the deinit gets called correctly after each request. // I think we still might want a static regardless, to be able to reuse the connection if possible. - static let client: MacOsProviderClient = { - let instance = MacOsProviderClient.connect() - // setup code - return instance + let client: MacOsProviderClient = { + let logger = Logger(subsystem: "com.bitwarden.desktop.autofill-extension", category: "credential-provider") + + // Check if the Electron app is running + let workspace = NSWorkspace.shared + let isRunning = workspace.runningApplications.contains { app in + app.bundleIdentifier == "com.bitwarden.desktop" + } + + + if !isRunning { + logger.log("[autofill-extension] Bitwarden Desktop not running, attempting to launch") + + // Try to launch the app + if let appURL = workspace.urlForApplication(withBundleIdentifier: "com.bitwarden.desktop") { + let semaphore = DispatchSemaphore(value: 0) + + workspace.openApplication(at: appURL, + configuration: NSWorkspace.OpenConfiguration()) { app, error in + if let error = error { + logger.error("[autofill-extension] Failed to launch Bitwarden Desktop: \(error.localizedDescription)") + } else if let app = app { + logger.log("[autofill-extension] Successfully launched Bitwarden Desktop") + } else { + logger.error("[autofill-extension] Failed to launch Bitwarden Desktop: unknown error") + } + semaphore.signal() + } + + // Wait for launch completion with timeout + _ = semaphore.wait(timeout: .now() + 5.0) + + // Add a small delay to allow for initialization + Thread.sleep(forTimeInterval: 1.0) + } else { + logger.error("[autofill-extension] Could not find Bitwarden Desktop app") + } + } else { + logger.log("[autofill-extension] Bitwarden Desktop is running") + } + + logger.log("[autofill-extension] Connecting to Bitwarden over IPC") + + return MacOsProviderClient.connect() }() init() { @@ -50,6 +90,31 @@ class CredentialProviderViewController: ASCredentialProviderViewController { self.extensionContext.completeRequest(withSelectedCredential: passwordCredential, completionHandler: nil) } + private func getWindowPosition() -> [Int32] { + let frame = self.view.window?.frame ?? .zero + let screenHeight = NSScreen.main?.frame.height ?? 0 + + logger.log("[autofill-extension] Detailed window debug:") + logger.log(" Popup frame:") + logger.log(" origin.x: \(frame.origin.x)") + logger.log(" origin.y: \(frame.origin.y)") + logger.log(" width: \(frame.width)") + logger.log(" height: \(frame.height)") + + + // frame.width and frame.height is always 0. Estimating works OK for now. + let estimatedWidth:CGFloat = 400; + let estimatedHeight:CGFloat = 200; + let centerX = Int32(round(frame.origin.x + estimatedWidth/2)) + let centerY = Int32(round(screenHeight - (frame.origin.y + estimatedHeight/2))) + + logger.log(" Calculated center:") + logger.log(" x: \(centerX)") + logger.log(" y: \(centerY)") + + return [centerX, centerY] + } + override func loadView() { let view = NSView() view.isHidden = true @@ -134,10 +199,11 @@ class CredentialProviderViewController: ASCredentialProviderViewController { userHandle: passkeyIdentity.userHandle, recordIdentifier: passkeyIdentity.recordIdentifier, clientDataHash: request.clientDataHash, - userVerification: userVerification + userVerification: userVerification, + windowXy: self.getWindowPosition() ) - CredentialProviderViewController.client.preparePasskeyAssertionWithoutUserInterface(request: req, callback: CallbackImpl(self.extensionContext, self.logger)) + self.client.preparePasskeyAssertionWithoutUserInterface(request: req, callback: CallbackImpl(self.extensionContext, self.logger)) return } } @@ -169,22 +235,22 @@ class CredentialProviderViewController: ASCredentialProviderViewController { override func prepareInterface(forPasskeyRegistration registrationRequest: ASCredentialRequest) { logger.log("[autofill-extension] prepareInterface") - // Create a timer for 20 second timeout + // Create a timer for 90 second timeout let timeoutTimer = DispatchWorkItem { [weak self] in guard let self = self else { return } - logger.log("[autofill-extension] Registration timed out after 20 seconds") + logger.log("[autofill-extension] Registration timed out after 90 seconds") self.extensionContext.cancelRequest(withError: BitwardenError.Internal("Registration timed out")) } // Schedule the timeout - DispatchQueue.main.asyncAfter(deadline: .now() + 20, execute: timeoutTimer) + DispatchQueue.main.asyncAfter(deadline: .now() + 90, execute: timeoutTimer) - // Create a timer to show UI after 10 seconds - DispatchQueue.main.asyncAfter(deadline: .now() + 10) { [weak self] in - guard let self = self else { return } - // Configure and show UI elements for manual cancellation - self.configureTimeoutUI() - } + // // Create a timer to show UI after 10 seconds + // DispatchQueue.main.asyncAfter(deadline: .now() + 90) { [weak self] in + // guard let self = self else { return } + // // Configure and show UI elements for manual cancellation + // self.configureTimeoutUI() + // } if let request = registrationRequest as? ASPasskeyCredentialRequest { if let passkeyIdentity = registrationRequest.credentialIdentity as? ASPasskeyCredentialIdentity { @@ -228,7 +294,9 @@ class CredentialProviderViewController: ASCredentialProviderViewController { userHandle: passkeyIdentity.userHandle, clientDataHash: request.clientDataHash, userVerification: userVerification, - supportedAlgorithms: request.supportedAlgorithms.map{ Int32($0.rawValue) } + supportedAlgorithms: request.supportedAlgorithms.map{ Int32($0.rawValue) }, + windowXy: self.getWindowPosition() + ) logger.log("[autofill-extension] prepareInterface(passkey) calling preparePasskeyRegistration") // Log details of the request @@ -236,7 +304,7 @@ class CredentialProviderViewController: ASCredentialProviderViewController { logger.log("[autofill-extension] rpId: \(req.userName)") - CredentialProviderViewController.client.preparePasskeyRegistration(request: req, callback: CallbackImpl(self.extensionContext)) + self.client.preparePasskeyRegistration(request: req, callback: CallbackImpl(self.extensionContext)) return } } @@ -305,11 +373,13 @@ class CredentialProviderViewController: ASCredentialProviderViewController { rpId: requestParameters.relyingPartyIdentifier, clientDataHash: requestParameters.clientDataHash, userVerification: userVerification, - allowedCredentials: requestParameters.allowedCredentials + allowedCredentials: requestParameters.allowedCredentials, + windowXy: self.getWindowPosition() + //extensionInput: requestParameters.extensionInput, ) - CredentialProviderViewController.client.preparePasskeyAssertion(request: req, callback: CallbackImpl(self.extensionContext)) + self.client.preparePasskeyAssertion(request: req, callback: CallbackImpl(self.extensionContext)) return } diff --git a/apps/desktop/src/app/app-routing.module.ts b/apps/desktop/src/app/app-routing.module.ts index 935291be2ae..071706a1e32 100644 --- a/apps/desktop/src/app/app-routing.module.ts +++ b/apps/desktop/src/app/app-routing.module.ts @@ -338,7 +338,7 @@ const routes: Routes = [ component: Fido2VaultComponent, }, { - path: "passkey-create", + path: "create-passkey", component: Fido2CreateComponent, }, { diff --git a/apps/desktop/src/app/components/fido2placeholder.component.ts b/apps/desktop/src/app/components/fido2placeholder.component.ts index fa6fbae86d8..8cc93d00b08 100644 --- a/apps/desktop/src/app/components/fido2placeholder.component.ts +++ b/apps/desktop/src/app/components/fido2placeholder.component.ts @@ -56,7 +56,7 @@ import { DesktopSettingsService } from "../../platform/services/desktop-settings export class Fido2PlaceholderComponent implements OnInit, OnDestroy { session?: DesktopFido2UserInterfaceSession = null; private cipherIdsSubject = new BehaviorSubject([]); - cipherIds$: Observable = this.cipherIdsSubject.asObservable(); + cipherIds$: Observable; constructor( private readonly desktopSettingsService: DesktopSettingsService, @@ -64,21 +64,16 @@ export class Fido2PlaceholderComponent implements OnInit, OnDestroy { private readonly router: Router, ) {} - async ngOnInit(): Promise { + ngOnInit() { this.session = this.fido2UserInterfaceService.getCurrentSession(); - - const cipherIds = await this.session?.getAvailableCipherIds(); - this.cipherIdsSubject.next(cipherIds || []); - - // eslint-disable-next-line no-console - console.log("Available cipher IDs", cipherIds); + this.cipherIds$ = this.session?.availableCipherIds$; } async chooseCipher(cipherId: string) { this.session?.confirmChosenCipher(cipherId); await this.router.navigate(["/"]); - await this.desktopSettingsService.setInModalMode(false); + await this.desktopSettingsService.setModalMode(false); } ngOnDestroy() { @@ -108,7 +103,7 @@ export class Fido2PlaceholderComponent implements OnInit, OnDestroy { // The session currently toggles modal on and send us here // But if this route is somehow opened outside of session we want to make sure we clean up? await this.router.navigate(["/"]); - await this.desktopSettingsService.setInModalMode(false); + await this.desktopSettingsService.setModalMode(false); } catch (error) { // TODO: Handle error appropriately } @@ -116,7 +111,7 @@ export class Fido2PlaceholderComponent implements OnInit, OnDestroy { async closeModal() { await this.router.navigate(["/"]); - await this.desktopSettingsService.setInModalMode(false); + await this.desktopSettingsService.setModalMode(false); this.session.notifyConfirmCredential(false); // little bit hacky: diff --git a/apps/desktop/src/autofill/services/desktop-autofill.service.ts b/apps/desktop/src/autofill/services/desktop-autofill.service.ts index 3d19699c2eb..1f84a55a428 100644 --- a/apps/desktop/src/autofill/services/desktop-autofill.service.ts +++ b/apps/desktop/src/autofill/services/desktop-autofill.service.ts @@ -37,6 +37,8 @@ import { NativeAutofillSyncCommand, } from "../../platform/main/autofill/sync.command"; +import type { NativeWindowObject } from "./desktop-fido2-user-interface.service"; + @Injectable() export class DesktopAutofillService implements OnDestroy { private destroy$ = new Subject(); @@ -45,7 +47,7 @@ export class DesktopAutofillService implements OnDestroy { private logService: LogService, private cipherService: CipherService, private configService: ConfigService, - private fido2AuthenticatorService: Fido2AuthenticatorServiceAbstraction, + private fido2AuthenticatorService: Fido2AuthenticatorServiceAbstraction, private accountService: AccountService, ) {} @@ -147,7 +149,11 @@ export class DesktopAutofillService implements OnDestroy { const controller = new AbortController(); void this.fido2AuthenticatorService - .makeCredential(this.convertRegistrationRequest(request), null, controller) + .makeCredential( + this.convertRegistrationRequest(request), + { windowXy: request.windowXy as [number, number] }, // TODO: Not sure if we want to change the type of windowXy to just number[] or if rust can generate [number,number]? + controller, + ) .then((response) => { callback(null, this.convertRegistrationResponse(request, response)); }) @@ -198,7 +204,11 @@ export class DesktopAutofillService implements OnDestroy { const controller = new AbortController(); void this.fido2AuthenticatorService - .getAssertion(this.convertAssertionRequest(request, true), null, controller) + .getAssertion( + this.convertAssertionRequest(request, true), + { windowXy: request.windowXy as [number, number] }, + controller, + ) .then((response) => { callback(null, this.convertAssertionResponse(request, response)); }) @@ -214,7 +224,11 @@ export class DesktopAutofillService implements OnDestroy { const controller = new AbortController(); void this.fido2AuthenticatorService - .getAssertion(this.convertAssertionRequest(request), null, controller) + .getAssertion( + this.convertAssertionRequest(request), + { windowXy: request.windowXy as [number, number] }, + controller, + ) .then((response) => { callback(null, this.convertAssertionResponse(request, response)); }) diff --git a/apps/desktop/src/autofill/services/desktop-fido2-user-interface.service.ts b/apps/desktop/src/autofill/services/desktop-fido2-user-interface.service.ts index dccb4472442..9bb3f8bedbf 100644 --- a/apps/desktop/src/autofill/services/desktop-fido2-user-interface.service.ts +++ b/apps/desktop/src/autofill/services/desktop-fido2-user-interface.service.ts @@ -6,8 +6,9 @@ import { Subject, filter, take, - timeout, BehaviorSubject, + Observable, + timeout, } from "rxjs"; import { AccountService } from "@bitwarden/common/auth/abstractions/account.service"; @@ -33,10 +34,18 @@ import { SecureNoteView } from "@bitwarden/common/vault/models/view/secure-note. import { DesktopSettingsService } from "src/platform/services/desktop-settings.service"; -// import the angular router +/** + * This type is used to pass the window position from the native UI + */ +export type NativeWindowObject = { + /** + * The position of the window, first entry is the x position, second is the y position + */ + windowXy?: [number, number]; +}; export class DesktopFido2UserInterfaceService - implements Fido2UserInterfaceServiceAbstraction + implements Fido2UserInterfaceServiceAbstraction { constructor( private authService: AuthService, @@ -55,18 +64,18 @@ export class DesktopFido2UserInterfaceService async newSession( fallbackSupported: boolean, - _tab: void, + nativeWindowObject: NativeWindowObject, abortController?: AbortController, ): Promise { - this.logService.warning("newSession", fallbackSupported, abortController); + this.logService.warning("newSession", fallbackSupported, abortController, nativeWindowObject); const session = new DesktopFido2UserInterfaceSession( this.authService, this.cipherService, this.accountService, this.logService, - this.messagingService, this.router, this.desktopSettingsService, + nativeWindowObject, ); this.currentSession = session; @@ -80,9 +89,9 @@ export class DesktopFido2UserInterfaceSession implements Fido2UserInterfaceSessi private cipherService: CipherService, private accountService: AccountService, private logService: LogService, - private messagingService: MessagingService, private router: Router, private desktopSettingsService: DesktopSettingsService, + private windowObject: NativeWindowObject, ) {} private confirmCredentialSubject = new Subject(); @@ -90,8 +99,17 @@ export class DesktopFido2UserInterfaceSession implements Fido2UserInterfaceSessi private createdCipher: Cipher; private updatedCipher: CipherView; - private availableCipherIds = new BehaviorSubject(null); private rpId = new BehaviorSubject(null); + private availableCipherIdsSubject = new BehaviorSubject(null); + /** + * Observable that emits available cipher IDs once they're confirmed by the UI + */ + get availableCipherIds$(): Observable { + return this.availableCipherIdsSubject.pipe( + filter((ids) => ids != null), + take(1), + ); + } private chosenCipherSubject = new Subject(); @@ -124,9 +142,9 @@ export class DesktopFido2UserInterfaceSession implements Fido2UserInterfaceSessi // make the cipherIds available to the UI. // Not sure if the UI also need to know about masterPasswordRepromptRequired -- probably not, otherwise we can send all of the params. - this.availableCipherIds.next(cipherIds); + this.availableCipherIdsSubject.next(cipherIds); - await this.showUi("/passkeys"); + await this.showUi("/passkeys", this.windowObject.windowXy); const chosenCipherId = await this.waitForUiChosenCipher(); @@ -141,31 +159,17 @@ export class DesktopFido2UserInterfaceSession implements Fido2UserInterfaceSessi return { cipherId: resultCipherId, userVerified: true }; } finally { // Make sure to clean up so the app is never stuck in modal mode? - await this.desktopSettingsService.setInModalMode(false); + await this.desktopSettingsService.setModalMode(false); } } - /** - * Returns once the UI has confirmed and completed the operation - * @returns - */ - async getAvailableCipherIds(): Promise { - return lastValueFrom( - this.availableCipherIds.pipe( - filter((ids) => ids != null), - take(1), - timeout(50000), - ), - ); - } - async getRpId(): Promise { console.log("getRpId"); return lastValueFrom( this.rpId.pipe( filter((id) => id != null), take(1), - timeout(50000), + timeout(5000), // 5 seconds timeout ), ); } @@ -219,7 +223,7 @@ export class DesktopFido2UserInterfaceSession implements Fido2UserInterfaceSessi this.rpId.next(rpId); try { - await this.showUi("/passkey-create"); + await this.showUi("/create-passkey", this.windowObject.windowXy); // Wait for the UI to wrap up const confirmation = await this.waitForUiNewCredentialConfirmation(); @@ -244,17 +248,14 @@ export class DesktopFido2UserInterfaceSession implements Fido2UserInterfaceSessi } } finally { // Make sure to clean up so the app is never stuck in modal mode? - await this.desktopSettingsService.setInModalMode(false); + await this.desktopSettingsService.setModalMode(false); } } - private async showUi(route: string) { + private async showUi(route: string, position?: [number, number]): Promise { // Load the UI: // maybe toggling to modal mode shouldn't be done here? - await this.desktopSettingsService.setInModalMode(true); - //pass the rpid to the fido2placeholder component through routing parameter - - // await this.router.navigate(["/passkeys"]); + await this.desktopSettingsService.setModalMode(true, position); await this.router.navigate([route]); } diff --git a/apps/desktop/src/locales/en/messages.json b/apps/desktop/src/locales/en/messages.json index c7f7f919499..02fd317632b 100644 --- a/apps/desktop/src/locales/en/messages.json +++ b/apps/desktop/src/locales/en/messages.json @@ -3436,5 +3436,8 @@ }, "savePasskeyQuestion": { "message": "Save passkey?" + }, + "saveNewPasskey": { + "message": "Save as new login" } } diff --git a/apps/desktop/src/main.ts b/apps/desktop/src/main.ts index c1f08927073..1ff9fe1675c 100644 --- a/apps/desktop/src/main.ts +++ b/apps/desktop/src/main.ts @@ -279,7 +279,7 @@ export class Main { async () => { await this.toggleHardwareAcceleration(); // Reset modal mode to make sure main window is displayed correctly - await this.desktopSettingsService.resetInModalMode(); + await this.desktopSettingsService.resetModalMode(); await this.windowMain.init(); await this.i18nService.init(); await this.messagingMain.init(); diff --git a/apps/desktop/src/main/window.main.ts b/apps/desktop/src/main/window.main.ts index 5420959e287..5a600070d56 100644 --- a/apps/desktop/src/main/window.main.ts +++ b/apps/desktop/src/main/window.main.ts @@ -77,18 +77,19 @@ export class WindowMain { } }); - this.desktopSettingsService.inModalMode$ + this.desktopSettingsService.modalMode$ .pipe( pairwise(), concatMap(async ([lastValue, newValue]) => { - if (lastValue && !newValue) { + if (lastValue.isModalModeActive && !newValue.isModalModeActive) { // Reset the window state to the main window state applyMainWindowStyles(this.win, this.windowStates[mainWindowSizeKey]); // Because modal is used in front of another app, UX wise it makes sense to hide the main window when leaving modal mode. this.win.hide(); - } else if (!lastValue && newValue) { + } else if (!lastValue.isModalModeActive && newValue.isModalModeActive) { // Apply the popup modal styles - applyPopupModalStyles(this.win); + this.logService.info("Applying popup modal styles", newValue.modalPosition); + applyPopupModalStyles(this.win, newValue.modalPosition); this.win.show(); } }), @@ -202,13 +203,15 @@ export class WindowMain { } } + // TODO: REMOVE ONCE WE CAN STOP USING FAKE POP UP BTN FROM TRAY + // Only used during initial UI development async loadUrl(targetPath: string, modal: boolean = false) { if (this.win == null || this.win.isDestroyed()) { await this.createWindow("modal-app"); return; } - await this.desktopSettingsService.setInModalMode(modal); + await this.desktopSettingsService.setModalMode(modal); await this.win.loadURL( url.format({ protocol: "file:", @@ -404,9 +407,9 @@ export class WindowMain { return; } - const inModalMode = await firstValueFrom(this.desktopSettingsService.inModalMode$); + const modalMode = await firstValueFrom(this.desktopSettingsService.modalMode$); - if (inModalMode) { + if (modalMode.isModalModeActive) { return; } diff --git a/apps/desktop/src/modal/passkeys/create/fido2-create.component.html b/apps/desktop/src/modal/passkeys/create/fido2-create.component.html index 8dbf6639a67..266f3bb8882 100644 --- a/apps/desktop/src/modal/passkeys/create/fido2-create.component.html +++ b/apps/desktop/src/modal/passkeys/create/fido2-create.component.html @@ -1,4 +1,4 @@ -
+
-

{{ "savePasskeyQuestion" | i18n }}

+

{{ "savePasskeyQuestion" | i18n }}

- + + + + + + +
diff --git a/apps/desktop/src/modal/passkeys/create/fido2-create.component.ts b/apps/desktop/src/modal/passkeys/create/fido2-create.component.ts index 0baa0d61770..365dd8a7ad5 100644 --- a/apps/desktop/src/modal/passkeys/create/fido2-create.component.ts +++ b/apps/desktop/src/modal/passkeys/create/fido2-create.component.ts @@ -115,7 +115,7 @@ export class Fido2CreateComponent implements OnInit { // The session currently toggles modal on and send us here // But if this route is somehow opened outside of session we want to make sure we clean up? await this.router.navigate(["/"]); - await this.desktopSettingsService.setInModalMode(false); + await this.desktopSettingsService.setModalMode(false); } catch (error) { // TODO: Handle error appropriately } @@ -123,7 +123,8 @@ export class Fido2CreateComponent implements OnInit { async closeModal() { await this.router.navigate(["/"]); - await this.desktopSettingsService.setInModalMode(false); + await this.desktopSettingsService.setModalMode(false); this.session.notifyConfirmCredential(false); + this.session.confirmChosenCipher(null); } } diff --git a/apps/desktop/src/modal/passkeys/fido2-vault.component.html b/apps/desktop/src/modal/passkeys/fido2-vault.component.html index 9e1cf9433be..edc241c4d21 100644 --- a/apps/desktop/src/modal/passkeys/fido2-vault.component.html +++ b/apps/desktop/src/modal/passkeys/fido2-vault.component.html @@ -1,4 +1,4 @@ -
+
-

{{ "passkeyLogin" | i18n }}

+

{{ "passkeyLogin" | i18n }}