bitwarden / mobile

Retired Bitwarden mobile app for iOS and Android (MAUI/Xamarin).
https://bitwarden.com
GNU General Public License v3.0
65 stars 9 forks source link

iOS Autofill: 'provide credentials without user interaction' does not work #1862

Open pLmzIpdQtffyP3ZXJvHAwH0DRIamzyX74bteE6J opened 2 years ago

pLmzIpdQtffyP3ZXJvHAwH0DRIamzyX74bteE6J commented 2 years ago

Steps To Reproduce

  1. In Safari, go to a website where the iOS keyboard can suggest a password from Bitwarden in the QuickType bar (using ASCredentialIdentityStore).
  2. Tap on the suggested account in the iOS QuickType bar to autofill the password of the selected account.

Expected Result

Similar to the built-in iCloud Keychain behavior, I would expect that the password of the selected account would be filled in immediately, after a quick Face ID or Touch ID authentication. No further view controller should be shown when filling in a password from a selected account in the QuickType bar.

Actual Result

In every case, the custom Bitwarden controller is being displayed after tapping on an account from the QuickType bar. The user has to wait until the presenting animation finishes, then the user is being authenticated using Face ID or Touch ID, and only then the password will be filled in.

Screenshots or Videos

Tapping on the blue button should invoke FaceID right away, like seen in the first video. Instead, the Bitwarden View Controller is always being presented, as can be seen in the second video.

https://user-images.githubusercontent.com/27898390/159992954-daced3f9-4ac0-44a7-8a94-b3df92803697.mov

https://user-images.githubusercontent.com/27898390/159992973-a56d9955-0c08-4686-9730-699a332462c9.MP4

Additional Context

Here are my findings after some initial debugging:

The relevant method for filling in passwords from the QuickType bar is ProvideCredentialWithoutUserInteraction. It seems like Bitwarden always returns UserInteractionRequired, which causes iOS to present the Bitwarden view controller: https://github.com/bitwarden/mobile/blob/4bd06d23935870dcfb0b43dcbc288de8689e34eb/src/iOS.Autofill/CredentialProviderViewController.cs#L85-L91

In my case, IsAuthed() always returned true, but IsLocked() returned true as well. Looking into VaultTimeoutService, it seems like this method is responsible for this behavior: https://github.com/bitwarden/mobile/blob/4bd06d23935870dcfb0b43dcbc288de8689e34eb/src/Core/Services/VaultTimeoutService.cs#L57-L69

biometricSet is always true, same as GetBiometricLockedAsync, meaning that the vault will always be in a "locked" state (at least until the password view controller has been shown).

Possible solution

As a disclaimer, I have looked into the Bitwarden code for the first time just to debug this behavior, so I am not confident to provide a pull request for this. However, I personally think that the IsLocked() method should not be checked inside ProvideCredentialWithoutUserInteraction because at this point in time of the application flow there would have been no way that BiometricLocked had been set to false previously. Further, the mandatory Face ID authorization provided by iOS when tapping on the QuickType bar already serves as a mechanism to "unlock" the vault, so checking for the lock state is not necessary. But again, I am not confident to say anything about possible security implications when removing this IsLocked() condition.

Operating System

iOS

Operating System Version

No response

Device

No response

Build Version

2.17.1

Beta

uukSzK2NDKW9hTMOiMXMsQJZkUxngsrpFR4nCv5 commented 1 year ago

This issue really bothered me when I began using Bitwarden. I made an issue about it and a suggested an insecure workaround on the forum: https://community.bitwarden.com/t/option-to-disable-verification-for-auto-fill-on-ios/46266

uukSzK2NDKW9hTMOiMXMsQJZkUxngsrpFR4nCv5 commented 1 year ago

I took a quick peek around the code and exactly what you mentioned seems to be where we can make a change. There's just one thing we need to account for: if the user has Password AutoFill disabled in iOS settings and Unlock with Face ID enabled in Bitwarden settings. In this case should we still prompt the Bitwarden UI? The user is explicitly disabling biometrics, perhaps Bitwarden should respect that?

Edit: It doesn't seem possible to read global device settings. I think the best route here would be to introduce a new setting to toggle biometrics for autofill.

uukSzK2NDKW9hTMOiMXMsQJZkUxngsrpFR4nCv5 commented 1 year ago

This is where the settings are handled for biometrics: https://github.com/bitwarden/mobile/blob/728182de6c8e8c5db723719a6eb347c46ceed9d4/src/Core/Services/StateService.cs#L239-L253 I propose we introduce a new setting named Use native Face ID or Disable pop-up, with a warning (the same warning you'd get when vault timeout is set to Never) just to clarify what it means, I don't think there's a better way to word it.

uukSzK2NDKW9hTMOiMXMsQJZkUxngsrpFR4nCv5 commented 1 year ago

Unfortunately my mac is too old to install the latest version of Xcode so there's not much I can do.