Skip to main content

Implementing Local Authentication

1. Using Local Authentication

Property Description Values
expo-local-authentication Module for local authentication expo-local-authentication

Example: Check if local authentication is available

import * as LocalAuthentication from 'expo-local-authentication';

const hasHardware = await LocalAuthentication.hasHardwareAsync();
console.log("Has hardware: ", hasHardware);

Example: Authenticate with biometrics

import * as LocalAuthentication from 'expo-local-authentication';

const authResult = await LocalAuthentication.authenticateAsync({
  promptMessage: 'Authenticate to proceed',
  cancelLabel: 'Cancel',
});
console.log("Authentication result: ", authResult);
Note: On iOS, the device must have Face ID or Touch ID enabled for local authentication to work.

2. Checking Biometric Support

Feature Description Support
Face ID Biometric authentication using facial recognition iOS / Android
Fingerprint Biometric authentication using fingerprint scanning iOS / Android
Iris Scan Biometric authentication using iris recognition iOS / Android
Touch ID Biometric authentication using fingerprint scanning on iOS iOS

Example: Check Biometric Support

import * as LocalAuthentication from 'expo-local-authentication';

const checkBiometricSupport = async () => {
  const supported = await LocalAuthentication.hasHardwareAsync();
  console.log("Biometric hardware supported:", supported);

  const types = await LocalAuthentication.supportedAuthenticationTypesAsync();
  console.log("Supported authentication types:", types);
};

checkBiometricSupport();
Note: On Android, biometric support depends on the device's security settings and installed biometric sensors.

3. Authenticating User

Property Description Example
authToken Token used for authentication with the server "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
userCredentials Credentials provided by the user (e.g., username/password) { username: "john_doe", password: "secure123" }
refreshToken Token used to obtain a new auth token when it expires "refresh_token_abc123"

Example: Basic Authentication Flow

import * as ExpoAuth from 'expo-auth';

const login = async () => {
  const credentials = {
    username: 'john_doe',
    password: 'secure123'
  };

  try {
    const response = await ExpoAuth.authenticate(credentials);
    console.log('Authentication successful:', response.authToken);
  } catch (error) {
    console.error('Authentication failed:', error.message);
  }
};
Note: Ensure that sensitive credentials are never stored in plain text. Use secure storage methods like SecureStore for sensitive data.
Warning: Do not send passwords in plain text over the network. Always use HTTPS and secure authentication methods.

4. Checking Enrolled Biometrics

Property Description Values Notes
isEnrolledAsync() Checks if the device has enrolled biometrics Promise<boolean> Returns true if biometrics are enrolled, otherwise false
isEnrolledAsync(type) Checks if the device has enrolled specific biometrics Promise<boolean> Supports Face, Fingerprint, and Biometric

Example: Checking Enrolled Biometrics

import * as LocalAuthentication from &#x27;expo-local-authentication&#x27;;

async function checkBiometrics() {
  const isEnrolled = await LocalAuthentication.isEnrolledAsync();
  console.log("Biometrics enrolled: ", isEnrolled);
}

checkBiometrics();

Example: Checking Specific Biometric Type

import * as LocalAuthentication from &#x27;expo-local-authentication&#x27;;

async function checkSpecificBiometrics() {
  const isFaceEnrolled = await LocalAuthentication.isEnrolledAsync("Face");
  const isFingerprintEnrolled = await LocalAuthentication.isEnrolledAsync("Fingerprint");
  console.log("Face enrolled: ", isFaceEnrolled);
  console.log("Fingerprint enrolled: ", isFingerprintEnrolled);
}

checkSpecificBiometrics();
Note: On Android, isEnrolledAsync may return false even if biometrics are set up, due to platform limitations.
Warning: Always handle the case where biometrics are not enrolled, as users may have disabled them or not set them up.

5. Setting Authentication Options

