How to custom validate a new user email


When a new user signs up it is common practice to send an email to confirm user email. The email sent contains a link (with a token). When the link is clicked user is taken to the page set up in the workflow and Bubble confirms the email address.

Because of the security issues involved, you have no control over this process. And can not manually confirm the user email in any way. You can only retrieve the information from user data type.


The sign up user experience is very important if you do not want to loose your new user right after he/she decided to join your app. This means that you should avoid as much as possible any interruption in the navigation flow. And a click on an email that takes the user to a new page is something that sometimes you do not want to happen.

This was the case while building my application. When users sign up, they have to go through 3 registration steps: personal info (name, surname, etc.), business info (company name, vat number, etc.) and data validation (mobile verification as well as email verification). The 3rd and last step it is crucial, and I wanted to provide a smooth experience to the new users in order to have them complete the sign up without any distraction.


This is the solution I implemented for my app and that I want to share with the community.

  1. in the USER data type create a text field called EMAIL CODE and a boolean filed (yes/no) called EMAIL VERIFIED. Set email verified default to NO.

  2. in the front end, design a box that shows the user email with a button (or a link) that says “click here to validate your email”

Schermata 2020-03-09 alle 16.03.08

  1. when the text underlined (click here to get your email verification code) is clicked, create a workflow (I have used some status for better management of the various conditions) with the following actions :

3.1) calculate a random string and save it in the user field EMAIL CODE

3.2) send and email to the user with the EMAIL CODE printed in the body

3.3) in the front end change the text in the box to “input here your email code” and the link text to “click here confirm the email verification code”

Schermata 2020-03-09 alle 16.08.26

3.4) the user receives the email and type the code in the box without leaving the page

Schermata 2020-03-09 alle 16.09.02

  1. when user click the text under the code in order to complete the verification, a new workflow starts (if the input code is the same as the random string saved before)

4.1) the only action required is the update of the EMAIL VERIFIED field to YES.

  1. the front end will show that the email has beed verified and the user can go on and complete the sign up

Schermata 2020-03-09 alle 16.09.10

NOTE: remember that every time you need to check if the user email has been verified, you need to control both the EMAIL VERIFIED custom field as well as the default “user’s email confirmed”. This is necessary in my case since I decided to manage this custom process but still to send a confirmation email upon sign up.

That’s all. A little tip that I hope can be useful to some of you.




Excelent approach!

Excellent work! Love it!

Thanks @stefanof,

I was wondering how I can use this when I make the account for someone else. In that case I don’t want to create a password because that would show up in the confirmation/invitation email of that user. But doing only your workflow won’t work either because they still need to log in, and therefore need a password right? Any idea?

Hi @j.poolman, this is only to validate an email or a mobile number for logged in users. I do not think it is applicable to your scenario.

1 Like


I was developing a similar system, only to realise that, since Bubble downloads the data to the browser, somebody with a little bit of knowledge could inspect the data and see what’s the code stored in the database.

Is that the case even with privacy settings? In other words, to check whether the video see equal, does Bubble load the code (even if the privacy is set to admin only or something like that?)

The thing is that if the privacy settings prevent to see the code, how are you going to check whether the code submitted by the user matches it?

I think you will need to do that checking in the server (ie, backend workflow).

1 Like

Hmm. OK. I think there may be a difference with checking a code, say, in a custom element (which likely will be exposed in the browser) and with checking, as you suggest, with a backend workflow. I will do some tests. Thanks for pointing this out.

No worries.

I think there’s definitely such difference. A custom workflow will download the data to your browser (including the code to validate against), but a backend workflow will not.

Privacy settings must be set to prevent the code from being sent to the browser, otherwise someone could sign up with any email address and verify it, even if they don’t have access.

If you do that, it means that when you check User->code, it always appears empty in the comparison.

