I'm trying to create a complete log in system in android studio. I want to allow a user to log in to their account with their fingerprint sensor from the app. There isn't a backend server, so how I understand it, is they would have to activate the feature if they wish, and their login details should be kept in somewhere within the app or the android system.
I came across encrypted shared prefs form android EncryptedSharedPreferences#inherited-methods which seemed promising but here https://issuetracker.google.com/issues/132325342 it states that " 2) tik is used for encryption/key management. However as I far as I can tell it on API < 23 keys generated by Tink are stored in plaintext in SharedPreferences tink-android which in the end makes EncryptedSharedPreferences no more secure that ordinary SharedPreferences. "
So I was thinking of manually encrypting the data in shared prefs and then store the keys in keystore, would that be secure enough or would the users login credentials be compromised? So far how-to-securely-store-encryption-keys-in-android seems to be the most valid answer but still unsure if it would be enough?
There are a few ways this could be done. Assuming you need to encrypt the user's data, there are 2 ways. Here is the official sample app which contains the two paths below.
First way: Key can only be unlocked by biometrics, user must authenticate with biometrics every time you wish to use the key.
setUserAuthenticationRequired(true)
, and setUserAuthenticationValidityDurationSeconds(-1)
BiometricPrompt#authenticate(CryptoObject)
onAuthenticationSucceeded()
, you can decrypt the data nowSecond way: Key can be unlocked by biometrics or pin/pattern/password, and used repeatedly within time t
since the last biometric/credential unlock. These keys are unlocked for your app whenever the user unlocks keyguard, or the settings credential screen.
setUserAuthenticationRequired(true)
, and setUserAuthenticationValidityDurationSeconds(t>0)
.BiometricPrompt#authenticate()
with setDeviceCredentialAllowed(true)
. Note that you do not need to wrap the keystore operation into a CryptoObject
in this case.onAuthenticationSucceeded()
, send the user into your appt
. If it's been over t
, attempting to use the key will result in UserNotAuthenticatedException
, and you should prompt the user for authentication again and go to step 2.