Option Values Description
authType "local" | "oauth" Specifies the authentication method to use. "local" for username/password, "oauth" for third-party providers.
requireEmailVerification true | false Enforces email verification before login. Defaults to false.
passwordPolicy string Defines password strength requirements (e.g., "minLength:8;requireNumbers:true;").
maxLoginAttempts number Maximum login attempts before account lockout. Defaults to 5.
lockoutDuration number Duration (in minutes) for which the account is locked after max attempts. Defaults to 30.

Example: Configure Authentication Options

const authConfig = {
  authType: "local",
  requireEmailVerification: true,
  passwordPolicy: "minLength:8;requireNumbers:true;",
  maxLoginAttempts: 5,
  lockoutDuration: 30
};
Note: These options are typically set in the backend configuration or via Expo's authentication service settings.

6. Handling Authentication Result

Example: Handle Authentication Result

import * as AuthSession from 'expo-auth-session';

const handleAuthResult = async (result) => {
  if (result?.type === 'success') {
    const { params } = result;
    const accessToken = params.access_token;
    const refreshToken = params.refresh_token;

    // Store tokens securely
    await SecureStore.setItemAsync('access_token', accessToken);
    await SecureStore.setItemAsync('refresh_token', refreshToken);

    // Redirect to app screen
    navigation.replace('Home');
  } else if (result?.type === 'dismissed') {
    // User dismissed the auth session
    console.log('Authentication was dismissed');
  }
};

export default function AuthScreen() {
  const [request, response, promptAsync] = AuthSession.useAuthRequest(
    {
      clientId: 'your-client-id',
      redirectUri: AuthSession.makeRedirectUri(),
      scopes: ['read', 'write'],
    },
    AuthSession.authTypes.PKCE
  );

  return (
    <View style={styles.container}>
      <Button
        title="Login with OAuth"
        onPress={() => promptAsync()}
      />
    </View>
  );
}
Property Description Values
result.type Indicates the outcome of the authentication flow 'success', 'dismissed', 'error'
result.params Parameters returned from the OAuth provider Object containing tokens and metadata
result.error Error object if authentication failed Standard error object with message and code
Note: Always validate and sanitize the tokens before storing them.
Warning: Never log or expose raw tokens in production environments.

7. Using Face ID (iOS)

Property Description Values
requireFaceID Indicates whether Face ID is required for authentication true or false
fallback Fallback authentication method if Face ID fails FaceID, TouchID, or None

Example: Enabling Face ID Authentication

import * as LocalAuthentication from &#x27;expo-local-authentication&#x27;;

const authenticateWithFaceID = async () => {
  const hasHardware = await LocalAuthentication.hasHardwareAsync();
  if (!hasHardware) {
    console.log("Face ID not supported");
    return;
  }

  const authResult = await LocalAuthentication.authenticateAsync({
    promptMessage: "Authenticate with Face ID",
    requireFaceID: true,
    fallback: "TouchID"
  });

  if (authResult.success) {
    console.log("Authentication successful");
  } else {
    console.log("Authentication failed");
  }
};
Note: Face ID authentication is only available on iOS devices with Face ID hardware.
Warning: Ensure that your app has the appropriate permissions in app.json or app.config.js to use Face ID.
Property Default Value Description
requireFaceID false Set to true to enforce Face ID usage
fallback None Defines fallback authentication method if Face ID is not available

8. Using Touch ID (iOS)

Property Description Values
touchID Enables or disables Touch ID authentication true or false
touchIDPrompt Custom message displayed to the user during Touch ID authentication string

Example: Enabling Touch ID Authentication

import * as LocalAuthentication from &#x27;expo-local-authentication&#x27;;

