diff --git a/apps/desktop/macos/autofill-extension/Base.lproj/CredentialProviderViewController.xib b/apps/desktop/macos/autofill-extension/Base.lproj/CredentialProviderViewController.xib
index d7f54c4521e..6bcbd589ce3 100644
--- a/apps/desktop/macos/autofill-extension/Base.lproj/CredentialProviderViewController.xib
+++ b/apps/desktop/macos/autofill-extension/Base.lproj/CredentialProviderViewController.xib
@@ -1,96 +1,70 @@
-
+
-
-
+
+
+
-
+
-
+
-
-
-
-
+
+
+
+
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
-
+
-
\ No newline at end of file
+
diff --git a/apps/desktop/macos/autofill-extension/CredentialProviderViewController.swift b/apps/desktop/macos/autofill-extension/CredentialProviderViewController.swift
index a6d894e0b84..38a1e707fc1 100644
--- a/apps/desktop/macos/autofill-extension/CredentialProviderViewController.swift
+++ b/apps/desktop/macos/autofill-extension/CredentialProviderViewController.swift
@@ -48,6 +48,13 @@ class CredentialProviderViewController: ASCredentialProviderViewController {
let passwordCredential = ASPasswordCredential(user: "j_appleseed", password: "apple1234")
self.extensionContext.completeRequest(withSelectedCredential: passwordCredential, completionHandler: nil)
}
+
+ override func loadView() {
+ let view = NSView()
+ view.isHidden = true
+ //view.backgroundColor = .clear
+ self.view = view
+ }
/*
Implement this method if your extension supports showing credentials in the QuickType bar.
@@ -77,6 +84,8 @@ class CredentialProviderViewController: ASCredentialProviderViewController {
}
override func provideCredentialWithoutUserInteraction(for credentialRequest: any ASCredentialRequest) {
+
+
if let request = credentialRequest as? ASPasskeyCredentialRequest {
if let passkeyIdentity = request.credentialIdentity as? ASPasskeyCredentialIdentity {
@@ -155,6 +164,13 @@ class CredentialProviderViewController: ASCredentialProviderViewController {
override func prepareInterface(forPasskeyRegistration registrationRequest: ASCredentialRequest) {
logger.log("[autofill-extension] prepareInterface")
+ // 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()
+ }
+
if let request = registrationRequest as? ASPasskeyCredentialRequest {
if let passkeyIdentity = registrationRequest.credentialIdentity as? ASPasskeyCredentialIdentity {
logger.log("[autofill-extension] prepareInterface(passkey) called \(request)")
@@ -234,4 +250,8 @@ class CredentialProviderViewController: ASCredentialProviderViewController {
}
}
+ private func configureTimeoutUI() {
+ self.view.isHidden = false;
+ }
+
}
diff --git a/apps/desktop/src/app/components/fido2placeholder.component.ts b/apps/desktop/src/app/components/fido2placeholder.component.ts
index e5d2b9f85bb..1e0b55b7c23 100644
--- a/apps/desktop/src/app/components/fido2placeholder.component.ts
+++ b/apps/desktop/src/app/components/fido2placeholder.component.ts
@@ -65,7 +65,7 @@ export class Fido2PlaceholderComponent implements OnInit {
// userVerification: true,
// });
- this.session.notifyConfirmCredential();
+ this.session.notifyConfirmCredential(true);
// Not sure this clean up should happen here or in session.
// The session currently toggles modal on and send us here
@@ -80,5 +80,7 @@ export class Fido2PlaceholderComponent implements OnInit {
async closeModal() {
await this.router.navigate(["/"]);
await this.desktopSettingsService.setInModalMode(false);
+
+ this.session.notifyConfirmCredential(false);
}
}
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 46171aa130a..f030d093856 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
@@ -80,14 +80,14 @@ export class DesktopFido2UserInterfaceSession implements Fido2UserInterfaceSessi
params: PickCredentialParams,
) => Promise<{ cipherId: string; userVerified: boolean }>;
- private confirmCredentialSubject = new Subject();
+ private confirmCredentialSubject = new Subject();
private createdCipher: Cipher;
/**
* Notifies the Fido2UserInterfaceSession that the UI operations has completed and it can return to the OS.
*/
- notifyConfirmCredential() {
- this.confirmCredentialSubject.next();
+ notifyConfirmCredential(confirmed: boolean): void {
+ this.confirmCredentialSubject.next(confirmed);
this.confirmCredentialSubject.complete();
}
@@ -95,7 +95,7 @@ export class DesktopFido2UserInterfaceSession implements Fido2UserInterfaceSessi
* Returns once the UI has confirmed and completed the operation
* @returns
*/
- private async waitForUiCredentialConfirmation(): Promise {
+ private async waitForUiCredentialConfirmation(): Promise {
return lastValueFrom(this.confirmCredentialSubject);
}
@@ -122,8 +122,10 @@ export class DesktopFido2UserInterfaceSession implements Fido2UserInterfaceSessi
await this.showUi();
// Wait for the UI to wrap up
- await this.waitForUiCredentialConfirmation();
-
+ const confirmation = await this.waitForUiCredentialConfirmation();
+ if (!confirmation) {
+ throw new Error("User cancelled");
+ }
// Create the credential
await this.createCredential({
credentialName,