Solution guide · Mobile App

Building an App With Biometric Login: Real Cost, Real Failure Modes

The short answer

Biometric login is a key management problem wearing a Face ID prompt. Added properly to an existing app it runs $15,000 to $60,000. As part of a first release, budget $50,000 to $130,000 over 10 to 16 weeks. A full identity platform with a self hosted passkey server, device fleet revocation and a verified recovery path runs $150,000 to $350,000 over 6 to 12 months. The prompt takes a day. Everything behind it is the project.

What this involves once real users touch it

The demo takes an afternoon. Call BiometricPrompt on Android or LAContext.evaluatePolicy on iOS, the sensor says yes, you call your login function. It works on your phone. It ships.

On a payments app we inherited, a user's partner added their own fingerprint to the phone, which Android allows up to five of and iOS allows as one Alternate Appearance for Face ID. The partner opened the app, went straight into the account, and money moved. Nothing was hacked. The postmortem was three lines: if (result.isSuccess) unlock(), the refresh token sitting in SharedPreferences, and a key never bound to the enrolled biometric set. The sensor answered "is this a valid finger on this device," which is not "is this the person who owns this account."

That gap is the discipline. Biometric login is a local gate over a cryptographic key, and the cost lives in how that key is created, invalidated, restored and revoked.

The biometric never proves anything to your server

Your backend cannot see a face. The only thing that crosses the network is a signature produced by a private key the secure hardware refused to release until the sensor matched.

So the correct build generates a key inside the Secure Enclave or the Android Keystore with setUserAuthenticationRequired(true) and hands it to the prompt as a CryptoObject. The server sends a random challenge, the key signs it, the server verifies against the public key registered at enrollment. If the private key never leaves hardware, a rooted device cannot fake the answer.

Skip the CryptoObject and your gate is a boolean, and a boolean is a Frida one liner. Hooking evaluatePolicy to return true is a party trick on jailbroken devices. A two day quote for biometric login is quoting the boolean.

One consequence buyers do not expect: with WebAuthn and passkeys, your server receives a User Verified flag in the assertion, and that flag is true whether the user used their face, their fingerprint or the device PIN. No bit says "Face ID happened." If a product team wants a dashboard of who logged in biometrically, tell them now that the protocol does not carry it. Same with the signature counter: synced platform passkeys from iCloud Keychain return a signCount of zero, so the clone detection FIDO documentation describes does nothing for the authenticators most of your users have.

Key invalidation is what pages you at 3am

Hardware backed keys are deliberately brittle. That is the point, and it is also the outage.

On Android, a key created with setInvalidatedByBiometricEnrollment(true) is destroyed the moment the user adds a fingerprint, and your next call throws KeyPermanentlyInvalidatedException. Catch it and you re-enrol gracefully. Miss it and the app crashes on the login screen for that user forever, because the exception fires on every launch and the only escape is clearing app data.

On iOS the same problem wears two disguises. Keychain items created with .biometryCurrentSet become unreadable when Face ID enrollment changes, while .biometryAny does not, which is the flag that let the partner into the payments app. Separately, LAContext.evaluatedPolicyDomainState is an opaque blob that changes when the enrolled set changes. Storing it at enrollment and comparing on each launch detects "a new face was added since this user trusted this device," which is a risk decision your business should make, not your iOS developer.

Then the restore case. Keychain items marked kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly do not migrate to a new phone. Correct behaviour, and also the incident: the week a major iOS version ships and a chunk of your base migrates devices, all of those users are silently logged out at once. If your fallback is an SMS one time code, you have aimed your entire user base at your Twilio spend cap inside a four hour window.

Two smaller landmines with outsized cost. NSFaceIDUsageDescription missing from Info.plist crashes the app the first time Face ID is invoked, and it does not crash on Touch ID devices, so it survives testing on an older test phone and detonates on release day. And you cannot meaningfully test any of this in CI: the iOS Simulator gives you Features, then Face ID, then Matching Face, the Android emulator takes adb -e emu finger touch 1, and cloud device farms do not drive real sensors. Biometric regression testing is manual on a physical device matrix, permanently. Budget it as a recurring line.

Android is three products sharing one API

The AndroidX BiometricPrompt API presents one clean surface over an uneven fleet, and the seam is the authenticator class.

Only Class 3, exposed as BIOMETRIC_STRONG, can unlock a Keystore key. Class 2, BIOMETRIC_WEAK, cannot back a CryptoObject at all. Plenty of budget and mid range handsets ship camera based face unlock that is Class 2. So a user with face unlock working on their lock screen calls canAuthenticate(BIOMETRIC_STRONG) and gets BIOMETRIC_ERROR_NONE_ENROLLED. Support will file this as a bug. It is the security model. The decision is whether you fall back to DEVICE_CREDENTIAL, the PIN or pattern, which does unlock Keystore keys, or tell that segment biometric login is unavailable.

