Download the PHP package sghimire/mobile-biometric without Composer
On this page you can find all versions of the php package sghimire/mobile-biometric. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.
Download sghimire/mobile-biometric
More information about sghimire/mobile-biometric
Files in sghimire/mobile-biometric
Package mobile-biometric
Short Description Self-contained native biometric authentication (Face ID / Touch ID / Android BiometricPrompt) for NativePHP Mobile — own facade, fluent API, events, and JS bindings, with no dependency on the paid nativephp/mobile-biometrics plugin.
License MIT
Informations about the package mobile-biometric
Mobile Biometric
Native Face ID / Touch ID / Android BiometricPrompt authentication for NativePHP Mobile apps.
This package is a free, self-contained alternative to the paid nativephp/mobile-biometrics plugin. It ships its own Laravel facade, a fluent prompt builder, a Laravel event, JS/TypeScript bindings, and the native Kotlin/Swift implementation — with no dependency on the paid plugin.
Features
- One call to trigger the device's native biometric prompt (Face ID, Touch ID, or Android fingerprint/face unlock).
- Fluent, chainable prompt builder in both PHP and JavaScript.
- Optional fallback to the device PIN/pattern/password (
allowDeviceCredential). - A
CompletedLaravel event you can listen to, or bind straight to a Livewire method with#[OnNative]. - A ready-made
biometric.verifiedroute middleware for gating routes behind a successful unlock. - Works from PHP (Blade/Livewire) and from JavaScript (Vue, React, Inertia, or plain JS).
Example App
Authenticator is a full example app built using this plugin
Requirements
- PHP ^8.2
nativephp/mobile^3.0livewire/livewire— only needed if you use the#[OnNative]attribute
Installation
Laravel's package auto-discovery registers BiometricsServiceProvider for you. Then register the plugin with NativePHP:
This wires up the plugin's nativephp.json manifest (bridge functions, Android permission, iOS NSFaceIDUsageDescription) into your native build. Rebuild/reinstall the native shell afterwards (php artisan native:install or native:run) so the permission and bridge function are picked up.
How It Works (Under the Hood)
The prompt request and its result travel two different paths — a synchronous "start" call, then an asynchronous result delivered back through two independent channels at once.
- Request out.
Biometrics::prompt()->prompt()(PHP) andBiometrics.prompt()(JS) both reach the same native bridge — JS viafetch('/_native/api/call', { method: 'Biometrics.Prompt', params }), PHP via the globalnativephp_call('Biometrics.Prompt', json_encode($params)). The bridge router matches"Biometrics.Prompt"toBiometricFunctions.Prompt(Kotlin on Android, Swift on iOS), which shows the OS biometric UI. - Immediate ack. That call returns right away with
{"started": true}— this is theboolyou get back from->prompt()/ the resolved value ofawait Biometrics.prompt(). It only confirms the OS prompt appeared, not that the user authenticated. - Result comes back later, twice. Once the user finishes (or cancels), the native side injects one script into the app's webview that does two independent things: fires a
native-eventCustomEventondocument(what the JSOn()/Off()helpers listen for), and makes a second call back into Laravel that instantiates and dispatches the realCompletedevent (whatEvent::listen()/#[OnNative]pick up).
PHP and JS each get their own notification of the same result — you don't need one side to relay to the other, and both can listen independently in the same app.
Because the result is asynchronous, always drive your UI from the Completed event/listener — never from the return value of prompt().
PHP Usage
The Biometrics facade
prompt() on the builder returns bool — true once the request reached the native bridge, false if it couldn't be started (e.g. running outside the native shell, or the call was already started once). It does not tell you whether the user was actually authenticated; wait for the Completed event for that.
If you never call ->prompt() explicitly, it fires automatically when the builder object is destructed (e.g. goes out of scope) — so Biometrics::prompt()->title('Unlock'); alone is enough to trigger it. Calling ->prompt() yourself is recommended so you can check the return value.
Builder methods
| Method | Description |
|---|---|
id(string $id) |
Custom correlation ID for this prompt (auto-generated UUID if omitted). |
title(string $title) |
Prompt title shown to the user. |
subtitle(string $subtitle) |
Prompt subtitle/description. |
cancelText(string $text) |
Label for the cancel button. |
allowDeviceCredential(bool $allow = true) |
Allow falling back to device PIN/pattern/password. |
event(string $eventClass) |
Dispatch a custom event class instead of the default Completed (must exist). |
remember() |
Flash the prompt's ID into the session so it survives a redirect; retrieve it later with PendingBiometricPrompt::lastId(). |
getId() |
Get (or lazily generate) this prompt's correlation ID. |
prompt() |
Send the prompt request to the native bridge. Returns bool. |
Tracking the app's unlock state
Biometrics also tracks a simple, process-lifetime "is this session unlocked" flag — handy for gating a whole app session behind one biometric check rather than checking per-action:
Typically you'd call Biometrics::unlock() inside your Completed event listener once success is true.
Listening for the result
Livewire: #[OnNative]
Bind the event straight to a component method instead of registering a listener manually:
Route middleware
Protect routes behind a successful unlock with the bundled biometric.verified middleware alias:
The middleware checks Biometrics::isUnlocked() and redirects if it's false — pair it with the Completed listener pattern above so unlock() gets called once the user authenticates.
JavaScript Usage
Importing
This package doesn't publish a #nativephp import alias (that's reserved for NativePHP's first-party plugins). Import the file directly — either from the vendor path, or copy it into your own resources/js/ and import it from there:
Full TypeScript types are included in biometric.d.ts alongside it, so editors get autocomplete either way.
Basic prompt
Biometrics.prompt() returns a thenable builder — await it directly, or chain builder methods first:
Resolving just means the native prompt was shown, exactly like the PHP side — listen for the Completed event to get the actual result.
Listening for events
Vue 3 example
React example
JS API reference
| Export | Signature | Description |
|---|---|---|
Biometrics.prompt() |
() => PendingBiometricPrompt |
Start building a prompt. |
.id(id) |
(string) => this |
Custom correlation ID. |
.title(title) |
(string) => this |
Prompt title. |
.subtitle(subtitle) |
(string) => this |
Prompt subtitle. |
.cancelText(text) |
(string) => this |
Cancel button label. |
.allowDeviceCredential(allow?) |
(boolean = true) => this |
Allow PIN/pattern/password fallback. |
On(event, callback) |
(string, (payload, eventName) => void) => void |
Subscribe to a native event. |
Off(event, callback) |
(string, (payload, eventName) => void) => void |
Unsubscribe. |
Events.Biometric.Completed |
string |
Event name constant for the Completed event. |
await-ing (or .then-ing) a PendingBiometricPrompt sends the request to the native bridge exactly once — awaiting it twice is a no-op the second time.
Events reference
Completed
Dispatched once, asynchronously, after the user finishes (or cancels) the biometric prompt.
| Property | Type | Description |
|---|---|---|
success |
bool / boolean |
Whether authentication succeeded. |
id |
?string |
The correlation ID from .id(), if one was set. |
message |
?string |
Error message on failure; null for a user-initiated cancel. |
- PHP class:
Sandip\Biometric\Native\Events\Biometric\Completed - JS event name constant:
Events.Biometric.Completed
Implementation Guide: Building a Biometric Unlock Gate
A common pattern: lock part of the app (e.g. /wallet) behind a biometric check that resets every time the app is opened. Here's the full flow — Blade/Livewire first, then the JS-only equivalent.
1. Protect the route
Anyone hitting /wallet without a matching unlock() call in this process's lifetime gets redirected to the login named route.
2. Reset the lock on app start
Call this once when the app boots (e.g. AppServiceProvider::boot()) so every fresh launch starts locked:
3a. Livewire lock screen
Tap the button, the native prompt appears, Completed lands on the component via #[OnNative], Biometrics::unlock() flips the flag the middleware checks, and the redirect takes the user straight into the now-unlocked route.
3b. Vue/React SPA lock screen
If your frontend is a JS SPA (Inertia or otherwise) hitting the same /wallet route, drive the prompt from JS and let a PHP-side listener registered once, globally, call Biometrics::unlock() — the JS side only needs to know when to navigate. This works because Completed reaches PHP and JS independently (see How It Works).
The PHP-side Biometrics::unlock() call (registered once, e.g. via a global Event::listen(Completed::class, ...) in a service provider) is what actually satisfies the biometric.verified middleware — the JS listener above is purely a UI reaction, not what unlocks the route.
Platform notes
| Android | iOS | |
|---|---|---|
| Min OS version | API 23 | 15.0 |
| Permission | android.permission.USE_BIOMETRIC |
NSFaceIDUsageDescription in Info.plist |
| Native implementation | resources/android/BiometricFunctions.kt (AndroidX BiometricPrompt) |
resources/ios/BiometricFunctions.swift (LocalAuthentication) |
Both are configured automatically by nativephp.json — you don't need to edit native project files by hand.
Testing
Outside of a compiled native shell, Biometrics::prompt()->prompt() returns false (there's no bridge to call) — this is expected and is exactly what the test suite asserts.
License
MIT