React Native Biometrische Authentifizierung: Face ID und Fingerabdruck
AI generated
RN
native
React Native · iOS · Android · Security
React Native Biometrische Authentifizierung
Face ID und Fingerabdruck sicher einbinden

Biometrische Authentifizierung ersetzt die lästige PIN-Eingabe durch einen Blick oder eine Berührung, verlangt dafür aber ein sauberes Verständnis des zugrunde liegenden Sicherheitsmodells. Face ID unter iOS und Fingerabdruck-Prompts unter Android entsperren niemals biometrische Rohdaten, sondern lokal einen kryptografischen Schlüssel. Dieser Artikel zeigt, wie biometrische Authentifizierung in React Native mit expo-local-authentication und react-native-biometrics sauber implementiert, mit echter Server-Verifikation kombiniert und mit sinnvollen Fallbacks abgesichert wird.

17 Min. Lesezeit Face ID · BiometricPrompt · Challenge-Response iOS · Android · Expo

1. Warum biometrische Authentifizierung in Apps sinnvoll ist

Biometrische Authentifizierung löst ein sehr konkretes UX-Problem: Nutzer geben eine App-PIN oder ein Passwort ungern mehrfach am Tag ein, besonders bei Apps, die häufig kurz geöffnet und wieder geschlossen werden. Ein Blick für Face ID oder eine Berührung des Fingerabdrucksensors dauert eine Bruchteilsekunde und fühlt sich für die meisten Nutzer natürlicher an als das Tippen eines Codes. Genau deshalb ist biometrische Authentifizierung heute Standard in Banking-Apps, Passwort-Managern und jeder Anwendung, die schnellen, aber trotzdem geschützten Zugriff auf sensible Inhalte bieten will.

Wichtig ist dabei, das Sicherheitsmodell nicht misszuverstehen. Biometrische Authentifizierung überträgt niemals Fingerabdruck- oder Gesichtsdaten irgendwohin, weder an einen Server noch an die App selbst. Stattdessen prüft das Betriebssystem lokal auf dem Gerät, ob die vorgehaltene Biometrie zur hinterlegten Referenz passt, und entsperrt im Erfolgsfall einen kryptografischen Schlüssel, der in einer gesicherten Hardware-Komponente liegt. Die App bekommt niemals die Rohdaten des Gesichts oder Fingerabdrucks zu sehen, sondern lediglich das Ergebnis: erfolgreich oder fehlgeschlagen, beziehungsweise eine mit dem entsperrten Schlüssel erzeugte Signatur.

Diese Trennung ist der Grund, warum biometrische Authentifizierung als Sicherheitsmechanismus überhaupt vertrauenswürdig ist. Eine App, die Face ID oder Fingerabdruck-Prüfung einbindet, muss selbst keine biometrischen Daten verarbeiten, speichern oder gar an ein Backend senden, was Datenschutzanforderungen erheblich vereinfacht. Gleichzeitig bedeutet das aber auch, dass biometrische Authentifizierung allein noch keine Aussage über die Identität gegenüber einem Server trifft, ein Punkt, der in Abschnitt 7 genauer behandelt wird.

2. Bibliotheken im Überblick

Für biometrische Authentifizierung in React Native haben sich zwei Bibliotheken etabliert, die unterschiedliche Anforderungen abdecken. expo-local-authentication bietet eine schlanke API für die reine Geräte-Authentifizierung: Sie prüft, ob Face ID oder Fingerabdruck verfügbar sind, zeigt den systemeigenen Prompt an und liefert ein einfaches Erfolgs- oder Fehlschlags-Ergebnis zurück. Für Anwendungsfälle wie das Sperren eines App-Bereichs oder das erneute Bestätigen vor einer sensiblen Aktion innerhalb der App reicht das vollständig aus.

react-native-biometrics geht einen Schritt weiter und kann zusätzlich asymmetrische Schlüsselpaare erzeugen, deren privater Schlüssel die gesicherte Hardware nie verlässt. Damit lassen sich Challenge-Response-Signaturen erzeugen, die ein Server tatsächlich kryptografisch verifizieren kann. Diese Fähigkeit ist entscheidend, sobald ein Backend der biometrischen Bestätigung eines Nutzers wirklich vertrauen soll, etwa beim Login ohne Passwort oder bei der Freigabe einer Transaktion.