Then the error codes. ERROR_LOCKOUT is a 30 second cooldown after five failures. ERROR_LOCKOUT_PERMANENT needs a device credential to clear and is a different screen. ERROR_CANCELED from the system is not ERROR_USER_CANCELED, and treating them alike produces the bug where the prompt loops after an incoming call. ERROR_VENDOR is a documented escape hatch for OEM specific codes with vendor defined meanings, which in practice means certain Xiaomi and Huawei builds return values nobody has a table for. iOS is tidier but still needs separate handling for .userFallback, .systemCancel, .biometryNotEnrolled and .biometryLockout. That is roughly a dozen states, each with different copy and a different next action, and it is most of the QA effort on this feature.

Passkeys and the two files that fail silently

If you want passwordless login rather than a convenience gate over an existing session, you want passkeys, which means running a FIDO2 relying party: SimpleWebAuthn on Node, java-webauthn-server from Yubico, or py_webauthn. You store the credential ID, the public key, the AAGUID and the sign counter, and you verify attestation at registration.

The part that eats a sprint is domain association. iOS needs an apple-app-site-association file served from /.well-known/ with a webcredentials entry and your team ID. Android needs assetlinks.json carrying the SHA-256 fingerprint of your signing certificate. With Play App Signing enabled, the fingerprint on your machine is not the one Google serves, so a developer who copies their local fingerprint ships passkeys that work in debug and fail on every production install, with no error a user could report. Verify against the fingerprint in the Play Console, and again after any key rotation.

Recovery is where the money and the fraud go

Every biometric enrollment is bootstrapped from something else, and that something else is your real security level. Ship a flawless Secure Enclave implementation behind an SMS reset and you have built an SMS authentication app with a nice animation. SIM swap crews go straight there.

A serious build treats re-enrollment on a new device as its own risk decision: step up verification, a cooling off window before the new device can move money, a notification to the old device, an audit trail. In EU payments, PSD2 strong customer authentication wants two factors from separate categories plus dynamic linking, meaning the amount and the payee are cryptographically bound into what the user approves. Signing an opaque nonce does not satisfy an auditor. Signing a challenge derived from the transaction details does.

One hard line: do not casually build server side face matching. Storing a face template on your servers puts you inside the Illinois Biometric Information Privacy Act, which requires written consent and a published retention schedule and carries a private right of action. Texas CUBI and Washington have their own regimes. On device Face ID and Touch ID keep you out of this entirely, because Apple and Google never hand you the template. That is a legal reason to stay on platform biometrics, not only an engineering one.

What it costs and how long it takes

These are Digital Heroes delivery bands, drawn from what this capability has taken across 2,000+ projects.

Added to an existing app with working auth, a local biometric gate over a hardware bound refresh token, both platforms, real error handling and a re-enrollment path: $15,000 to $60,000. As part of a first release, where you also build the session model and recovery flow it depends on: $50,000 to $130,000 in 10 to 16 weeks. A full platform with a self hosted FIDO2 relying party, device fleet registry, admin revocation console, verified recovery and regulator evidence: $150,000 to $350,000 over 6 to 12 months.

What moves this capability's number. Web in scope pushes you from a local gate to a real relying party, roughly doubling the backend. Regulated payments or health adds dynamic linking, audit artefacts and a documented threat model. Offline authentication, common in field and logistics apps, removes the server challenge and forces a device local trust model that is hard to get right. Enterprise deployment adds work profiles and MDM behaviour. And the device matrix: supporting Class 2 only Android hardware is an extra branch of design and QA, and it is the most commonly forgotten item in other people's quotes.

When you should not build this

If you are not an identity provider for anybody else, do not write your own FIDO2 relying party. Take a managed one: Auth0, Stytch, Descope, Hanko or Corbado. They price per monthly active user, a rounding error at 10,000 users and a real line item at 500,000, and by the time it is a real line item you will know enough to bring it in house on your terms.

The buyer who should take that deal: a consumer or B2B SaaS product where auth is a cost centre, with no offline requirement and no data residency mandate. Buy the passkey server, keep the client work, because that is where your differentiation and all of the failure modes live. Building it yourself is right in three cases: authentication is your product, you are contractually forbidden from third party identity storage, or you must authenticate with no network. Outside those three, a custom relying party is a hobby you are paying for.

