Skip to content

Commit

Permalink
Added back cancelButtonText option.
Browse files Browse the repository at this point in the history
Added API version detection to the allowDeviceCredentials feature. This feature is only able to be combined with BIOMETRIC_STRONG (Class 3) devices on API versions greater or equal to API 30. Anything prior to API 30, does not support device credentials combined with BIOMETRIC_STRONG (Class 3) crypto-based authentication.
  • Loading branch information
tyler-cook-self committed May 18, 2022
1 parent 92613c8 commit 7d03fc2
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 12 deletions.
11 changes: 9 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,11 @@ if (biometryType === ReactNativeBiometrics.Biometrics) {

Detects what type of biometric sensor is available. Returns a `Promise` that resolves to an object with details about biometrics availability

__Options Object__
| Parameter | Type | Description | iOS | Android |
| --- | --- | --- | --- | --- |
| allowDeviceCredentials | boolean | Boolean that provides the user the option to bypass using biometric information to retrieve the private key. Note: This feature is not supported in Android versions prior to API 30. |||

__Result Object__

| Property | Type | Description |
Expand Down Expand Up @@ -222,7 +227,8 @@ __Options Object__
| --- | --- | --- | --- | --- |
| promptMessage | string | Message that will be displayed in the fingerprint or face id prompt |||
| payload | string | String of data to be signed by the RSA signature |||
| allowDeviceCredentials | boolean | Boolean that provides the user the option to bypass using biometric information to retrieve the private key. |||
| cancelButtonText | string | Text to be displayed for the cancel button on biometric prompts, defaults to `Cancel` |||
| allowDeviceCredentials | boolean | Boolean that provides the user the option to bypass using biometric information to retrieve the private key. Note: This feature is not supported in Android versions prior to API 30. |||

__Result Object__

Expand Down Expand Up @@ -266,7 +272,8 @@ __Options Object__
| --- | --- | --- | --- | --- |
| promptMessage | string | Message that will be displayed in the biometrics prompt |||
| fallbackPromptMessage | string | Message that will be shown when FaceID or TouchID has failed and a passcode has been set on the device. |||
| allowDeviceCredentials | boolean | Boolean that provides the user the option to bypass using biometric information to retrieve the private key. |||
| cancelButtonText | string | Text to be displayed for the cancel button on biometric prompts, defaults to `Cancel` |||
| allowDeviceCredentials | boolean | Boolean that provides the user the option to bypass using biometric information to retrieve the private key. Note: This feature is not supported in Android versions prior to API 30. |||

__Result Object__

Expand Down
26 changes: 16 additions & 10 deletions android/src/main/java/com/rnbiometrics/ReactNativeBiometrics.java
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,7 @@ public void run() {
try {
String promptMessage = params.getString("promptMessage");
String payload = params.getString("payload");
String cancelButtonText = params.getString("cancelButtonText");
boolean allowDeviceCredentials = params.getBoolean("allowDeviceCredentials");

Signature signature = Signature.getInstance("SHA256withRSA");
Expand All @@ -170,7 +171,7 @@ public void run() {
Executor executor = Executors.newSingleThreadExecutor();
BiometricPrompt biometricPrompt = new BiometricPrompt(fragmentActivity, executor, authCallback);

biometricPrompt.authenticate(getPromptInfo(promptMessage, allowDeviceCredentials), cryptoObject);
biometricPrompt.authenticate(getPromptInfo(promptMessage, cancelButtonText, allowDeviceCredentials), cryptoObject);
} catch (Exception e) {
promise.reject("Error signing payload: " + e.getMessage(), "Error generating signature: " + e.getMessage());
}
Expand All @@ -181,25 +182,29 @@ public void run() {
}
}

private PromptInfo getPromptInfo(String promptMessage, boolean allowDeviceCredentials) {
PromptInfo.Builder builder = new PromptInfo.Builder()
.setAllowedAuthenticators(getSupportedAuthenticators(allowDeviceCredentials))
.setTitle(promptMessage);
private PromptInfo getPromptInfo(String promptMessage, String cancelButtonText, boolean allowDeviceCredentials) {
PromptInfo.Builder builder = new PromptInfo.Builder().setTitle(promptMessage);

if (allowDeviceCredentials == false) {
builder.setNegativeButtonText("Cancel");
builder.setAllowedAuthenticators(getAllowedAuthenticators(allowDeviceCredentials));

if (allowDeviceCredentials == false || isCurrentSDK29OrEarlier()) {
builder.setNegativeButtonText(cancelButtonText);
}

return builder.build();
}

private int getSupportedAuthenticators(boolean allowDeviceCredentials) {
if (allowDeviceCredentials) {
private int getAllowedAuthenticators(boolean allowDeviceCredentials) {
if (allowDeviceCredentials && !isCurrentSDK29OrEarlier()) {
return BiometricManager.Authenticators.BIOMETRIC_STRONG | BiometricManager.Authenticators.DEVICE_CREDENTIAL;
}
return BiometricManager.Authenticators.BIOMETRIC_STRONG;
}

private boolean isCurrentSDK29OrEarlier() {
return Build.VERSION.SDK_INT <= Build.VERSION_CODES.Q;
}

@ReactMethod
public void simplePrompt(final ReadableMap params, final Promise promise) {
if (isCurrentSDKMarshmallowOrLater()) {
Expand All @@ -209,14 +214,15 @@ public void simplePrompt(final ReadableMap params, final Promise promise) {
public void run() {
try {
String promptMessage = params.getString("promptMessage");
String cancelButtonText = params.getString("cancelButtonText");
boolean allowDeviceCredentials = params.getBoolean("allowDeviceCredentials");

AuthenticationCallback authCallback = new SimplePromptCallback(promise);
FragmentActivity fragmentActivity = (FragmentActivity) getCurrentActivity();
Executor executor = Executors.newSingleThreadExecutor();
BiometricPrompt biometricPrompt = new BiometricPrompt(fragmentActivity, executor, authCallback);

biometricPrompt.authenticate(getPromptInfo(promptMessage, allowDeviceCredentials));
biometricPrompt.authenticate(getPromptInfo(promptMessage, cancelButtonText, allowDeviceCredentials));
} catch (Exception e) {
promise.reject("Error displaying local biometric prompt: " + e.getMessage(), "Error displaying local biometric prompt: " + e.getMessage());
}
Expand Down
2 changes: 2 additions & 0 deletions index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ module ReactNativeBiometrics {
* @returns {Promise<Object>} Promise that resolves to an object cryptographic signature details
*/
export function createSignature(createSignatureOptions: CreateSignatureOptions): Promise<CreateSignatureResult> {
createSignatureOptions.cancelButtonText = createSignatureOptions.cancelButtonText ?? 'Cancel';
createSignatureOptions.allowDeviceCredentials = createSignatureOptions.allowDeviceCredentials ?? false

return bridge.createSignature(createSignatureOptions);
Expand All @@ -131,6 +132,7 @@ module ReactNativeBiometrics {
* @returns {Promise<Object>} Promise that resolves an object with details about the biometrics result
*/
export function simplePrompt(simplePromptOptions: SimplePromptOptions): Promise<SimplePromptResult> {
simplePromptOptions.cancelButtonText = simplePromptOptions.cancelButtonText ?? 'Cancel';
simplePromptOptions.fallbackPromptMessage = simplePromptOptions.fallbackPromptMessage ?? 'Use Passcode';
simplePromptOptions.allowDeviceCredentials = simplePromptOptions.allowDeviceCredentials ?? false

Expand Down

0 comments on commit 7d03fc2

Please sign in to comment.