Fingerprint API Failing in Standalone App

I’m using the Expo Fingerprint API, and the iOS prompt pops up and authenticates perfectly fine when developing. However once I publish and try it in the iOS standalone app, I get error code ‘unknown’ and the prompt is not displayed.

This was working fine in my previous releases.

Attempts to solve issue so far:

  • rolled back to previous version of my code where the fingerprint scanning was working in standalone app
  • upgraded Expo and React Native using the guide on Exposition for 20.0.0 SDK Release

Another weird thing is if I delete the standalone app and reinstall, the fingerprint scan works fine.

Some more info I found in the Expo code:

private static String convertErrorCode(int code) {
    switch (code) {
      case FingerprintManager.FINGERPRINT_ERROR_CANCELED:
        return "user_cancel";
      case FingerprintManager.FINGERPRINT_ERROR_HW_UNAVAILABLE:
        return "not_available";
      case FingerprintManager.FINGERPRINT_ERROR_LOCKOUT:
        return "lockout";
      case FingerprintManager.FINGERPRINT_ERROR_NO_SPACE:
        return "no_space";
      case FingerprintManager.FINGERPRINT_ERROR_TIMEOUT:
        return "timeout";
      case FingerprintManager.FINGERPRINT_ERROR_UNABLE_TO_PROCESS:
        return "unable_to_process";
      default:
        return "unknown";
    }
  }

Any help would be appreciated.

Hi, is it possible to share any code where you use this?

Hi, here is the code we are using:

async _scanFinger() {
        if (Platform.OS === 'ios') {
            let result = await Expo.Fingerprint.authenticateAsync(I18n.t('fingerprintPromptTxt'));
            if (result.success) {
                await this._redirectOnAuthenticated();
                return;
            } else {
                this.setState({fingerprintFailedMsg: result.error, showFingerBtn: true,})
            }
        } else {
            let result = await Expo.Fingerprint.authenticateAsync();
            if (result.success) {
                await this._redirectOnAuthenticated();
                return;
            }

            this.setState({
                fingerprintAndroidFailed: true,
                showFingerBtn: true,
                fingerprintFailedMsg: I18n.t('fingerprintFailedMsg')
            })
        }
    }

    
    async componentDidMount() {
        const fingerprint = await AsyncStorage.getItem('Fingerprint');
        if (fingerprint === 'true') {
            await this._scanFinger();
        }
    }

    async componentWillMount() {
        let fingerprintSupport = await checkFingerprintSupport();
        this.setState({ fingerprintSupport });
    }

Interesting. If this is failing on iOS, I suspect https://github.com/expo/expo/blob/master/ios/Exponent/Versioned/Modules/Api/EXFingerprint.m#L57 is the more relevant code to look at. @ben have you seen this switch statement fallthrough on iOS before?

Also, are you calling the hardwareAvailable and isEnrolledAsync methods anywhere? It seems like you’re setting state that says whether the phone can do fingerprint auth, but aren’t actually doing a different auth method if it doesn’t.

Yes I check when they set it up (which is another screen) I use both hardwareAvailable and isEnrolledAsync methods to check before they enable it. Then I set the fingerprint in async storage to be ‘true’, which is the check you see in my code snippet.

@dikaiosune Still getting ‘unknown’ error. Not sure if this is relevant but I took a look at this and some error codes are deprecated now: Apple Developer Documentation

Would this be relevant to this issue at all?

I’ve opened an issue here about this: https://github.com/expo/expo/issues/663

I thought I managed to get around this issue but it happened again. Here’s what I did:

After upgrading Expo to 21.0.0 I built another binary and deployed it to TestFlight.
Fingerprint was working once the update was downloaded onto any phones affected.
However when I hit Publish on XDE it broke the Fingerprint again.

I do remember updating XDE just before the first time Fingerprint broke when I published.

Not sure if XDE could be breaking it?