Die Faustregel: Wer biometrische Authentifizierung nur als lokale Zugriffssperre innerhalb der App braucht, kommt mit expo-local-authentication aus und spart sich zusätzliche Komplexität. Wer hingegen eine serverseitige Instanz überzeugen muss, dass tatsächlich der berechtigte Nutzer und nicht irgendjemand am entsperrten Gerät gehandelt hat, braucht die Public-Key-Fähigkeiten von react-native-biometrics oder ein eigenes natives Modul mit vergleichbarer Funktionalität.


// LocalAuthGate.js — pure device-level check with expo-local-authentication
import * as LocalAuthentication from 'expo-local-authentication';

/**
 * Runs a local biometric authentication prompt and returns
 * whether the device owner successfully confirmed their identity.
 * This does NOT prove anything to a remote server on its own.
 */
export async function requestBiometricUnlock() {
  const hasHardware = await LocalAuthentication.hasHardwareAsync();
  const isEnrolled = await LocalAuthentication.isEnrolledAsync();

  if (!hasHardware || !isEnrolled) {
    // No biometric sensor, or none configured on this device
    return { success: false, reason: 'unavailable' };
  }

  const result = await LocalAuthentication.authenticateAsync({
    promptMessage: 'Mit Face ID oder Fingerabdruck entsperren',
    fallbackLabel: 'Geräte-Code verwenden',
    cancelLabel: 'Abbrechen',
    disableDeviceFallback: false, // always allow passcode fallback
  });

  return result.success
    ? { success: true }
    : { success: false, reason: result.error };
}

3. Face ID unter iOS einrichten

Unter iOS läuft biometrische Authentifizierung über das LocalAuthentication-Framework von Apple, das sowohl Face ID als auch den älteren Touch-ID-Sensor über dieselbe API abstrahiert. Bevor überhaupt ein Prompt angezeigt werden kann, muss die App das Feld NSFaceIDUsageDescription in der Info.plist hinterlegen, einen Erklärungstext, der dem Nutzer zeigt, wofür die App Face ID nutzen möchte. Fehlt dieser Eintrag, stürzt die App beim ersten Versuch, Face ID zu verwenden, kommentarlos ab, ein Fehler, der in der Entwicklung leicht übersehen wird, weil der Touch-ID-Pfad auf älteren Testgeräten diesen Hinweis gar nicht verlangt.

Der eigentliche Ablauf beginnt mit LAContext.canEvaluatePolicy(), das prüft, ob die gewählte Richtlinie überhaupt anwendbar ist, bevor der eigentliche Prompt gestartet wird. Diese Prüfung deckt zwei unterschiedliche Fälle ab: Zum einen, ob passende Hardware vorhanden ist, zum anderen, ob der Nutzer überhaupt eine Biometrie eingerichtet hat. Ein Gerät mit funktionierendem Face-ID-Sensor, auf dem aber kein Gesicht hinterlegt wurde, liefert hier bewusst ein negatives Ergebnis, damit die App rechtzeitig auf eine Alternative wie den Geräte-Passcode ausweichen kann.

Erst wenn canEvaluatePolicy() erfolgreich war, ruft man evaluatePolicy() auf, das den eigentlichen Face-ID- oder Touch-ID-Prompt anzeigt und asynchron das Ergebnis liefert. In React Native übernehmen sowohl expo-local-authentication als auch react-native-biometrics diese beiden Schritte intern, sodass man LAContext in der Praxis selten direkt in Swift anfassen muss, außer bei einem eigenen nativen Modul oder beim Debuggen eines Problems, das auf JavaScript-Ebene nicht sichtbar ist.


// BiometricAuthBridge.swift — minimal LAContext usage for Face ID / Touch ID
import LocalAuthentication

func evaluateBiometricPolicy(completion: @escaping (Bool, String?) -> Void) {
    let context = LAContext()
    var error: NSError?

    // Step 1: check hardware availability and enrollment BEFORE prompting
    let policy = LAPolicy.deviceOwnerAuthenticationWithBiometrics
    guard context.canEvaluatePolicy(policy, error: &error) else {
        completion(false, error?.localizedDescription ?? "biometry_unavailable")
        return
    }

    // Step 2: show the actual Face ID / Touch ID prompt
    let reason = "Mit Face ID oder Touch ID authentifizieren"
    context.evaluatePolicy(policy, localizedReason: reason) { success, evalError in
        DispatchQueue.main.async {
            completion(success, evalError?.localizedDescription)
        }
    }
}

