Skip to content

Commit faaeed2

Browse files
authored
[API Breaking] allowedAuthenticatorsOn{Enable,Authenticate} #222
ref DEV-3177 ref DEV-3146
2 parents 3f9c80f + fcd7754 commit faaeed2

6 files changed

Lines changed: 45 additions & 31 deletions

File tree

javasample/src/main/java/com/oursky/authgeartest/MainViewModel.java

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import androidx.lifecycle.LiveData;
1919
import androidx.lifecycle.MutableLiveData;
2020

21+
import com.oursky.authgear.BiometricAuthenticator;
2122
import com.oursky.authgear.PreAuthenticatedURLNotAllowedException;
2223
import com.oursky.authgear.PreAuthenticatedURLOptions;
2324
import com.oursky.authgear.Authgear;
@@ -68,10 +69,12 @@
6869
import com.tencent.mm.opensdk.openapi.WXAPIFactory;
6970

7071
import java.util.Date;
72+
import java.util.List;
7173

7274
@SuppressWarnings("ConstantConditions")
7375
public class MainViewModel extends AndroidViewModel implements AuthgearDelegate {
74-
private static final int ALLOWED = BiometricManager.Authenticators.BIOMETRIC_STRONG;
76+
private static final List<BiometricAuthenticator> ALLOWED_AUTHENTICATORS_ON_ENABLE = List.of(BiometricAuthenticator.BIOMETRIC_STRONG);
77+
private static final List<BiometricAuthenticator> ALLOWED_AUTHENTICATORS_ON_AUTHENTICATE = List.of(BiometricAuthenticator.BIOMETRIC_STRONG, BiometricAuthenticator.DEVICE_CREDENTIAL);
7578
private static final String TAG = MainViewModel.class.getSimpleName();
7679
private Authgear mAuthgear = null;
7780
private IWXAPI wechatAPI;
@@ -136,7 +139,7 @@ private void updateBiometricState() {
136139
if (Build.VERSION.SDK_INT >= 23) {
137140
mAuthgear.checkBiometricSupported(
138141
this.getApplication(),
139-
ALLOWED
142+
ALLOWED_AUTHENTICATORS_ON_ENABLE
140143
);
141144
supported = true;
142145
}
@@ -609,7 +612,8 @@ private BiometricOptions makeBiometricOptions(FragmentActivity activity) {
609612
"Biometric authentication",
610613
"Use biometric to authenticate",
611614
"Cancel",
612-
ALLOWED,
615+
ALLOWED_AUTHENTICATORS_ON_ENABLE,
616+
ALLOWED_AUTHENTICATORS_ON_AUTHENTICATE,
613617
true
614618
);
615619
}
@@ -634,7 +638,7 @@ public void enableBiometric(FragmentActivity activity) {
634638
mIsLoading.setValue(true);
635639

636640
try {
637-
mAuthgear.checkBiometricSupported(activity, ALLOWED);
641+
mAuthgear.checkBiometricSupported(activity, ALLOWED_AUTHENTICATORS_ON_ENABLE);
638642
} catch (Exception e) {
639643
mIsLoading.setValue(false);
640644
setError(e);

sdk/src/main/java/com/oursky/authgear/Authgear.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -640,8 +640,8 @@ constructor(
640640
*/
641641
@MainThread
642642
@RequiresApi(api = Build.VERSION_CODES.M)
643-
fun checkBiometricSupported(context: Context, allowedAuthenticators: Int) {
644-
core.checkBiometricSupported(context, allowedAuthenticators)
643+
fun checkBiometricSupported(context: Context, allowedAuthenticatorsOnEnable: List<BiometricAuthenticator>) {
644+
core.checkBiometricSupported(context, allowedAuthenticatorsOnEnable)
645645
}
646646

647647
/**

sdk/src/main/java/com/oursky/authgear/AuthgearCore.kt

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -886,13 +886,11 @@ internal class AuthgearCore(
886886
}
887887

888888
@RequiresApi(api = Build.VERSION_CODES.M)
889-
fun checkBiometricSupported(context: Context, allowed: Int) {
889+
fun checkBiometricSupported(context: Context, allowedAuthenticatorsOnEnable: List<BiometricAuthenticator>) {
890890
requireIsInitialized()
891891
requireMinimumBiometricAPILevel()
892892

893-
var allowed = allowed
894-
ensureAllowedIsValid(allowed)
895-
allowed = convertAllowed(allowed)
893+
val allowed = convertAllowed(allowedAuthenticatorsOnEnable)
896894
val result = BiometricManager.from(context).canAuthenticate(allowed)
897895
if (result != BiometricManager.BIOMETRIC_SUCCESS) {
898896
throw wrapException(BiometricCanAuthenticateException(result))
@@ -931,21 +929,22 @@ internal class AuthgearCore(
931929
val accessToken: String = this.accessToken
932930
?: throw UnauthenticatedUserException()
933931

934-
ensureAllowedIsValid(options.allowedAuthenticators)
935-
val allowed = convertAllowed(options.allowedAuthenticators)
932+
val allowedAuthenticatorsOnEnable = convertAllowed(options.allowedAuthenticatorsOnEnable)
933+
val allowedAuthenticatorsOnAuthenticate = convertAllowed(options.allowedAuthenticatorsOnAuthenticate)
934+
936935
val promptInfo = buildPromptInfo(
937936
options.title,
938937
options.subtitle,
939938
options.description,
940939
options.negativeButtonText,
941-
allowed
940+
allowedAuthenticatorsOnEnable
942941
)
943942

944943
val kid = UUID.randomUUID().toString()
945944
val alias = "com.authgear.keys.biometric.$kid"
946945
val spec = makeGenerateKeyPairSpec(
947946
alias,
948-
authenticatorTypesToKeyProperties(allowed),
947+
authenticatorTypesToKeyProperties(allowedAuthenticatorsOnAuthenticate),
949948
options.invalidatedByBiometricEnrollment)
950949
val challenge = this.oauthRepo.oauthChallenge("biometric_request").token
951950
val keyPair = createKeyPair(spec)
@@ -1019,14 +1018,13 @@ internal class AuthgearCore(
10191018
requireIsInitialized()
10201019
requireMinimumBiometricAPILevel()
10211020

1022-
ensureAllowedIsValid(options.allowedAuthenticators)
1023-
val allowed = convertAllowed(options.allowedAuthenticators)
1021+
val allowedAuthenticatorsOnAuthenticate = convertAllowed(options.allowedAuthenticatorsOnAuthenticate)
10241022
val promptInfo = buildPromptInfo(
10251023
options.title,
10261024
options.subtitle,
10271025
options.description,
10281026
options.negativeButtonText,
1029-
allowed
1027+
allowedAuthenticatorsOnAuthenticate
10301028
)
10311029

10321030
val challenge = this.oauthRepo.oauthChallenge("biometric_request").token

sdk/src/main/java/com/oursky/authgear/Biometric.kt

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,6 @@ import androidx.biometric.BiometricPrompt
99
import androidx.biometric.BiometricPrompt.PromptInfo
1010
import java.security.*
1111

12-
internal const val BIOMETRIC_ONLY = BiometricManager.Authenticators.BIOMETRIC_STRONG
13-
internal const val BIOMETRIC_OR_DEVICE_CREDENTIAL =
14-
BiometricManager.Authenticators.BIOMETRIC_STRONG or BiometricManager.Authenticators.DEVICE_CREDENTIAL
15-
1612
@RequiresApi(api = Build.VERSION_CODES.M)
1713
internal fun makeGenerateKeyPairSpec(alias: String, allowed: Int, invalidatedByBiometricEnrollment: Boolean): KeyGenParameterSpec {
1814
val builder = KeyGenParameterSpec.Builder(
@@ -107,17 +103,25 @@ internal fun authenticatorTypesToKeyProperties(allowed: Int): Int {
107103
return out
108104
}
109105

110-
internal fun ensureAllowedIsValid(allowed: Int) {
111-
if (allowed != BIOMETRIC_ONLY && allowed != BIOMETRIC_OR_DEVICE_CREDENTIAL) {
112-
throw IllegalArgumentException("AuthenticateTypes must be BIOMETRIC_STRONG or BIOMETRIC_STRONG | DEVICE_CREDENTIAL")
106+
internal fun convertAllowed(allowedAuthenticators: List<BiometricAuthenticator>): Int {
107+
var flags = 0
108+
for (allowed in allowedAuthenticators) {
109+
flags = flags or allowed.raw
113110
}
114-
}
115111

116-
internal fun convertAllowed(allowed: Int): Int {
117-
if (Build.VERSION.SDK_INT < 30 && (allowed and BiometricManager.Authenticators.DEVICE_CREDENTIAL) != 0) {
118-
return allowed xor BiometricManager.Authenticators.DEVICE_CREDENTIAL
112+
// The official documentation says that on 29 and below,
113+
// DEVICE_CREDENTIAL and BIOMETRIC_STRONG | DEVICE_CREDENTIAL
114+
// are unsupported.
115+
// https://developer.android.com/identity/sign-in/biometric-auth#:~:text=The%20following%20combinations%20of%20authenticator%20types%20aren%27t%20supported%20on%20Android%2010%20(API%20level%2029)%20and%20lower
116+
if (Build.VERSION.SDK_INT < 30) {
117+
if (flags == BiometricManager.Authenticators.DEVICE_CREDENTIAL || flags == (BiometricManager.Authenticators.DEVICE_CREDENTIAL or BiometricManager.Authenticators.BIOMETRIC_STRONG)) {
118+
// Fallback to BiometricManager.Authenticators.BIOMETRIC_STRONG
119+
// which is a strong default.
120+
flags = BiometricManager.Authenticators.BIOMETRIC_STRONG
121+
}
119122
}
120-
return allowed
123+
124+
return flags
121125
}
122126

123127
internal fun canAuthenticateResultToString(result: Int): String {
@@ -160,7 +164,6 @@ internal fun buildPromptInfo(
160164
negativeButtonText: String,
161165
allowed: Int
162166
): PromptInfo {
163-
ensureAllowedIsValid(allowed)
164167
val builder = PromptInfo.Builder()
165168
.setTitle(title)
166169
.setSubtitle(subtitle)
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
package com.oursky.authgear
2+
3+
import androidx.biometric.BiometricManager
4+
5+
enum class BiometricAuthenticator(val raw: Int) {
6+
BIOMETRIC_STRONG(BiometricManager.Authenticators.BIOMETRIC_STRONG),
7+
DEVICE_CREDENTIAL(BiometricManager.Authenticators.DEVICE_CREDENTIAL)
8+
}

sdk/src/main/java/com/oursky/authgear/BiometricOptions.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ data class BiometricOptions constructor(
88
var subtitle: String,
99
var description: String,
1010
var negativeButtonText: String,
11-
var allowedAuthenticators: Int,
11+
var allowedAuthenticatorsOnEnable: List<BiometricAuthenticator>,
12+
var allowedAuthenticatorsOnAuthenticate: List<BiometricAuthenticator>,
1213
var invalidatedByBiometricEnrollment: Boolean
1314
)

0 commit comments

Comments
 (0)