okta-mobile-kotlin
okta-mobile-kotlin copied to clipboard
Biometrics Sample Code
Describe the feature request?
Do you guys have any code samples for integrating biometrics with okta? I am trying to store the okta token so that it requires biometric credentials to unlock. I took a look at this sample but the code seems to be incomplete - https://github.com/okta/samples-android. I could not find any instructions or documentation on the exact mechanism how credentials can be locked behind biometrics. If you take a look at the official android documentation that doesn't incorporate okta, you will notice that their credential locking depends on the usage of a cipher which I see no usage of in the okta sample code - https://developer.android.com/training/sign-in/biometric-auth#kotlin.
New or Affected Resource(s)
https://github.com/okta/okta-mobile-kotlin/pull/207 https://github.com/okta/okta-mobile-kotlin/issues/226
Provide a documentation link
No response
Additional Information?
No response
@gusuly0rum, browser-sign-in sample in samples-android implements biometric encryption in this commit: https://github.com/okta/samples-android/commit/e83bda0bc6f85a843606b5a22334465126b43a56#diff-49361603563ae620a4d140801622437cb3df95ccbc8e68e4881a1f184da0de08 EncryptedSharedPreferences is used for biometric encryption in the sample. You can see how the EncryptedSharedPreferences is set up in SharedPreferencesModule in the linked commit for biometric and non-biometric encryption. BiometricCredentialSharedPrefs can't be read or written to unless the user has been authenticated with the biometric prompt.
I see, I am not seeing any examples of code that describes how to retrieve the token after being biometrically authenticated.
Should we use biometricalCredentialSharedPrefs.getString("blah", null)
? Or should we use CredentialBootstrap.defaultCredential().token
? Or something else? I tried accessing the token through CredentialBootstrap.defaultCredential().token
even before being successfully biometrically authenticated but I was able to access the token to my surprise.
@Module
@InstallIn(SingletonComponent::class)
class AuthenticationModule {
@Provides
@Singleton
fun provideKeyGenSpec(): KeyGenParameterSpec {
return KeyGenParameterSpec.Builder(
DEFAULT_MASTER_KEY_ALIAS,
KeyProperties.PURPOSE_ENCRYPT or KeyProperties.PURPOSE_DECRYPT)
.setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
.setBlockModes(KeyProperties.BLOCK_MODE_GCM)
.setKeySize(DEFAULT_AES_GCM_MASTER_KEY_SIZE)
.setUserAuthenticationParameters(60, KeyProperties.AUTH_BIOMETRIC_STRONG)
.setUserAuthenticationRequired(true)
.build()
}
@Provides
@Singleton
fun provideMasterKey(context: Context, keyGenSpec: KeyGenParameterSpec): MasterKey {
return MasterKey.Builder(context)
.setKeyGenParameterSpec(keyGenSpec)
.build()
}
@Provides
@Singleton
fun provideWebAuthClient(
context: Context,
oidcEndpoints: OidcEndpoints,
oidcConfiguration: OidcConfiguration,
keyGenSpec: KeyGenParameterSpec
): WebAuthenticationClient {
AuthFoundationDefaults.cache = SharedPreferencesCache.create(context)
val oidcClient = OidcClient.create(oidcConfiguration, oidcEndpoints)
CredentialBootstrap.initialize(oidcClient.createCredentialDataSource(context, keyGenSpec))
return CredentialBootstrap.oidcClient.createWebAuthenticationClient()
}
}
@gusuly0rum, you might need to clear the existing shared preferences in the app. The easiest way to test this is with uninstalling and reinstalling the app. createCredentialDataSource creates shared preferences with the same file name, so you're able to access it since it continues using the same encryption.