Tutorial
Implementing Biometric Authentication in an Android TWA
September 6, 2026 · 10 min read
User authentication on mobile devices must be friction-free to maintain high conversion and engagement rates. While typing complex passwords on a virtual keyboard is tedious, native applications have long bypassed this issue by offering biometric hardware checks, such as fingerprint readers and facial recognition. Progressive Web App developers deploying to the Google Play Store using a Trusted Web Activity can achieve this exact native behaviour by implementing the Web Authentication API, commonly known as WebAuthn.
The Mechanics of WebAuthn in a Trusted Web Activity
WebAuthn is a web standard designed to provide secure, credential-based authentication using cryptographic key pairs. Inside a TWA, which operates within a secure Chrome context integrated with Google Play Services, WebAuthn calls are automatically routed to the native Android Biometric Prompt. This bridge allows your web-based application to request access to the device fingerprint scanner or front-facing depth camera directly, without requiring native Java or Kotlin bridges.
Before implementing the API, developers must understand the workflow differences between traditional web sessions and platform-based biometric credentials. The table below outlines how WebAuthn registration and verification steps map directly to Android hardware prompts.
| WebAuthn Concept | Web API Call | Android Action Triggered | Cryptographic Outcome |
|---|---|---|---|
| Credential Creation | navigator.credentials.create() | Requests fingerprint/facial scan to enrol | Generates a public/private key pair on device secure hardware |
| Credential Assertion | navigator.credentials.get() | Displays native system biometric prompt | Signs a server challenge using the secure on-device private key |
| Relying Party | rp domain matching context | Verifies app signature matches origin | Guarantees authentication only works on registered domains |
Setting Up Biometric Registration (Credential Creation)
The biometric flow begins with enrolling the user device. To accomplish this, your backend server must generate a unique, cryptographically secure registration challenge. This challenge prevents replay attacks and is passed back to your frontend JavaScript application to trigger the registration prompt.
When invoking the WebAuthn API for a mobile-first application inside a TWA, you must configure the authenticator selection properties. Specifically, set the authenticatorAttachment to platform. This property instructs the browser to bypass physical USB security keys or external Bluetooth authenticators, focusing solely on the internal hardware authenticators built directly into the Android device.
The Registration Code Template
Below is a standardized JavaScript implementation for triggering biometric registration on the user device. This code must be executed within a secure origin (HTTPS) and should be initiated by a direct user gesture, such as tapping a Biometric Registration button.
async function registerBiometrics(username, challengeFromServer, userId) { const publicKeyCredentialCreationOptions = { challenge: Uint8Array.from(challengeFromServer, c => c.charCodeAt(0)), rp: { name: "My TWA SaaS Platform", id: window.location.hostname }, user: { id: Uint8Array.from(userId, c => c.charCodeAt(0)), name: username, displayName: username }, pubKeyCredParams: [{ alg: -7, type: "public-key" }, { alg: -257, type: "public-key" }], authenticatorSelection: { authenticatorAttachment: "platform", requireResidentKey: true, userVerification: "required" }, timeout: 60000, attestation: "none" }; try { const credential = await navigator.credentials.create({ publicKey: publicKeyCredentialCreationOptions }); return credential; } catch (error) { console.error("Biometric registration failed:", error); throw error; } }
In this code block, the algorithm identifiers (-7 for ES256 and -257 for RS256) represent widely supported cryptographic formats compatible with Android Secure Enclaves and hardware keystores. The userVerification requirement set to required ensures the Android OS forces the user to complete their biometric verification step rather than simply acknowledging a system prompt.
Implementing Biometric Authentication (Assertion)
Once a user successfully registers their device, future logins can bypass passwords entirely. When the user attempts to sign in, your server issues a new challenge, and the frontend web app requests a cryptographic signature using the credentials stored on the device.
To prompt the user for their fingerprint or facial verification during login, execute the assertion request shown in the implementation pattern below:
async function authenticateUser(challengeFromServer, registeredCredentialId) { const publicKeyCredentialRequestOptions = { challenge: Uint8Array.from(challengeFromServer, c => c.charCodeAt(0)), allowCredentials: [{ id: Uint8Array.from(atob(registeredCredentialId), c => c.charCodeAt(0)), type: "public-key" }], userVerification: "required", timeout: 60000 }; try { const assertion = await navigator.credentials.get({ publicKey: publicKeyCredentialRequestOptions }); return assertion; } catch (error) { console.error("Biometric authentication failed:", error); throw error; } }
Upon calling this function, the Android OS halts active rendering of the TWA and overlays the native biometric modal. If the biometric scan matches the registered profile, the system generates a signature and returns it to your script context. Your frontend application must then transmit this payload back to your backend server to verify the signature and issue an authentication cookie or JWT session token.
Security Requirements and the Role of Digital Asset Links
WebAuthn enforces strict origin-matching rules to prevent phishing and spoofing. This security layer is highly relevant when running within an Android TWA. For the WebAuthn API to function successfully inside a TWA, the application must establish a deep, cryptographic bond of trust between the Android APK/AAB wrapper and the underlying web domain.
This trust is established by deploying a Digital Asset Links configuration file. Without a valid asset links file, the operating system limits the TWA browser context, preventing access to platform biometrics and throwing security exceptions when calling the credentials API.
To ensure your TWA is fully trusted for biometric procedures, verify the following configuration conditions:
- Generate a assetlinks.json file containing your Android app package name and the SHA-256 fingerprint of your signing keystore.
- Deploy this file to your web server at the exact path:
/.well-known/assetlinks.json. - Ensure the file is served with a content-type header of
application/jsonand returns a 200 HTTP status code. - Verify that the SHA-256 fingerprint matches your production Google Play signing key, especially if you utilise Google Play App Signing, as Google regenerates this key upon distribution.
Handling Fallbacks and Hardware Limitations Gracefully
While biometric authentication is highly convenient, it cannot be the sole mechanism for logging into your application. Devices may lack biometric sensors, sensors can become damaged, or users may choose not to grant biometric access. Therefore, your TWA must check for hardware compatibility before exposing biometric login buttons to the interface.
Before displaying a Register Fingerprint or Login with Face ID button, query the browser for platform authenticator availability using the built-in capability check:
if (window.PublicKeyCredential && PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable) { PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable() .then((available) => { if (available) { showBiometricLoginButton(); } else { displayStandardPasswordLoginForm(); } }) .catch((err) => console.error("Capability check error:", err)); } else { displayStandardPasswordLoginForm(); }
By implementing this programmatic gate, you ensure that legacy devices and unsupported environments degrade gracefully to standard password, PIN, or magic link registration pathways, ensuring seamless user authentication experiences regardless of the hardware profile used.
Ready to ship your Android app?
Paste your PWA URL, get a signed APK and a Google Play ready AAB in minutes.
Build my app