8000 [PM-10450] Fix FIdo2 never lock user verification not appearing by fedemkr · Pull Request #787 · bitwarden/ios · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

[PM-10450] Fix FIdo2 never lock user verification not appearing #787

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Aug 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import AuthenticationServices
import BitwardenSdk
import BitwardenShared
import Combine
import OSLog

/// An `ASCredentialProviderViewController` that implements credential autofill.
Expand All @@ -11,12 +12,21 @@
/// The app's theme.
var appTheme: AppTheme = .default

/// A subject containing whether the controller did appear.
private var didAppearSubject = CurrentValueSubject<Bool, Never>(false)

Check warning on line 16 in BitwardenAutoFillExtension/CredentialProviderViewController.swift

View check run for this annotation

Codecov / codecov/patch

BitwardenAutoFillExtension/CredentialProviderViewController.swift#L16

Added line #L16 was not covered by tests

/// The processor that manages application level logic.
private var appProcessor: AppProcessor?

/// The context of the credential provider to see how the extension is being used.
private var context: CredentialProviderContext?

override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)

Check warning on line 25 in BitwardenAutoFillExtension/CredentialProviderViewController.swift

View check run for this annotation

Codecov / codecov/patch

BitwardenAutoFillExtension/CredentialProviderViewController.swift#L24-L25

Added lines #L24 - L25 were not covered by tests

didAppearSubject.send(true)

Check warning on line 27 in BitwardenAutoFillExtension/CredentialProviderViewController.swift

View check run for this annotation

Codecov / codecov/patch

BitwardenAutoFillExtension/CredentialProviderViewController.swift#L27

Added line #L27 was not covered by tests
}

// MARK: ASCredentialProviderViewController

override func prepareCredentialList(for serviceIdentifiers: [ASCredentialServiceIdentifier]) {
Expand Down Expand Up @@ -307,6 +317,12 @@
extensionContext.completeRegistrationRequest(using: asPasskeyRegistrationCredential)
}

func getDidAppearPublisher() -> AsyncPublisher<AnyPublisher<Bool, Never>> {
didAppearSubject
.eraseToAnyPublisher()
.values

Check warning on line 323 in BitwardenAutoFillExtension/CredentialProviderViewController.swift

View check run for this annotation

Codecov / codecov/patch

BitwardenAutoFillExtension/CredentialProviderViewController.swift#L320-L323

Added lines #L320 10000 - L323 were not covered by tests
}

func setUserInteractionRequired() {
context?.flowFailedBecauseUserInteractionRequired = true
cancel(error: ASExtensionError(.userInteractionRequired))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1579,8 +1579,6 @@ class AuthRepositoryTests: BitwardenTestCase { // swiftlint:disable:this type_bo

/// `validatePin(_:)` returns `false` if the there is no active account.
func test_validatePin_noActiveAccount() async throws {
let account = Account.fixture()

let isPinValid = try await subject.validatePin(pin: "123")

XCTAssertFalse(isPinValid)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import AuthenticationServices
import Combine

/// A delegate that is used to handle actions and retrieve information from within an Autofill extension
/// on Fido2 flows.
Expand All @@ -19,6 +20,9 @@ public protocol Fido2AppExtensionDelegate: AppExtensionDelegate {
@available(iOSApplicationExtension 17.0, *)
func completeRegistrationRequest(asPasskeyRegistrationCredential: ASPasskeyRegistrationCredential)

/// Gets a publisher for when `didAppear` happens.
func getDidAppearPublisher() -> AsyncPublisher<AnyPublisher<Bool, Never>>

/// Marks that user interaction is required.
func setUserInteractionRequired()
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import AuthenticationServices
import Combine
import Foundation

@testable import BitwardenShared
Expand All @@ -8,6 +9,7 @@ class MockFido2AppExtensionDelegate: MockAppExtensionDelegate, Fido2AppExtension
var completeAssertionRequestMocker = InvocationMocker<ASPasskeyAssertionCredential>()
var completeRegistrationRequestMocker = InvocationMocker<ASPasskeyRegistrationCredential>()
var extensionMode: AutofillExtensionMode = .configureAutofill
var didAppearPublisher = CurrentValueSubject<Bool, Never>(false)
var setUserInteractionRequiredCalled = false

var flowWithUserInteraction: Bool = true
Expand All @@ -20,6 +22,12 @@ class MockFido2AppExtensionDelegate: MockAppExtensionDelegate, Fido2AppExtension
completeRegistrationRequestMocker.invoke(param: asPasskeyRegistrationCredential)
}

func getDidAppearPublisher() -> AsyncPublisher<AnyPublisher<Bool, Never>> {
didAppearPublisher
.eraseToAnyPublisher()
.values
}

func setUserInteractionRequired() {
setUserInteractionRequiredCalled = true
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -129,9 +129,15 @@ class AppProcessorFido2Tests: BitwardenTestCase {
func test_onNeedsUserInteraction_flowWithUserInteraction() async {
appExtensionDelegate.flowWithUserInteraction = true

await assertAsyncDoesNotThrow {
let taskResult = Task {
try await subject.onNeedsUserInteraction()
}

appExtensionDelegate.didAppearPublisher.send(true)

await assertAsyncDoesNotThrow {
try await taskResult.value
}
XCTAssertFalse(appExtensionDelegate.setUserInteractionRequiredCalled)
}

Expand Down
17 changes: 15 additions & 2 deletions BitwardenShared/UI/Platform/Application/AppProcessor.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import AuthenticationServices
import BitwardenSdk
import Combine
import Foundation
import OSLog
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⛏️ If we don't have logs in the file we shouldn't have this

import UIKit

/// The `AppProcessor` processes actions received at the application level and contains the logic
Expand Down Expand Up @@ -423,11 +424,23 @@ extension AppProcessor: Fido2UserInterfaceHelperDelegate {
}

func onNeedsUserInteraction() async throws {
if let fido2AppExtensionDelegate = appExtensionDelegate as? Fido2AppExtensionDelegate,
!fido2AppExtensionDelegate.flowWithUserInteraction {
guard let fido2AppExtensionDelegate = appExtensionDelegate as? Fido2AppExtensionDelegate else {
return
}

if !fido2AppExtensionDelegate.flowWithUserInteraction {
fido2AppExtensionDelegate.setUserInteractionRequired()
throw Fido2Error.userInteractionRequired
}

// WORKAROUND: We need to wait until the view controller appears in order to perform any
// action that needs user interaction or it might not show the prompt to the user.
// E.g. without this there are certain devices that don't show the FaceID prompt
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⛏️ "E.g." means "for example" ("exempli gratia"); if you want "that is" or "in other words", that'd be "i.e." ("id est")

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wanted exampli gratia, as there are other cases in which this happens as setting up the PIN.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool, wasn't sure!

// and the user only sees the screen dimming a bit and failing the flow.
Comment on lines +436 to +439
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

for await didAppear in fido2AppExtensionDelegate.getDidAppearPublisher() {
guard didAppear else { continue }
return
}
}

func showAlert(_ alert: Alert) {
Expand Down
Loading
0