-
Notifications
You must be signed in to change notification settings - Fork 9.8k
[local_auth] Remove FingerprintManager uses and fix deprecations #6059
Conversation
@@ -90,9 +92,27 @@ interface AuthCompletionHandler { | |||
.setConfirmationRequired((Boolean) call.argument("sensitiveTransaction")) | |||
.setConfirmationRequired((Boolean) call.argument("sensitiveTransaction")); | |||
|
|||
if (allowCredentials) { | |||
promptBuilder.setDeviceCredentialAllowed(true); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This method was deprecated in favor of setAllowedAuthenticators
(documentation, so all authentication methods need to be known here versus just a boolean indicating whether or not to allow device credentials. See changes below.
authHelper.authenticate(); | ||
// Handle case where only device credential is available | ||
if (!isBiometricOnly && canAuthenticateWithDeviceCredential()) { | ||
if (Build.VERSION.SDK_INT >= 30) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For API 30+, an authentication request can be made by specifying device credentials alone as an allowed authenticator. See documentation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The docs for https://developer.android.com/reference/androidx/biometric/BiometricPrompt.PromptInfo.Builder#setDeviceCredentialAllowed(boolean) make it sound like all the fallback code we have here is already part of androidx.biometrics already. Can we eliminate all of this code and always just make a single sendAuthenticationRequest
call?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you may be right. I definitely misunderstood the API and overcomplicated this :/ I'll make the changes and request your review again!
BiometricManager.Authenticators.BIOMETRIC_WEAK | ||
| BiometricManager.Authenticators.DEVICE_CREDENTIAL); | ||
|
||
switch (errorCode) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added more error handling below based on the error messages of the new API. I changed some of the error messages, so let me know if those are magic strings and need to be changed back or added elsewhere.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think we should consider the message itself to be API-stable, just the code. (Theoretically someone could be relying on it of course, but they shouldn't be.)
return; | ||
} | ||
|
||
// API 23 - 28 with fingerprint | ||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && fingerprintManager != null) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The functionality this added is covered by BiometricPrompt
now. See documentation.
@@ -74,7 +76,7 @@ interface AuthCompletionHandler { | |||
FragmentActivity activity, | |||
MethodCall call, | |||
AuthCompletionHandler completionHandler, | |||
boolean allowCredentials) { | |||
ArrayList<String> authenticationMethods) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should avoid using string-based APIs internally; we have to use them for platform channels, but in other scenarios we should stick to things that would provide compile-time correctness checks.
Stepping back a bit though, do we need this change at all? It looks like this is passing in the enrolled authentication, but I wouldn't expect that we would need to restrict by that, vs. just letting the system pick what's available. Why not keep the bool, and then use it to decide whether to add DEVICE_CREDENTIAL
to the default of BIOMETRIC_WEAK | BIOMETRIC_STRONG
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, yes, you're definitely right. Since it's just specifying the allowed authenticators, I can keep the boolean and just add DEVICE_CREDENTIAL
depending like you're saying.
...al_auth_android/android/src/main/java/io/flutter/plugins/localauth/AuthenticationHelper.java
Outdated
Show resolved
Hide resolved
authHelper.authenticate(); | ||
// Handle case where only device credential is available | ||
if (!isBiometricOnly && canAuthenticateWithDeviceCredential()) { | ||
if (Build.VERSION.SDK_INT >= 30) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The docs for https://developer.android.com/reference/androidx/biometric/BiometricPrompt.PromptInfo.Builder#setDeviceCredentialAllowed(boolean) make it sound like all the fallback code we have here is already part of androidx.biometrics already. Can we eliminate all of this code and always just make a single sendAuthenticationRequest
call?
...h/local_auth_android/android/src/main/java/io/flutter/plugins/localauth/LocalAuthPlugin.java
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, but one question about whether we can simplify further.
authHelper.authenticate(); | ||
boolean allowCredentials = !isBiometricOnly && canAuthenticateWithDeviceCredential(); | ||
|
||
if (canAuthenticateWithBiometrics() || allowCredentials) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I haven't tried this out, so maybe I'm just misunderstanding the docs, but do we even need to do this check and the errorCode
computation below? If we just call authenticate
, wouldn't we get an immediate error callback for these cases (e.g., we tried to auth with biometrics only, but there were no biometrics) with the right code, which we could then translate into our own error result? It seems like we still may be duplicating some BiometricPrompt
logic here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, I see. I guess the idea before was that we could catch any issues before trying to authenticate (I assume the old APIs required this), but you're right. Now, we can just send the request and the AuthenticationHelper
should catch it since it provides the callbacks for authentication requests.
On this note, in a follow-up PR I will add tests for AuthenticationHelper
since that will do all of the error handling and is currently not tested.
BiometricManager.Authenticators.BIOMETRIC_WEAK | ||
| BiometricManager.Authenticators.DEVICE_CREDENTIAL); | ||
|
||
switch (errorCode) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think we should consider the message itself to be API-stable, just the code. (Theoretically someone could be relying on it of course, but they shouldn't be.)
result.error("NotSupported", "This device does not support required security features", null); | ||
@Override | ||
public void onError(String code, String error) { | ||
if (authInProgress.compareAndSet(true, false)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see that this is pre-existing, but do you know why only error cases set this back to false? Is there another call elsewhere for success/failure?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, the other callbacks call helper methods that set it back to false, as well!
I think you need to remove this line: Line 151 in 107ab29
now that we're just doing a single call. I assume that was there because we used to have multiple calls for biometric vs non-biometric attempts, but now we just have the one. It looks like with that line still there, we'd have a case where we would never return a result. Otherwise, stillLGTM! |
Fixes
Also expands test suite for LocalAuthPlugin.java.
Pre-launch Checklist
dart format
.)[shared_preferences]
pubspec.yaml
with an appropriate new version according to the pub versioning philosophy, or this PR is exempt from version changes.CHANGELOG.md
to add a description of the change, following repository CHANGELOG style.///
).