How to brief and vet a developer

Give them the constraints that decide the architecture: regulated or not, offline or not, web in scope or not, whether you own the existing session model, and your worst supported Android device.

Then ask these. What happens when a user adds a fingerprint after enrolling, and where exactly does that exception get caught? Show me where the key is created, and prove the biometric result is not a boolean. What is the difference between Class 3 and Class 2 on Android, and what do users on Class 2 hardware see? Which Keychain access control flag are you using, and why that one? What is our recovery flow, and what stops a SIM swap from owning it? How do we revoke one device without logging out the fleet? Who verifies our assetlinks fingerprint against Play App Signing?

Someone who has shipped this answers the enrollment question in one sentence, usually with a war story attached. Someone who has not will describe the prompt.

Research & sources

The evidence behind this guide

Independent findings on why this investment pays off. Every link goes to the primary source.

  1. Standish's 2015 CHAOS research found roughly a third of software projects (about 36% by the Modern definition) fully succeed on time, on budget, and on scope, with top success drivers including executive support, user involvement, and clear requirements/business objectives. Source: Standish Group (CHAOS Report) (2015) →
  2. Brands not sending push notifications can lift 90-day app retention by 190%, and forfeit roughly 95 cents of every dollar spent on user acquisition when opted-in users receive no messages within 90 days; rich notifications with images see 56% higher direct open rates. Source: Airship (2024) →
  3. Only about 30% of digital transformations succeed at meeting their objectives, but getting six critical success factors in place (leadership commitment, talent, agile culture, progress monitoring, clear strategy, and a modernized platform) raises the odds of success from 30% to 80%. Source: Boston Consulting Group (BCG) (2020) →
  4. Companies in the top quartile of McKinsey's Developer Velocity Index had 2014-18 revenue growth four to five times faster than bottom-quartile peers, showing that software-building capability is a driver of business performance, not just a support function. Source: McKinsey & Company (2020) →
Rohan Malhotra · Enterprise Software Consultant

Rohan advises mid-market and enterprise teams on ERP, CRM and custom software, and has led delivery on dozens of business-software builds.

Writes for Digital Heroes, shipping business software for 2,000+ brands across 55+ countries since 2017.

FAQ

Frequently asked questions