Im Expo-Managed-Workflow lässt sich NSFaceIDUsageDescription nicht direkt in einer eigenen Info.plist pflegen, sondern wird über app.json und ein Config Plugin gesetzt. Beim nächsten eas build landet der Eintrag automatisch in den generierten nativen Projektdateien, zusammen mit den nötigen Android-Permissions, ohne dass native Projektdateien von Hand angefasst werden müssen.


{
  "expo": {
    "name": "mironsoft-demo",
    "slug": "mironsoft-demo",
    "plugins": [
      [
        "expo-local-authentication",
        {
          "faceIDPermission": "Erlaube $(PRODUCT_NAME), Face ID fuer die biometrische Authentifizierung zu nutzen."
        }
      ]
    ],
    "ios": {
      "infoPlist": {
        "NSFaceIDUsageDescription": "Diese App nutzt Face ID, um dein Konto ohne Passworteingabe sicher zu entsperren."
      }
    },
    "android": {
      "permissions": ["USE_BIOMETRIC", "USE_FINGERPRINT"]
    }
  }
}

4. Fingerabdruck und BiometricPrompt unter Android

Unter Android ist die moderne API für biometrische Authentifizierung die BiometricPrompt-Klasse, die Fingerabdruck, Gesichtserkennung und Iris-Scanner je nach Gerät einheitlich behandelt. Voraussetzung ist der Eintrag USE_BIOMETRIC als Permission in der AndroidManifest.xml, eine sogenannte normale Permission, die zur Installationszeit automatisch gewährt wird und keinen expliziten Laufzeit-Dialog erfordert. Damit unterscheidet sich der Einstieg deutlich einfacher als bei gefährlichen Permissions wie Kamera oder Standort.

Vor dem eigentlichen Prompt sollte immer BiometricManager.canAuthenticate() aufgerufen werden, das analog zu canEvaluatePolicy() unter iOS prüft, ob passende Hardware vorhanden und mindestens eine Biometrie eingerichtet ist. Der Rückgabewert unterscheidet mehrere Fehlerzustände fein granular: keine Hardware, Hardware temporär nicht verfügbar, oder Hardware vorhanden aber keine Biometrie eingerichtet. Diese Unterscheidung erlaubt es, dem Nutzer eine passende Fehlermeldung zu zeigen, statt pauschal "Fingerabdruck nicht verfügbar" anzuzeigen.

Wichtig ist der Unterschied zur älteren FingerprintManager-API, die inzwischen als veraltet gilt. Die alte API kannte ausschließlich Fingerabdrücke und bot keine einheitliche UI, jeder Hersteller zeigte einen eigenen Dialog mit unterschiedlichem Design. BiometricPrompt liefert dagegen eine vom System bereitgestellte, konsistente Oberfläche über alle unterstützten Biometrie-Typen hinweg und ist seit Android 9 der empfohlene Weg. Neue Apps sollten ausschließlich BiometricPrompt verwenden, die alte API existiert nur noch aus Kompatibilitätsgründen in älteren Codebasen.


// BiometricAuthHelper.kt — minimal BiometricPrompt implementation
import androidx.biometric.BiometricManager
import androidx.biometric.BiometricPrompt
import androidx.fragment.app.FragmentActivity
import androidx.core.content.ContextCompat

fun checkBiometricAvailability(activity: FragmentActivity): Int {
    val biometricManager = BiometricManager.from(activity)
    return biometricManager.canAuthenticate(
        BiometricManager.Authenticators.BIOMETRIC_STRONG
    )
    // Compare against BIOMETRIC_SUCCESS, BIOMETRIC_ERROR_NO_HARDWARE,
    // BIOMETRIC_ERROR_HW_UNAVAILABLE, BIOMETRIC_ERROR_NONE_ENROLLED
}