const authenticateWithTouchID = async () => {
  const hasHardware = await LocalAuthentication.hasHardwareAsync();
  if (hasHardware) {
    const authResult = await LocalAuthentication.authenticateAsync({
      promptMessage: &#x27;Authenticate with your fingerprint&#x27;,
      fallbackEnabled: true
    });
    
    if (authResult.success) {
      console.log(&#x27;Authentication successful&#x27;);
    } else {
      console.log(&#x27;Authentication failed&#x27;);
    }
  } else {
    console.log(&#x27;Touch ID not supported&#x27;);
  }
};
Note: Touch ID authentication requires the device to have a compatible sensor and the user must have enrolled fingerprints in the system.
Warning: Touch ID authentication is only available on iOS devices. For Android, consider using Face Recognition or Fingerprint scanning via expo-local-authentication.

Supported Platforms

  • iOS 11+
  • Requires device with Touch ID sensor

9. Using Fingerprint (Android)

Property Description Values
fingerprint Enables fingerprint authentication true or false
fallback Allows fallback to PIN or password true or false

Example: Enabling Fingerprint Authentication

import * as LocalAuthentication from 'expo-local-authentication';

const authenticateWithFingerprint = async () => {
  const { success } = await LocalAuthentication.authenticateAsync({
    promptMessage: 'Authenticate with fingerprint',
    fallback: true,
  });

  if (success) {
    console.log('Authentication successful');
  } else {
    console.log('Authentication failed');
  }
};
Note: Fingerprint authentication is only available on Android devices with fingerprint sensors.
Warning: Ensure proper error handling for cases where fingerprint authentication is not supported or fails.

10. Setting Fallback to Passcode

When implementing local authentication in Expo, you can configure a fallback to passcode authentication if biometric authentication fails or is not available.

Property Description Default
fallback Specifies the fallback method when biometric authentication fails. Options include 'passcode', 'devicePasscode', or false. false

Example: Configure fallback to passcode

import * as LocalAuthentication from &#x27;expo-local-authentication&#x27;;

const authenticateWithFallback = async () => {
  const hasHardware = await LocalAuthentication.hasHardwareAsync();
  const isEnrolled = await LocalAuthentication.isEnrolledAsync();

  if (hasHardware && isEnrolled) {
    const authResult = await LocalAuthentication.authenticateAsync({
      fallback: &#x27;passcode&#x27;
    });
    if (authResult.success) {
      console.log("Authentication successful");
    } else {
      console.log("Authentication failed");
    }
  } else {
    console.log("No biometric hardware or enrollment");
  }
};
Note: The fallback option is only supported on iOS and Android devices that have a passcode set up.
Warning: If the user has not set up a passcode, setting fallback to 'passcode' will result in a failure.

11. Getting Biometric Types

Property Description Values
biometryType Indicates the type of biometric authentication available FACE, FINGERPRINT, IRIS, UNKNOWN

Example: Check Biometric Type

import * as LocalAuthentication from &#x27;expo-local-authentication&#x27;;

async function getBiometricType() {
  const { biometryType } = await LocalAuthentication.getBiometricTypesAsync();
  console.log("Biometric type:", biometryType);
}

getBiometricType();

12. Handling Authentication Cancellation

Example: Canceling Authentication Flow

import * as Authentication from 'expo-auth-session';

const handleAuthCancel = () => {
  // Reset authentication state
  setAuthState('idle');
  
  // Clear any temporary tokens or data
  clearAuthTokens();
  
  // Notify user of cancellation
  alert('Authentication was canceled');
};

// Example usage in a cancellation handler
const onCancel = () => {
  handleAuthCancel();
  // Optionally navigate back to previous screen
  navigation.goBack();
};
Property Description Usage
onCancel Callback function triggered when authentication is canceled by user Pass to authentication providers to handle cancellation
authState Current state of authentication flow (idle, pending, success, error) Used to manage UI state during cancellation
Note: When handling cancellation, ensure all temporary authentication data is cleared to prevent security issues.
Warning: Do not reuse canceled authentication tokens or session data as they may be invalid.

Best Practices for Cancellation Handling

  • Reset authentication state to idle when cancellation occurs
  • Clear temporary tokens and session data immediately
  • Provide user feedback when authentication is canceled
  • Navigate back to previous screen or reset flow as needed

Was this article helpful?