Thanks to visit codestin.com
Credit goes to github.com

Skip to content
This repository was archived by the owner on Feb 22, 2023. It is now read-only.

[local_auth] Remove FingerprintManager uses and fix deprecations #6059

Merged
merged 15 commits into from
Jul 27, 2022

Conversation

camsim99
Copy link
Contributor

@camsim99 camsim99 commented Jun 29, 2022

Fixes

  • Issue #106298
  • Partially Issue #78137 by removing Android deprecations (not Flutter deprecations)
  • Issue #105005 by explicitly setting device credentials as an allowed authenticator if applicable

Also expands test suite for LocalAuthPlugin.java.

Pre-launch Checklist

  • I read the Contributor Guide and followed the process outlined there for submitting PRs.
  • I read the Tree Hygiene wiki page, which explains my responsibilities.
  • I read and followed the relevant style guides and ran the auto-formatter. (Unlike the flutter/flutter repo, the flutter/plugins repo does use dart format.)
  • I signed the CLA.
  • The title of the PR starts with the name of the plugin surrounded by square brackets, e.g. [shared_preferences]
  • I listed at least one issue that this PR fixes in the description above.
  • I updated pubspec.yaml with an appropriate new version according to the pub versioning philosophy, or this PR is exempt from version changes.
  • I updated CHANGELOG.md to add a description of the change, following repository CHANGELOG style.
  • I updated/added relevant documentation (doc comments with ///).
  • I added new tests to check the change I am making, or this PR is test-exempt.
  • All existing and new tests are passing.

@@ -90,9 +92,27 @@ interface AuthCompletionHandler {
.setConfirmationRequired((Boolean) call.argument("sensitiveTransaction"))
.setConfirmationRequired((Boolean) call.argument("sensitiveTransaction"));

if (allowCredentials) {
promptBuilder.setDeviceCredentialAllowed(true);
Copy link
Contributor Author

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) {
Copy link
Contributor Author

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.

Copy link
Contributor

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?

Copy link
Contributor Author

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) {
Copy link
Contributor Author

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.

Copy link
Contributor

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) {
Copy link
Contributor Author

@camsim99 camsim99 Jul 6, 2022

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.

@camsim99 camsim99 marked this pull request as ready for review July 6, 2022 23:04
@camsim99 camsim99 requested a review from stuartmorgan-g July 6, 2022 23:04
@@ -74,7 +76,7 @@ interface AuthCompletionHandler {
FragmentActivity activity,
MethodCall call,
AuthCompletionHandler completionHandler,
boolean allowCredentials) {
ArrayList<String> authenticationMethods) {
Copy link
Contributor

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?

Copy link
Contributor Author

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.

authHelper.authenticate();
// Handle case where only device credential is available
if (!isBiometricOnly && canAuthenticateWithDeviceCredential()) {
if (Build.VERSION.SDK_INT >= 30) {
Copy link
Contributor

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?

@camsim99 camsim99 requested a review from stuartmorgan-g July 13, 2022 22:33
Copy link
Contributor

@stuartmorgan-g stuartmorgan-g left a 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) {
Copy link
Contributor

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.

Copy link
Contributor Author

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) {
Copy link
Contributor

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)) {
Copy link
Contributor

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?

Copy link
Contributor Author

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!

@stuartmorgan-g
Copy link
Contributor

I think you need to remove this line:

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!

@camsim99 camsim99 added the autosubmit Merge PR when tree becomes green via auto submit App label Jul 26, 2022
@auto-submit auto-submit bot merged commit 04e8d66 into flutter:main Jul 27, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
autosubmit Merge PR when tree becomes green via auto submit App p: local_auth platform-android
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants