> For the complete documentation index, see [llms.txt](https://docs.buildnatively.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.buildnatively.com/guides/integration/biometrics-and-credentials.md).

# Biometrics & Credentials

## What is Biometrics & Credentials?

Biometrics & Credentials gives your app two related capabilities: verifying the user's identity using the device's native biometric authentication (Face ID, Touch ID, or device passcode), and securely storing and retrieving login credentials on the device.

Credentials are stored in the device's secure storage - the **iOS Keychain** on iPhone and **private Local Storage** on Android. They are tied to your app's hostname, so they are only accessible from within your specific app.

## Prerequisites

{% hint style="success" %}
This feature is available in all plans. [See all plans](/getting-started/subscription-plans.md)
{% endhint %}

## Implementation

Choose your integration method below: **Bubble.io Plugin** (No-Code), **JavaScript SDK** (Code), or **AI Agents** (for AI-powered editors like Lovable, Base44, and Replit).

### Initialization

{% tabs %}
{% tab title="Bubble.io Plugin" %}
**Check Plugin**

Before starting, verify if the Natively plugin is already installed in your Bubble project.

1. Open your Bubble editor and navigate to the Plugins tab in the left sidebar.
2. **Check Installed Plugins:** Look through your list of installed plugins for "Natively iOS & Android app builder".
   * If it IS installed: Check the version number. If an update is available (e.g., you see a button saying "Update"), click it to ensure you have the latest features and bug fixes.

<figure><img src="https://docs.buildnatively.com/~gitbook/image?url=https%3A%2F%2F3352617162-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F90tV7pYflEQdiAr2VfWu%252Fuploads%252FmfnSUug82IdnxOAoBrak%252Fnatively_app_builder_bubble_plugin_update.png%3Falt%3Dmedia%26token%3Dc193f69f-b03b-4be4-b80b-f34ba37ac212&#x26;width=768&#x26;dpr=3&#x26;quality=100&#x26;sign=a89e4510&#x26;sv=2" alt=""><figcaption></figcaption></figure>

* If it is NOT installed: Click the + Add plugins button, search for "Natively", and click Install.

<figure><img src="https://docs.buildnatively.com/~gitbook/image?url=https%3A%2F%2F3352617162-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F90tV7pYflEQdiAr2VfWu%252Fuploads%252FC5rA42yQHcN1uGKFbzmF%252Fnatively_app_builder_bubble_plugin.png%3Falt%3Dmedia%26token%3Dd9706d9b-dbe8-459b-b9b3-5667648aa4b7&#x26;width=768&#x26;dpr=3&#x26;quality=100&#x26;sign=9aae2297&#x26;sv=2" alt=""><figcaption></figcaption></figure>
{% endtab %}

{% tab title="JavaScript SDK" %}
**Check SDK**

Before writing any logic, ensure the Natively SDK is correctly installed and up-to-date in your codebase.

1. Open your project's main HTML file (or header settings) and look for the Natively script tag inside the `<head>` section.
2. Install/Update: If missing or outdated, add the following code. You can specify the SDK version in the URL (e.g., `@2.26.0`).

```javascript
<head>
  <script async onload="nativelyOnLoad()" src="https://cdn.jsdelivr.net/npm/natively@2.26.0/natively-frontend.min.js"></script>
</head>
```

{% hint style="info" %}
To ensure you are using the most up-to-date version, check the [Natively GitHub releases page](https://github.com/buildnatively/js-sdk/releases) for the latest version number.
{% endhint %}
{% endtab %}

{% tab title="AI Agents" %}
**Initialize the SDK**

AI-powered editors like Lovable, Base44, and Replit use the JavaScript SDK to implement Natively features. Before implementing any feature, the Natively SDK must be initialized in your project.

Copy the line below and paste it into your AI agent to check and set up the Natively SDK in your project.

```
Check if the following Natively SDK script is present in the <head> of index.html. If missing or outdated, add it: <script async onload="nativelyOnLoad()" src="https://cdn.jsdelivr.net/npm/natively@2.26.0/natively-frontend.min.js"></script><script>function nativelyOnLoad() { window.natively.setDebug(true); console.log("✅ Natively SDK loaded successfully."); }</script> For reference: https://docs.buildnatively.com/guides/integration/how-to-get-started https://github.com/buildnatively/js-sdk/releases
```

{% endtab %}
{% endtabs %}

### Setup Logic

{% tabs %}
{% tab title="Bubble.io Plugin" %}

#### \[Element] Natively - Biometrics

{% hint style="info" %}
On initialization, the element automatically checks if the user has stored credentials for your app's hostname. The result is available in the **User has stored credentials** state.
{% endhint %}

#### Events:

* **User's identity verified** - fires when biometric authentication succeeds.
* **User's identity verification failed** - fires when biometric authentication fails.
* **User's credentials received** - fires when credentials are successfully retrieved after biometric verification.
* **User's credentials not received** - fires when credentials could not be retrieved after biometric verification.
* **User's credentials saved** - fires when credentials are successfully saved after biometric verification.
* **User's credentials removed** - fires when credentials are successfully removed from the device.
* **Biometrics supported** - fires when **Check biometrics support** completes, and the device supports biometrics.
* **Biometrics not supported** - fires when **Check biometrics support** completes, and the device does not support biometrics.

#### States:

* **User's login after biometric authentication.** - the stored username/login(can be anything you're using for authentication) retrieved after successful biometric authentication.
* **User's password after biometric authentication** - the stored password retrieved after successful biometric authentication.
* **User's device supports biometrics.** - Yes/No. Whether the device supports biometric authentication.
* **User has stored credentials.** - Yes/No. Whether credentials for this app are already stored on the device.

#### Actions:

* **Check biometrics support** - checks whether the device supports biometric authentication:
  * `allow_passcode` - Yes/No. Allows users without Face ID/Touch ID to use the device passcode as a fallback.
* **Verify user's identity** - triggers native biometric authentication to confirm the user's identity:
  * `allow_passcode` - Yes/No. Allows users without Face ID/Touch ID to use the device passcode as a fallback.
* **Get user's credentials** - triggers biometric authentication and retrieves stored credentials on success:
  * `allow_passcode` - Yes/No. Allows users without Face ID/Touch ID to use the device passcode as a fallback.
* **Save user's credentials** - triggers biometric authentication and saves credentials on success:
  * `login` - the username or email to store (can be any text);
  * `password` -  the password to store (can be any text);
  * `allow_passcode` - Yes/No. Allows users without Face ID/Touch ID to use the device passcode as a fallback.
* **Remove user's credentials** - removes stored credentials from the device. No biometric authentication required.
* **Clear user's credentials from element** - clears credentials from the element state; call this after **Get user's credentials**.
  {% endtab %}

{% tab title="JavaScript SDK" %}

```javascript
// ============================================================================
// NATIVELY BIOMETRICS & CREDENTIALS - DOCUMENTATION & EXAMPLES
// ============================================================================

// Initialize
// allowPasscode: boolean — allows users without Face ID/Touch ID to use
// the device passcode as a fallback for biometric authentication
const allowPasscode = true;
const biometrics = new NativelyBiometrics(allowPasscode);

// ============================================================================
// ALL AVAILABLE METHODS
// ============================================================================
// biometrics.checkBiometricsSupport(callback)
//   - Checks whether the device supports biometric authentication.
//   - resp.status: true / false
//
// biometrics.checkCredentials(callback)
//   - Checks whether credentials are already stored for this app's hostname.
//   - resp.status: true / false
//
// biometrics.verifyUserIdentify(callback)
//   - Triggers native biometric authentication to verify the user's identity.
//   - Does not retrieve or save credentials.
//   - resp.status: true / false
//
// biometrics.getUserCredentials(callback)
//   - Triggers biometric authentication and retrieves stored credentials on success.
//   - resp.status: "SUCCESS_BIOMETRICS" / "FAILED_BIOMETRICS" / "FAILED_OBTAIN"
//   - resp.username: the stored username
//   - resp.password: the stored password
//
// biometrics.saveUserCredentials(username, password, callback)
//   - Triggers biometric authentication and saves the provided credentials on success.
//   - username: string — the username to store
//   - password: string — the password to store
//   - resp.status: "SUCCESS_SAVE" / "FAILED_BIOMETRICS"
//
// biometrics.removeUserCredentials(callback)
//   - Removes stored credentials from the device. No biometric authentication required.
//   - resp.status: always "success" regardless of whether credentials existed.

// --- Biometrics. Check Support Example. Start ---

const check_support_callback = function(resp) {
    if (resp.status) {
        console.log("Biometrics supported");
    } else {
        console.log("Biometrics not supported");
    }
};

biometrics.checkBiometricsSupport(check_support_callback);

// --- Biometrics. Check Support Example. End ---


// --- Biometrics. Check Credentials Example. Start ---

const check_credentials_callback = function(resp) {
    if (resp.status) {
        console.log("Credentials exist for this app");
    } else {
        console.log("No credentials stored");
    }
};

biometrics.checkCredentials(check_credentials_callback);

// --- Biometrics. Check Credentials Example. End ---


// --- Biometrics. Verify Identity Example. Start ---

const verify_identity_callback = function(resp) {
    if (resp.status) {
        console.log("Identity verified");
    } else {
        console.log("Verification failed");
    }
};

biometrics.verifyUserIdentify(verify_identity_callback);

// --- Biometrics. Verify Identity Example. End ---


// --- Biometrics. Get Credentials Example. Start ---

const get_credentials_callback = function(resp) {
    if (resp.status === "SUCCESS_BIOMETRICS") {
        console.log("Username:", resp.username);
        console.log("Password:", resp.password);
    } else {
        console.log("Failed to get credentials:", resp.status);
    }
};

biometrics.getUserCredentials(get_credentials_callback);

// --- Biometrics. Get Credentials Example. End ---


// --- Biometrics. Save Credentials Example. Start ---

const username = "user@example.com";
const password = "securepassword";

const save_credentials_callback = function(resp) {
    if (resp.status === "SUCCESS_SAVE") {
        console.log("Credentials saved successfully");
    } else {
        console.log("Failed to save credentials:", resp.status);
    }
};

biometrics.saveUserCredentials(username, password, save_credentials_callback);

// --- Biometrics. Save Credentials Example. End ---


// --- Biometrics. Remove Credentials Example. Start ---

const remove_credentials_callback = function(resp) {
    console.log("Credentials removed");
};

biometrics.removeUserCredentials(remove_credentials_callback);

// --- Biometrics. Remove Credentials Example. End ---
```

{% endtab %}

{% tab title="AI Agents" %}
AI-powered editors like Lovable, Base44, and Replit use the JavaScript SDK to implement Natively features.&#x20;

Copy the line below and paste it into your AI agent.&#x20;

<pre><code>[<a data-footnote-ref href="#user-content-fn-1">Your feature description</a>] using the Natively Biometrics &#x26; Credentials SDK: const biometrics = new NativelyBiometrics(allowPasscode); // allowPasscode: boolean — true allows device passcode as fallback when Face ID/Touch ID unavailable. // biometrics.checkBiometricsSupport(callback) — resp.status: true/false. // biometrics.checkCredentials(callback) — resp.status: true/false (whether credentials exist for this app). // biometrics.verifyUserIdentify(callback) — resp.status: true/false. // biometrics.getUserCredentials(callback) — resp.status: "SUCCESS_BIOMETRICS"/"FAILED_BIOMETRICS"/"FAILED_OBTAIN". resp.username, resp.password. // biometrics.saveUserCredentials(username, password, callback) — resp.status: "SUCCESS_SAVE"/"FAILED_BIOMETRICS". // biometrics.removeUserCredentials(callback) — resp.status: always "success". For reference: https://docs.buildnatively.com/guides/integration/biometrics-and-credentials
</code></pre>

{% hint style="warning" %}
Replace the placeholder at the beginning with a description of what you want to build - for example: "Add biometric login so returning users can sign in with Face ID or Touch ID instead of entering their password every time".
{% endhint %}
{% endtab %}
{% endtabs %}

### How to use

#### Check biometrics support before showing the option

Always call `checkBiometricsSupport` first to verify the device supports biometrics before showing a biometric login option. If the device doesn't support it, fall back to your standard login flow.

#### Check for stored credentials on app load

Call `checkCredentials` when the app loads to determine if the user has previously saved credentials. If credentials exist, you can offer a "Sign in with biometrics" button instead of showing the full login form.

#### Save credentials after a successful login

The right moment to save credentials is immediately after a successful standard login (email + password). Prompt the user to enable biometric login for next time - for example, with a checkbox or a prompt saying "Use Face ID for next login?". Update the stored credentials each time the user changes their password.

#### Use `verifyUserIdentity` for sensitive actions

Use `verifyUserIdentity` when you need to confirm the user's identity before a sensitive action - like viewing payment details, confirming a purchase, or accessing private data - without needing to retrieve stored credentials.

#### Always provide a fallback

Not all users have or want biometrics. Set `allowPasscode` to `true` to allow the device passcode as a fallback. Also give users the option to skip biometric login entirely and use their standard credentials instead.

#### Give users control over their credentials

Always provide a way for users to remove their stored credentials - for example, in your app's account settings. Call `removeUserCredentials` when the user signs out or disables biometric login.

#### Credentials are tied to the hostname

Stored credentials are linked to your app's hostname, not a specific user. If multiple users share a device, saving new credentials will overwrite the previously stored ones.

## Troubleshooting

<details>

<summary>Biometrics not triggering</summary>

Make sure the feature is triggered from a user interaction - like a button tap - rather than automatically on page load. Also verify the SDK is fully loaded before calling any biometric methods.

</details>

<details>

<summary><code>checkBiometricsSupport</code> returns <code>false</code></summary>

The device does not support biometric authentication, or the user has not enrolled any biometrics (no Face ID or fingerprint set up). Set `allowPasscode` to `true` to allow the device passcode as a fallback, or fall back to your standard login flow.

</details>

<details>

<summary><code>checkCredentials</code> returns <code>false</code> after saving</summary>

Credentials are tied to your app's hostname. If you're testing on a different domain or subdomain than production, the stored credentials won't be found. Make sure you're testing on the same hostname where credentials were saved.

</details>

<details>

<summary><code>getUserCredentials</code> returns <code>FAILED_OBTAIN</code></summary>

Credentials were not found for the current hostname or were removed from the device. Call `checkCredentials` first to verify credentials exist before attempting to retrieve them.

</details>

<details>

<summary>Biometric prompt not appearing on Android</summary>

The device may not have biometrics enrolled. Android requires the user to have set up fingerprint or face unlock in their device settings. If `allowPasscode` is `true`, the device PIN should appear as a fallback.

</details>

<details>

<summary>Credentials not persisting between app sessions</summary>

Make sure `saveUserCredentials` completed successfully before closing the app - check for `SUCCESS_SAVE` (iOS) or `true` (Android) in the callback. On Android, credentials are stored in private Local Storage, so clearing the app's data will remove them.

</details>

<details>

<summary>Multiple users on the same device</summary>

Credentials are tied to the hostname, not to a specific user account. If a second user saves credentials on the same device, they will overwrite the first user's stored credentials. Warn users about this if your app supports multiple accounts.

</details>

[^1]: Replace this placeholder