fun showBiometricPrompt(
    activity: FragmentActivity,
    onSuccess: () -> Unit,
    onError: (String) -> Unit,
) {
    val executor = ContextCompat.getMainExecutor(activity)
    val callback = object : BiometricPrompt.AuthenticationCallback() {
        override fun onAuthenticationSucceeded(result: BiometricPrompt.AuthenticationResult) {
            onSuccess()
        }
        override fun onAuthenticationError(errorCode: Int, errString: CharSequence) {
            onError(errString.toString())
        }
    }

    val prompt = BiometricPrompt(activity, executor, callback)
    val promptInfo = BiometricPrompt.PromptInfo.Builder()
        .setTitle("Biometrische Authentifizierung")
        .setSubtitle("Mit Fingerabdruck oder Gesicht bestätigen")
        .setNegativeButtonText("Abbrechen")
        .build()

    prompt.authenticate(promptInfo)
}

5. Implementierung mit react-native-biometrics

Sobald biometrische Authentifizierung nicht nur lokal, sondern gegenüber einem Server nachweisbar sein soll, kommt react-native-biometrics ins Spiel. Der zentrale Aufruf createKeys() erzeugt ein asymmetrisches Schlüsselpaar direkt auf dem Gerät. Der private Schlüssel verbleibt dabei in der Secure Enclave unter iOS beziehungsweise im Android Keystore und verlässt diese gesicherte Hardware-Komponente nie, weder als Datei noch im Arbeitsspeicher der App. Nur der öffentliche Schlüssel wird an den Server übertragen und dort dem jeweiligen Nutzerkonto zugeordnet.

Für die eigentliche Authentifizierung fordert die App zunächst eine zufällige Challenge vom Server an. Anschließend ruft sie createSignature() auf, wobei genau diese Challenge signiert wird. Das Betriebssystem zeigt dabei automatisch den Face-ID- oder Fingerabdruck-Prompt an, und nur bei erfolgreicher biometrischer Bestätigung wird der private Schlüssel kurzzeitig zum Signieren freigegeben. Die entstandene Signatur wird an den Server zurückgeschickt, der sie mit dem zuvor hinterlegten öffentlichen Schlüssel prüft. Schlägt diese Prüfung fehl, war entweder die Biometrie nicht erfolgreich oder es liegt ein manipulierter Client vor.

Für einfachere Fälle, in denen keine Server-Verifikation nötig ist, bietet dieselbe Bibliothek zusätzlich simplePrompt(), das funktional expo-local-authentication ähnelt: ein reiner Ja-Nein-Prompt ohne kryptografischen Nachweis. Diese Flexibilität, beide Modi in einer Bibliothek zu haben, macht react-native-biometrics zur pragmatischen Wahl, wenn eine App im Laufe ihrer Entwicklung von reiner lokaler Bestätigung zu echter Server-seitiger Verifikation wechseln könnte.


// BiometricChallenge.js — server-verifiable biometric authentication
import ReactNativeBiometrics from 'react-native-biometrics';

const rnBiometrics = new ReactNativeBiometrics({
  allowDeviceCredentials: true, // fall back to device passcode/PIN
});

/**
 * Generates a device-bound key pair once (e.g. during onboarding or login).
 * The private key never leaves the Secure Enclave / Android Keystore.
 */
export async function enrollBiometricKey(userId) {
  const { keysExist } = await rnBiometrics.biometricKeysExist();
  if (keysExist) return true;

  const { publicKey } = await rnBiometrics.createKeys();
  // Send only the public key to the backend, tied to this userId
  await fetch('https://api.mironsoft.de/v1/biometric-keys', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ userId, publicKey }),
  });
  return true;
}

/**
 * Performs a real challenge-response biometric authentication
 * that the server can cryptographically verify.
 */
export async function authenticateWithBiometrics(userId) {
  const challengeRes = await fetch(
    `https://api.mironsoft.de/v1/biometric-challenge?userId=${userId}`
  );
  const { challenge } = await challengeRes.json();

  const { success, signature } = await rnBiometrics.createSignature({
    promptMessage: 'Identität mit Biometrie bestätigen',
    payload: challenge,
  });

  if (!success) {
    return { authenticated: false, reason: 'biometric_prompt_failed' };
  }

  const verifyRes = await fetch('https://api.mironsoft.de/v1/biometric-verify', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ userId, challenge, signature }),
  });

  const { verified } = await verifyRes.json();
  return { authenticated: verified };
}

