[NEW PLUGIN] BioPass - Native FaceID/TouchID & Passwordless Login (Free & Pro)

Hello Bubblers! :waving_hand:

I’m excited to launch BioPass, a native wrapper for WebAuthn that allows you to add Biometric Login (FaceID, TouchID, Windows Hello) to your Bubble apps without relying on expensive 3rd party services.

It runs directly in your app. No API calls to external auth providers.

:fire: Two versions available:

:green_circle: BioPass Free (Best for simple apps)

  • Full Biometric Registration & Login flow.

  • Client-side validation.

  • Smart error handling (No more confusing error codes for users).

Plugin Page: FREE VERSION

:red_circle: BioPass Pro (Best for SaaS / Enterprise) If you are building a serious app, the Pro version adds:

  1. :shield: Server-Side Verification: We include Node.js backend actions to cryptographically verify keys. This makes it impossible to spoof a login via frontend hacking.

  2. :sparkles: Conditional UI (Autofill): The “Magic” feature. Users click your email input, and the browser suggests “Sign in with Passkey”. Zero friction.

  3. :mobile_phone: Multi-Device Support: Let users add their iPhone, iPad, and Laptop to the same account.

Plugin Page: PRO VERSION

Happy building! :rocket:

Hey Bubblers! :waving_hand:

I am incredibly excited to announce the biggest update ever to the BioPass plugin! V2 is officially live, and it transforms Bubble authentication by bringing true, enterprise-grade FIDO2 / WebAuthn security to your apps. :shield::sparkles:

If you want to offer your users the exact same passwordless experience used by Apple, Google, and major banks (FaceID, TouchID, YubiKeys), this update is for you.

:fire: What’s New in V2?

:mobile_phone: Device Recognition (AAGUID Mapping) Have you ever wanted to show your users a list of their saved devices? BioPass V2 now reads the hardware metadata and outputs “Friendly Names”! You can now save exactly what device they used to your database:

  • :white_check_mark: Apple iCloud Keychain

  • :white_check_mark: Google Password Manager

  • :white_check_mark: Windows Hello

  • :white_check_mark: 1Password / Bitwarden

:magic_wand: Nameless Login (Discoverable Credentials) Users don’t even need to type their email anymore! Just click an empty input or a “Login with Passkey” button, and the browser will automatically prompt them with a native dropdown of their saved identities. It’s magic! :top_hat:

:locked_with_key: Bank-Level Server-Side Security We’ve completely overhauled the security architecture. BioPass V2 introduces new Server-Side Actions (Generate Secure Challenge, Verify Registration, Verify Login). The cryptographic challenges are now generated and validated 100% on the backend, making your app immune to Replay Attacks and hardware cloning (Counter validation included!).

Ready to drop passwords forever?

I’ve also updated the documentation with a step-by-step guide on how to build the perfect Backend Workflow architecture (including a neat Regex trick to instantly match credentials).

Let me know what you guys think, and feel free to drop any questions below! Happy building! :rocket::blue_heart:

Looks like a nice plugin! Platform’s listing “Web & Native mobile”. Just to confirm, does this plugin add FaceID/bio login capabilities to native mobile apps?

Hello Toby! Thank you for your feedback! I chose “Both” (Web and Mobile) not realising that the native mobile is already available to the public. For now only mobile and i will review my plugins and that’s a great idea to add on a new update! Thanks!

Hey really cool plugin! However, I think this plugin could really benefit from some more documentation, or even a youtube video. For example, in your sample app, you have some form of second datatype which seems to be tied to a specific login session, how does that work? The “counter” field of the verify login action is something i dont understand either. Also, if we set up the conditional UI action button, and then verify in back-end, how do we actually log the user in in the front-end without collection their password? I also know you included a regex extract for finding credential id however the biopass element also has a “Temp credential ID” which I suppose is that same field? Would be great with some clarifications around some of these aspects, otherwise great work here :slight_smile:

Hi Pontus! First of all thank you for your feedback!

Yeah i lack a bit in the documentation… I’ll try my best to explain.

FaceOS Element is more to check if the user is a person or to use in live cameras to count people but you can still use it to register and login.

To register with the FaceOS element:

1- You put the element and start the camera.

2- Use the action Generate Descriptor

3- When the event Descriptor Generated occurs you save the state Descriptor Output to save the JSON in you DB.

To login with the FaceOS element:

1- User inserts his email.

2- Use the action Load Face Database to load the JSONs saved in DB (this have to be changed due to security reasons)

3- With the email it will get the JSON (you have to expose that attributes to public)

4- You turn on the camera and it will return if it’s authenticated or not

5- You need to create an API to login (at the bottom)

To register with the FaceOS Biometrics:

1- Use the action Register Biometrics.

2- Once the event Biometrics Registered triggers save the Last Credential Id in the DB.