How much does it cost to add biometric login to an app?
Added to an app that already has working authentication, expect $15,000 to $60,000 across iOS and Android. That covers hardware backed key generation, the roughly dozen prompt error states, re-enrollment after a biometric change, and a real device test pass. Quotes under $10,000 are almost always for a boolean gate that a rooted device defeats in one line of code.
How long does biometric login take to build?
Two to four weeks inside an existing app with a solid session model. Ten to sixteen weeks if it is part of a first release, because you are also building the session and recovery flows it sits on top of. Six to twelve months for a full platform with a self hosted passkey server and fleet revocation.
Can you add biometric login to our existing app?
Yes, and it is usually the cheaper path. The work depends on how your session model works today. If you already have refresh tokens and a clean revocation story, biometrics bind a hardware key to that and the change stays contained. If sessions are ad hoc or tokens live in plain storage, that gets fixed first, and it is the larger half of the job.
What breaks at scale with biometric login?
Key invalidation events that hit thousands of users at once. Major OS releases and device migrations wipe device bound Keychain items by design, so a whole cohort re-authenticates in the same few hours and floods whatever your fallback is. Teams that only budget for the happy path find this out when their SMS provider hits its spend cap.
Should we use a third party service instead of building it?
If authentication is not your product, yes. Auth0, Stytch, Descope, Hanko and Corbado all run the passkey server for you, priced per monthly active user, and it stays cheap until you are large. Build your own relying party only if auth is the product, you cannot store identity with a third party, or you need offline authentication.
Is biometric login actually secure, or is it theatre?
It depends on one implementation detail. If the biometric releases a private key held in the Secure Enclave or Android Keystore and that key signs a server challenge, it is strong. If the code checks whether the prompt returned success and then logs the user in, it is theatre, and a Frida hook defeats it on a rooted device.
Does biometric login work on all Android phones?
No, and this catches most budget planning. Only Class 3 biometrics can unlock a Keystore key, and plenty of mid range devices ship Class 2 face unlock that cannot. Those users have face unlock on their lock screen while your app correctly reports no biometric enrolled, so you need a deliberate fallback to device PIN or a clear message.
Can we log which users signed in with their face rather than a PIN?
Not reliably. The WebAuthn assertion carries a User Verified flag that is true for face, fingerprint and device PIN alike, with no distinction between them. If a compliance or analytics requirement depends on proving biometric specifically, rewrite that requirement before the build starts.
We have a $40,000 budget. What can we realistically get?
A properly hardware bound biometric gate on iOS and Android over your existing login, with real error handling, re-enrollment after biometric changes, and a tested fallback. That fits comfortably. What does not fit is a self hosted passkey server, a web credential flow, an admin revocation console, or regulated payment dynamic linking. Take the client work now and add the server side when volume justifies it.
How long does it take to go from idea to a live app in the App Store?
Plan on 10 to 16 weeks for a focused first version on Digital Heroes timelines: about two weeks of design, eight to ten weeks of development and testing, then store submission. Apple usually reviews within 24 to 48 hours, and Google Play can take up to a week for a new developer account. The schedule slips when the feature list grows mid-build far more often than it slips because of the stores.
Can custom software connect to the tools we already use, like QuickBooks, Stripe, and Google Workspace?
Yes, and connecting your existing tools is one of the main reasons to build custom: mainstream platforms like QuickBooks, Stripe, Shopify, and Google Workspace all publish documented APIs. Budget 1 to 3 weeks of work per integration depending on API quality and how much data flows in both directions. Ask any vendor whether they have integrated with your specific tools before, because quirks like QuickBooks' OAuth token handling and API rate limits get learned on someone's project, and it should not be yours.
Does it matter which tech stack the agency wants to use?
Yes, but not in the way most buyers expect: the goal is boring, popular technology such as React, Node.js or Python, and PostgreSQL, because any future team can maintain it and hiring a replacement developer takes days, not months. The red flag is an agency-proprietary framework or an unusual language, which welds you to that one vendor no matter what your contract says about code ownership. A useful test: could you find three freelancers fluent in this stack within a week? If not, push back.
What changes when my app grows from 1,000 to 100,000 users?
Scaling from 1,000 to 100,000 users mostly changes the backend and the bills, not the app on the phone. Expect database tuning, caching, and a move off entry-level hosting tiers, with infrastructure costs climbing from tens of dollars a month into the hundreds or low thousands. This is also where no-code backends hit hard ceilings, Bubble's workload unit pricing being the classic example, which is why products expecting real scale either start custom or plan the migration early.
We run everything on spreadsheets and Airtable. How do we know it's time for custom software?
The reliable signals are re-typing the same data into multiple tools, one employee acting as human middleware between systems, and errors appearing in handoffs between teams. Hard limits force the issue too: Airtable's Team plan caps at 50,000 records per base, and Business costs $45 per seat per month, so a 20-person team pays about $10,800 a year for a tool it has already outgrown. When workarounds consume more hours than the tools save, the spreadsheet era is over.
What does it cost to run a mobile app every month after launch?
Budget three buckets: store fees (Apple charges $99 a year, Google Play a one-time $25), hosting and infrastructure, and per-use services like maps, SMS, or payment processing. Across Digital Heroes client projects, a small production app runs $150 to $500 a month all-in before any new feature work. The number scales with usage, so ask your agency for a cost projection at 1,000 users and at 50,000, not just at launch.
Can I move my users and data off a no-code platform into a custom app?
Your data can move, but your users' passwords cannot. Platforms like Bubble let you export records through CSV files or their API, but password hashes never leave the platform, so a migration needs a password reset or email login flow for every existing user. Plan the export before you hit the platform's pricing or capacity ceilings, because migrating under pressure is how data gets lost.
How many people does it actually take to build a mobile app?
A typical agency team is four to six people: a project lead, a designer, one or two mobile developers, a backend developer, and a tester, most of them part-time on your project. A lean first version can ship with three. Be skeptical of one person claiming to cover design, mobile, backend, and testing alone on a complex app; something on that list is being skipped, and it is usually testing.
Can I start my app on Bubble or FlutterFlow and move to custom code later?
You can move partially, and the two tools differ sharply. FlutterFlow exports real Flutter source code on its paid plans, so a development team can take it over and keep building; Bubble has no code export, so leaving Bubble means a rebuild where only your data comes with you. If a future migration is realistic, pick FlutterFlow, keep the data model clean, and treat the no-code version as a market test rather than the permanent product.
Keep reading
let's build

Build something worth launching.

A plan, a team, a timeline, within 24 hours. No decks, no discovery calls. Tell us what you're building and we'll come back with a real scope and a real number.

message us directly · we reply within one business day

mission briefing

Monthly dispatch

Playbooks, real build costs, and what we're shipping. One email a month. No fluff.

visit us

New York HQ

1140 Broadway, Suite 704 · New York, NY 10001

Get directions
Online now

Hey there 👋 How can we help you today?