6. Fallback-Strategien

Kein biometrisches System funktioniert immer und für jeden Nutzer, weshalb Fallback-Strategien fester Bestandteil jeder Implementierung von biometrischer Authentifizierung sein müssen. Face ID kann bei ungünstigem Licht oder verdecktem Gesicht fehlschlagen, ein Fingerabdrucksensor kann durch nasse oder schmutzige Finger falsch negative Ergebnisse liefern, und manche Nutzer richten aus persönlichen Gründen gar keine Biometrie auf ihrem Gerät ein. Eine App, die in diesen Fällen komplett blockiert, verliert Nutzer an einer Stelle, die technisch leicht vermeidbar wäre.

Sowohl iOS als auch Android bieten dafür einen eingebauten Fallback auf den Geräte-Passcode beziehungsweise die Geräte-PIN, der über Parameter wie disableDeviceFallback beziehungsweise allowDeviceCredentials aktiviert werden kann. Dieser Fallback läuft komplett auf Betriebssystemebene ab, die App muss also keinen eigenen PIN-Eingabe-Screen bauen, sondern bekommt lediglich das Ergebnis des System-Dialogs zurückgemeldet. Wichtig ist, diesen Fallback aktiv zuzulassen und nicht aus Bequemlichkeit zu deaktivieren, da sonst Nutzer ohne eingerichtete Biometrie komplett ausgesperrt werden.

Nach mehreren aufeinanderfolgenden Fehlversuchen sperrt sowohl iOS als auch Android die biometrische Eingabe temporär und verlangt danach zwingend den Geräte-Code, ein sogenanntes Lockout-Verhalten, das Brute-Force-Angriffe auf den biometrischen Sensor verhindert. Eine App sollte diesen Zustand erkennen und dem Nutzer klar kommunizieren, warum plötzlich nur noch der Passcode-Dialog erscheint, statt einen scheinbar zufälligen Fehler anzuzeigen. Als Grundregel gilt: Biometrische Authentifizierung sollte nie die einzige Option ohne jeglichen Fallback sein, sondern immer eine schnellere Ergänzung zu einem funktionierenden Passwort- oder PIN-Pfad bleiben.

7. Das Sicherheitsmodell wirklich verstehen

Ein häufiges Missverständnis bei biometrischer Authentifizierung ist die Annahme, ein erfolgreicher Face-ID- oder Fingerabdruck-Prompt beweise gegenüber einem Server automatisch die Identität eines bestimmten Nutzers. Tatsächlich bestätigt ein einfacher Prompt über expo-local-authentication oder simplePrompt() nur sogenannte "Device Owner Authentication": Irgendeine Person, die am entsperrten Gerät sitzt und deren Biometrie im System hinterlegt ist, hat den Prompt bestätigt. Für rein lokale Zugriffskontrolle innerhalb einer App reicht das völlig aus, für eine Aussage gegenüber einem Backend jedoch nicht.

Echte Identitätsprüfung gegenüber einem Server erfordert die in Abschnitt 5 beschriebene Public-Key-Challenge-Response-Authentifizierung. Der entscheidende Unterschied: Nur wenn der Server eine vom Client signierte, serverseitig generierte Zufalls-Challenge kryptografisch gegen den zuvor hinterlegten öffentlichen Schlüssel verifizieren kann, hat er einen belastbaren Beweis, dass tatsächlich der private Schlüssel dieses spezifischen Geräts verwendet wurde, freigegeben durch eine erfolgreiche biometrische Prüfung. Ein simples "true" oder "false" aus einem lokalen Prompt lässt sich dagegen beliebig fälschen, sobald es unverifiziert an einen Server gesendet wird.

Für Anwendungsfälle wie passwortloses Login, Freigabe von Zahlungen oder Signieren rechtlich relevanter Vorgänge ist deshalb ausschließlich der Challenge-Response-Ansatz geeignet. Für weniger kritische Fälle, etwa das erneute Sperren eines bereits eingeloggten App-Bereichs nach einer Pause, reicht die einfachere Device-Owner-Variante aus, da hier ohnehin keine neue Aussage gegenüber einem Server getroffen werden muss, sondern lediglich der bereits authentifizierte Zustand der App geschützt wird.