To login with the FaceOS Biometrics:

1- Use the action Authenticate Biometrics.

2- Once the event Biometrics Authenticated triggers the state Authenticated Credential ID will be filled with your information

3- You need to create an API to login (at the bottom).

Authenticate the user without changing his pass and using a magic link

1- Create your API:

To initialize you have to get your Authenticated Credential ID and paste in the Value.

2- Create a backend workflow “faceid-auth”. With this configuration:

3- Add a “Send magic login link” with the “just create link, don’t send email ticked”.

4- Finally add a “Return data from API”.

5 - In the login events when FaceOS is authenticated or when FaceOS Biometrics event Biometrics Authenticated runs the flow should be like this (in the navigation to external link should be the result of the Get Magic Link):

Why we need to do this? To be Sync, if you just call a backend workflow it will be Async and the magic link will fail.

I hope it helped,

Cheers!

thanks but i think FaceOSBiometrics is another plugin than BioPass?

I’ve figured out how to register/verify a passkey and how verify a login session. however, with a verified login session, how would i actually log the user in? when i do the “Login with Passkey” action it generates a login json that i verify in the backend but once its verified i have no way of actually logging the user in to their account in the front end, what it would seem, with your plugin. am i missing something? thanks! :slight_smile:

In case anyone wants to solve this problem in the future the approach that i took and recommend is to have your login verification happen through an api connector call directed at a backend workflow where you can return a magic login link that can be used in the front-end. you can extract the email from the login json and use that to generate a magic login link if the login verifies successfully.

Sorry I got confused! Too many plugins and also I was on my main job…

But the answer of how do you login is basically like in the post i wrote with some ajustments:

1. The New Backend API Workflow (passkey_secure_login)

In your Backend Workflows menu, create a new workflow with this exact structure:

  • Required Key/Parameter: login_json (Type: text).

  • Expose as a public API workflow

  • Ignore privacy rules

  • Response type JSON object with parameters link and error

  • Note: Do not ask for the email here. We will discover it in the next step.

Step 1: Find the passkey and the user (Data > Do a search for)

  • Do a search for User_Passkey.

  • Constraint/Filter: login_json (the parameter you received) contains This User_Passkey's Credential ID.

  • Result: Bubble will secretly scour the database and find the exact record for that passkey.

Step 2: Run your Server Action (Verify Login)

  • login_json = Parameter login_json

  • stored_public_key = Result of Step 1's Public Key

  • stored_credential_id = Result of Step 1's Credential ID

  • stored_counter = Result of Step 1's Counter

Step 3: Generate the Magic Link (Only if valid)

  • Action: Send magic login link.

  • Email: Result of Step 1's User's Email.

  • Just create link, don’t send email: :white_check_mark: CHECKED!

  • :warning: Only when: Result of Step 2 (Verify Login)'s verified is yes.

Step 4: Update the Security Counter

  • Action: Data > Make changes to a thing :right_arrow: Result of Step 1.

  • Counter = Result of Step 2's new_counter.

  • :warning: Only when: Result of Step 2's verified is yes.

Step 5: Return the response to the Front-end (Return data from API) Here is where you create the two outputs you suggested:

  • :key: link (Type: text) = Result of Step 3 (Assign a magic login link).

  • :stop_sign: error (Type: text) = Result of Step 2's error.

    • Condition Note: You can either type a custom text here (e.g., “Authentication failed”), or pass the exact error from the plugin by using the condition: Only when Result of Step 2's verified is no.

2. The API Connector Setup

In your API Connector, the call pointing to this backend workflow becomes extremely simple. It only needs to send one piece of data in the Body:

  • POST
  • URL: https://your_app.bubbleapps.io/version-test/api/1.1/wf/passkey_secure_login
  • Parameter: login_json (private unticked)
  • Use as: Action
  • Data Type: JSON

(Make sure to initialize it once with a real login_json so Bubble saves the link and error response structure).

3. The Front-end Workflow

Login screen:

  1. The user clicks “Login with Passkey” :right_arrow: Runs the plugin action Login with Passkey.

  2. The plugin triggers the login_success event.

  3. Action 1: Run the API Connector call we created above, passing This BioPass's login_json into the parameter.

  4. Action 2 (Success): Navigation > Open an external website.

    • Destination: Result of Step 1's response's link.

    • :warning: Only when: Result of Step 1's response's link is not empty.

  5. Action 3 (Error): Show an Alert/Text element on the screen displaying the error.

    • Text: Result of Step 1's response's error.

    • :warning: Only when: Result of Step 1's response's error is not empty.

I hope this helps! Cheers!

Yes…FaceOS is a bit more focused on security because you can check if the person is a human, by turning the head both sides, smile, open mouth.

It also can count people for security cameras and i added a simple face/touch id.