I don’t have a paid account (yet), so can’t access backend workflows. I have tried using FLOW Single SSA (From Listpopper and Friends plugin) which I as expecting would be able to see the User->code field as it’s a server-side action… but for some reason it’s still not able to see the code.

I’m stumped - any other ways to ensure the comparison is carried out on the backend? Or do the privacy rules also apply to the backend???

Does anyone know how to prevent the email verification code from being visible by viewing the source in the browser?

It shouldn’t be visible on the client side if it’s not permitted in a privacy rule.

I haven’t actually done this yet, but what I’m planning on doing is sending the user’s verification code to a backend workflow, and having that check the code and set a “Is Email Verified” flag if it’s correct. Unfortunately, to trigger that backend workflow I’ll either have to 1) create an API workflow (then configure the API connector to connect to the bubble app itself), or (2, much easier) add another field to the User object called “Entered Verification Code”, so changes to it can trigger the backend workflow using a Database Trigger Event.

All a bit hacky, but the UX would be worth it, I feel.

To verify a code backend without having a user seeing the code:

This way of verifying will allow you to setup your own authentication system, and make it easier for users to verify their info later on if you ever need it, without needing to stay on the same page. You can disable a users access when their key is unvalidated, but they are logged in.

Create a table or “thing” called key.
Permission 1: Current user is This Key’s Creator
Permission 2: Everyone: NONE
Permission 1 setting: (Do a Search For)
resendTime, validated, created by
Permission 2 setting: EVERYONE, NOTHING


  • OTP (text)
  • resendTime (date)
  • validated: yes/no (default = no)
  • The usual Bubble defaults

The workflow:
When a user “clicks sign up”:

  1. Sign the User Up
  2. (Create this workflow API) Create/Generate a key :
  • step 1) Generate confirm code (nano id random string)
  • step 2) ( IF Current users key count is 0): creates a new “key”
    -confirm code: result of step 1
    -resend time: current date/time +seconds (30)
  • step 3) ( IF Current users key count is 1): Modify current users “key” (same properties as above)
  • step 4) ( IF STEP 1 is not emtpy) Adds new key to current user

Now here you can either return the key and get the confirmation code live to your current user right away with this being an API you use via API connector, then set it as a state or something for a user to confirm that code. This way is not preferred, cause then they would need to validate on the same page, and if they refresh, need to validate again in order for the code to sync. Follow the steps below to get a better result and allow a user to come back and confirm later if needed.

Either way you got to verify the code is legit, right?

So the user is still logged in, but their key is not verified. They still need to confirm their code.

Create an API called “check_otp_validity” in backend workflows.
code (text)

  • step 1) return data (as parameter valid=yes/no: do a search for: keys (otp=code | createdby=current user)count:1 VALID = yes
  • step 2) return data (as parameter valid=yes/no: do a search for: keys (otp=code | createdby=current user)count:0 VALID = no

Now connect this via API connector (assuming you guys can figure that out) and make it an Action or Data, whichever your workflow prefers. When this result is valid, change their key to validated = yes

This will check for validity on the backend and will not allow a user to view anything other than resend time, validated, and their “key” but only that, nothing else.

Another thing to add, is now you can setup conditions for when Current user is logged in and Current user’s key is empty go to confirm page or something. I have also added resend time to the flow to account for when a user is allowed to send a code, to prevent spam of course. You may need to figure out a way to setup some conditionals to work with that property. A hint, update the page every second with the current users date/time to match their resend time.

Hope this helps some Bubblers.


Thanks GhostCode, I like this approach although I would expect to have something out of the box from Bubble (better than the current one).

Any chance you have an example project to share?

Thanks and best,


As this was over a year ago, there may be better methods.

I still use this method to this day, until I develop a better way.

But I can try to guide you through it. Where do you need help?

Thanks, I am currently quite up to speed with Bubble and thanks very much for the help.

I was bit lazy and looking for something pre-built :wink:

Did you manage to find any better way to manage this?

Thanks so much,