8. UX Best Practices

Der richtige Zeitpunkt für einen Prompt zur biometrischen Authentifizierung ist entscheidend für die Akzeptanz bei Nutzern. Sinnvolle Momente sind der App-Start nach vollständigem Kaltstart, sensible Aktionen wie das Anzeigen von Kontodaten oder das Bestätigen einer Zahlung, sowie die Rückkehr aus dem Hintergrund nach einer gewissen Inaktivitätszeit. Ein Prompt bei jeder einzelnen Bildschirmnavigation wirkt dagegen aufdringlich und führt dazu, dass Nutzer die App-Nutzung als lästig empfinden, selbst wenn die zugrunde liegende Sicherheit technisch korrekt ist.

Barrierefreiheit verdient bei biometrischer Authentifizierung besondere Aufmerksamkeit. Nicht jeder Nutzer kann oder möchte Biometrie einrichten, sei es aus motorischen, gesundheitlichen oder rein persönlichen Gründen. Eine App muss deshalb immer einen vollständig gleichwertigen Pfad ohne Biometrie anbieten, nicht nur als technischen Fallback, sondern als gleichberechtigte, klar auffindbare Option in den Einstellungen. Wird Biometrie als einzig sichtbarer Login-Weg präsentiert und der Passwort-Pfad versteckt, entsteht faktisch eine Zugangsbarriere für einen Teil der Nutzerschaft.

Fehlermeldungen sollten nie die kryptischen Systemtexte unverändert durchreichen. Statt "Authentication error -7" oder ähnlicher Rohmeldungen aus LAContext beziehungsweise BiometricPrompt sollte die App die bekannten Fehlercodes in verständliche, handlungsorientierte Texte übersetzen: "Fingerabdruck nicht erkannt, bitte erneut versuchen" oder "Face ID ist auf diesem Gerät nicht eingerichtet, bitte Passwort verwenden". Diese Übersetzung reduziert Support-Anfragen spürbar und macht biometrische Authentifizierung für Nutzer nachvollziehbar statt frustrierend.

9. Biometrie-Ansätze im Vergleich

Die Wahl der richtigen Lösung für biometrische Authentifizierung in React Native hängt maßgeblich davon ab, ob am Ende eine Server-seitige Verifikation stehen muss oder eine lokale Bestätigung ausreicht. Die folgende Übersicht vergleicht die drei gängigen Ansätze.

Ansatz Server-Verifikation möglich Setup-Aufwand Einsatzzweck
expo-local-authentication Nein, nur Device-Owner-Check Gering App-Sperre, sensible Aktion erneut bestätigen
react-native-biometrics Ja, Public-Key-Challenge-Response Mittel Passwortloses Login, Zahlungsfreigabe
Eigenes natives Modul Ja, volle Kontrolle Hoch Sonderanforderungen, z. B. eigene Krypto-Parameter

In der Praxis reicht expo-local-authentication für die überwiegende Mehrheit der Fälle mit reiner lokaler Zugriffskontrolle aus und sollte dort auch bevorzugt werden, da es weniger native Abhängigkeiten mitbringt. Sobald jedoch eine Backend-Instanz der biometrischen Bestätigung wirklich vertrauen soll, führt an react-native-biometrics oder einem vergleichbaren eigenen nativen Modul kein Weg vorbei, da nur der Public-Key-Ansatz eine tatsächlich überprüfbare kryptografische Aussage liefert.

Mironsoft

React Native Entwicklung für iOS und Android

Biometrische Authentifizierung, die auch der Server nachvollziehen kann?

Wir bauen Face-ID- und Fingerabdruck-Flows für eure React-Native-App, inklusive echter Challenge-Response-Verifikation gegen euer Backend, sauberer Fallback-Strategien und einer UX, die Nutzer nicht aussperrt.

Face ID & Fingerabdruck

Saubere Einrichtung unter iOS und Android, inklusive Info.plist und AndroidManifest.xml

Server-Verifikation

Public-Key-Challenge-Response mit react-native-biometrics gegen euer Backend

UX & Fallbacks

Barrierefreie Fallback-Pfade und verständliche Fehlermeldungen statt Systemtexten

10. Zusammenfassung

