Skip to content

Feature request: Add Biometric Authentication Process as an Option #615

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

Open
ttorii20 opened this issue Sep 19, 2023 · 14 comments · May be fixed by #878
Open

Feature request: Add Biometric Authentication Process as an Option #615

ttorii20 opened this issue Sep 19, 2023 · 14 comments · May be fixed by #878

Comments

@ttorii20
Copy link

I am interested in adding a biometric authentication process for storage access authentication on each platform. Specifically, I'd like to introduce an option that requires biometric authentication when accessing the keychain on iOS and the keystore on Android.

Currently, flutter_secure_storage does not have such a feature, and there's no way to set this as an option. I believe adding the ability to set a biometric authentication process as an option would be beneficial.

Differences Across Platforms

The method of requesting biometric authentication from the user varies by platform. On iOS, the keychain handles the responsibility of controlling the biometric authentication dialog. In contrast, the Android keystore does not. Therefore, it's necessary to handle errors and display the biometric authentication dialog when required on Android.

For Android:
I'd like to introduce options similar to setUserAuthenticationRequired and setUserAuthenticationValidityDurationSeconds. Here's a snippet to illustrate the desired functionality:

  private SharedPreferences initializeEncryptedSharedPreferencesManagerAuthenticationRequired(Context context,
            int authenticationValidityDurationSeconds) throws GeneralSecurityException, IOException {
        MasterKey key = new MasterKey.Builder(context, masterKeyAlias)
                .setKeyGenParameterSpec(
                        new KeyGenParameterSpec.Builder(masterKeyAlias,
                                KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
                                .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
                                .setBlockModes(KeyProperties.BLOCK_MODE_GCM)
                                .setKeySize(256)
                                .setUserAuthenticationRequired(true)
                                .setUserAuthenticationValidityDurationSeconds(
                                    authenticationValidityDurationSeconds
                                )
                                .setInvalidatedByBiometricEnrollment(true)
                                .build())

For iOS:
I'd like to introduce an option to set SecAccessControlCreateFlags.biometryCurrentSet for the keychain. Here's a snippet to illustrate the desired functionality:


if let accessControl = accessControl {
    var secAccessControlCreateFlags: SecAccessControlCreateFlags
    // ... other code ...
    }  else if accessControl == "biometryCurrentSet" {
        secAccessControlCreateFlags = SecAccessControlCreateFlags.biometryCurrentSet
    }  else {
        abort()
    }
    // ... other code ...
    accessControlCreateWithFlags = SecAccessControlCreateWithFlags(kCFAllocatorDefault,
                                                                           attrAccessible,
                                                                           secAccessControlCreateFlags,
                                                                           &error)
 // ... other code ...
    var keychainQuery = baseQuery(key: key, groupId: groupId, accountName: accountName, synchronizable: synchronizable, returnData: nil, accessControl: accessControlCreateWithFlags)
   // ... other code ...
   return SecItemAdd(keychainQuery as CFDictionary, nil)

}

Anticipated Use Case

The primary use case I envision is during user login, where biometric authentication is performed to access the necessary information for authentication.

@MacOMNI
Copy link

MacOMNI commented Oct 2, 2023

That is a good idea!!

@bogdannedelcu
Copy link

@ttorii20 please add for Android also a flag to force the storage of the key on the TEE, not doing so would result in not creating the key. This is important for certification processes

@ttorii20
Copy link
Author

@bogdannedelcu
Thanks for bringing this up. Just to be sure, are you suggesting we add an IsStrongBoxBacked flag for Android? And if it's about beefing up security, should we roll this into the main stream instead of a fork?

@bogdannedelcu
Copy link

bogdannedelcu commented Dec 26, 2023 via email

@u382514
Copy link

u382514 commented Feb 15, 2024

I second this and would love to see this sooner than later. Seems like the the current approach is to retrieve a simple true/false from biometrics (using local_auth package?) and using that as the sole trust to access secure storage for the data. I'd like to not just get a true/false but that secure storage cannot literally access the keychain/keystore unless biometric auth has opened it up.

@humphrey
Copy link

+1 for this.

@juliansteenbakker
Copy link
Owner

I am closing all older issues. If this issue still exists in the latest version, please let me know.

@CodeCommander
Copy link

CodeCommander commented Dec 5, 2024

@juliansteenbakker I'm considering using this library for my project and noticed that this feature appears to be missing. It seems like it would be a relatively easy addition (on the iOS side at least) to just support setting a value for kSecAttrAccessControl around line 44 of this file: https://github.com/juliansteenbakker/flutter_secure_storage/blob/develop/flutter_secure_storage/ios/Classes/FlutterSecureStorage.swift

Also see Apple documentation: https://developer.apple.com/documentation/security/ksecattraccesscontrol

@AlexanderThiele
Copy link

I would love to see this feature in this library. Is it tracked somewhere else, or can we re-open this ticket again?

@juliansteenbakker

@nameddorna
Copy link

I second this and would love to see this sooner than later. Seems like the the current approach is to retrieve a simple true/false from biometrics (using local_auth package?) and using that as the sole trust to access secure storage for the data. I'd like to not just get a true/false but that secure storage cannot literally access the keychain/keystore unless biometric auth has opened it up.

I’m also very interested in having this implemented, as relying solely on a true/false response from biometric authentication (via local_auth) is not secure enough for protecting sensitive data. @juliansteenbakker

Looking forward to any updates on this and Thanks for your great work!

@juliansteenbakker
Copy link
Owner

I have added accessControlFlags to the AppleOptions, which you can use to set biometric authentication. This will work on macOS and iOS. Code is now available on the develop branch and will be released in the next beta version.

Android implementation will be added in a later release.

@juliansteenbakker juliansteenbakker linked a pull request Feb 4, 2025 that will close this issue
@Kun19
Copy link

Kun19 commented Feb 6, 2025

Hi @juliansteenbakker,

first of all thank you for your plugin and for your work. As a security researcher/consultant I started looking into the Android implementation of the biometric authentication to be able to recommend the plugin to clients....

It looks like that the biometric authentication is just "event-bound". If the onAuthenticationSucceeded callback is called the passed BiometricPrompt.AuthenticationResult and the included CryptoObject is NOT considered/checked (see https://github.com/juliansteenbakker/flutter_secure_storage/blob/feat/access-control-android/flutter_secure_storage/android/src/main/java/com/it_nomads/fluttersecurestorage/FlutterSecureStorage.java#L270).

This makes it possible for an attacker to bypass the biometric authentication (with specific Frida scripts). For the details (secure implementation) you can have a look at this blog post: https://labs.withsecure.com/publications/how-secure-is-your-android-keystore-authentication

I would like to make you aware of this so that you have the chance to bring it into the next release :)

Kind Regards

@juliansteenbakker
Copy link
Owner

Hi, thank you for noticing! I am aware of this issue, and i am currently in the process of rewriting the whole EncryptedSharedPreferences part so this is handled correctly. The PR is still a draft to check if tests are failing. Once i have production ready code, i will let it know here so it can be verified.

Copy link

github-actions bot commented Apr 8, 2025

⚠️ This issue has been marked as stale because it has been open for 60 days with no activity.

If this issue is still relevant, please comment to keep it active. Otherwise, it will be closed in 60 days.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

10 participants