Biometrische Authentifizierung in React Native lässt sich mit zwei etablierten Bibliotheken abdecken: expo-local-authentication für die reine, lokale Geräte-Authentifizierung und react-native-biometrics, sobald eine kryptografisch belastbare Server-Verifikation notwendig ist. Face ID unter iOS verlangt zwingend den Eintrag NSFaceIDUsageDescription und die Prüfung über LAContext.canEvaluatePolicy() vor dem eigentlichen Prompt. Fingerabdruck und Gesichtserkennung unter Android laufen über die moderne BiometricPrompt-API, abgesichert durch die USE_BIOMETRIC-Permission und BiometricManager.canAuthenticate().

Der wichtigste konzeptionelle Punkt bleibt die Unterscheidung zwischen einer einfachen Device-Owner-Bestätigung und einer echten Public-Key-Challenge-Response-Authentifizierung. Nur Letztere liefert einem Server einen tatsächlich überprüfbaren Beweis, dass der private Schlüssel eines bestimmten Geräts nach erfolgreicher Biometrie-Prüfung verwendet wurde. Fallback-Strategien auf den Geräte-Passcode und eine barrierefreie, klar kommunizierte UX runden eine robuste Implementierung von biometrischer Authentifizierung ab, ohne Nutzer auszuschließen, die keine Biometrie eingerichtet haben.

React Native Biometrische Authentifizierung — Das Wichtigste auf einen Blick

Bibliotheken

expo-local-authentication für lokale Checks, react-native-biometrics für Server-verifizierbare Challenge-Response-Signaturen.

Plattform-Setup

NSFaceIDUsageDescription (iOS) und USE_BIOMETRIC-Permission mit BiometricPrompt (Android) sind Pflicht.

Sicherheitsmodell

Device-Owner-Check beweist nichts gegenüber einem Server. Nur Public-Key-Challenge-Response tut das.

Fallbacks & UX

Geräte-Passcode als Fallback immer zulassen, Lockout-Verhalten erkennen, verständliche Fehlermeldungen zeigen.

11. FAQ: React Native Biometrische Authentifizierung

1expo-local-authentication vs. react-native-biometrics?
Ersteres prüft nur lokal den Geräte-Eigentümer ohne Server-Nachweis. Letzteres erzeugt Schlüsselpaare und liefert Challenge-Response-Signaturen, die ein Backend verifizieren kann.
2Warum ist NSFaceIDUsageDescription Pflicht?
iOS verlangt eine Nutzungserklärung vor dem ersten Face-ID-Prompt. Fehlt der Eintrag, stürzt die App beim ersten Aufruf ab.
3Was prüft canEvaluatePolicy()?
Ob passende Hardware vorhanden und eine Biometrie eingerichtet ist, vor dem eigentlichen evaluatePolicy()-Prompt.
4Biometrie nicht verfügbar, was dann?
Geräte-Passcode-Fallback aktiv zulassen, damit Nutzer ohne eingerichtete Biometrie nicht ausgesperrt werden.
5Wie funktioniert Server-Verifikation wirklich?
Server-Challenge signieren mit dem geräteinternen privaten Schlüssel nach Biometrie-Erfolg, Server verifiziert mit dem hinterlegten öffentlichen Schlüssel.
6Was passiert nach mehreren Fehlversuchen?
Temporäre Sperre der Biometrie, danach ist zwingend der Geräte-Code nötig. Verhindert Brute-Force-Angriffe.
7Verlassen biometrische Daten das Gerät?
Nein. Rohdaten bleiben in der Secure Enclave bzw. im Android Keystore, weder App noch Server sehen sie je.
8BiometricPrompt vs. alte Fingerprint-API?
BiometricPrompt ist seit Android 9 Standard, unterstützt mehrere Biometrie-Typen und bietet eine konsistente Systemoberfläche statt herstellerspezifischer Dialoge.
9Barrierefreiheit beachten?
Immer einen gleichwertigen, klar sichtbaren Login-Pfad ohne Biometrie anbieten, nicht nur als versteckten Fallback.
10Erneuter Prompt nach Hintergrund?
Nur bei sensiblen Bereichen nach sinnvoller Inaktivitätszeit, nicht bei jedem kurzen App-Wechsel.