Skip to content
Back to the Bootcamp
The Momentum Bubble Bootcamp, free. Part 7 of the paid course that trained hundreds of Bubble developers — released free, because the thinking it teaches is exactly what great AI-assisted development is built on.

Bootcamp

Sign up, log in and the security container: Bubble account workflows

Authentication is the first thing every real app needs and the worst place to improvise. The good news is that in Bubble you shouldn’t build any of the hard parts yourself: the platform ships account workflows that enforce good security practice by default, and the screens around them are so standard that, built well once, they can move into every future project. This is that once.

The User is a special data type in every Bubble app: it cannot be deleted, it ships with email, email-confirmed and password fields, and the password can never be viewed by anyone, not even the developer. Every account workflow in Bubble is built around it.

The User: a data type you can’t delete

The User identifies the person (strictly, the browser) accessing your app, and it’s how you control access to data and features. You’ll find it on the Data tab with its default fields, and you extend it like any other type: common additions are a role, an account (for SaaS apps where several users share one), or a company. People will use your app in two states, logged out, where they’re effectively an anonymous member of the public, and logged in, where you know who they are. To identify someone, they must create an account.

Bubble’s account actions fall into three tiers. The bread and butter, which we’ll implement below: sign the user up, log the user in, log the user out, update the user’s credentials (change email or password), send a confirmation email and send a password reset email. Then some useful extras: sign up or log in with a social network (Google, Facebook or another OAuth provider), send a magic login link for apps where forgetting a password shouldn’t matter, and make changes to the current user. Finally the administrator tier, for super-user roles managing other accounts: create an account for someone else, assign a temporary password, change another user’s email, or log a user out of all sessions.

What makes these worth using rather than working around is that they enforce security:

  • Once saved, nobody can access a user’s password. You can validate it at creation time; after that it’s gone from view forever.
  • A user must supply their current password to update their credentials, so someone at an unlocked computer can’t quietly change the account’s email or password.
  • A password can only be reset via a tokenised link sent to the account’s email address. No email access, no reset.

And they encourage security through choices you configure. You decide whether sign-up requires an email confirmation (worthwhile for free products where throwaway accounts are a risk; it also catches typos in addresses, the cause of a surprising share of “my login doesn’t work” messages). You decide whether to require a password confirmation field. In Settings, on the General tab, you can define a password policy: minimum length, require a number, a capital letter, a non-alphanumeric character. Modern minimums keep climbing because complexity is what makes brute-forcing impractical. The same area covers redirecting users whose passwords have expired, and basic two-factor authentication (fully integrated 2FA needs Bubble’s Growth plan or higher; note the industry has moved from SMS codes toward authenticator apps, as SMS is now considered interceptable).

Current User and the security container

Current User is the dynamic expression referencing whoever is using the app right now, and it exposes every field on their User record: Current User's email, Current User's company, and so on. It’s essential for security and wonderfully easy to reference. Its limit is that it only ever points at one person. When you need other users’ data, you search instead, and often combine the two: Do a search for Orders: company = Current User's company finds orders placed by anyone in the same company, which also covers cases like an HQ user acting on behalf of someone else.

One naming trap: in a search result, Bubble calls each returned user this user. Current User is always the person using the app at this moment; this user is whichever user a search returned, who may or may not be the same person. Keeping those straight matters once privacy rules arrive in a later module.

The first practical use of Current User is the security container, the simplest way to stop logged-out visitors seeing a protected page:

  1. On a protected page (our CRM’s contacts page), take the outermost group holding everything, header included, and rename it Group Security Container.
  2. In its Layout tab, untick “This element is visible on page load” and tick collapse when hidden.
  3. Add a conditional: When Current User is logged in, this element is visible.
  4. Add one page workflow: when the user is logged out, Go to page... auth. The container means they’d see nothing anyway; the redirect means they don’t sit on an empty page.

Test it in preview with debug_mode=true: inspect the container while logged in and the condition evaluates yes; log out, load the page again, and nothing renders before the redirect fires. The same pattern extends to roles later: When Current User's role is admin, this element is visible.

Build the sign-up form

Now the auth screen. Working from the Figma design, the sign-up group needs an email field, a password field and a continue button.

  1. Don’t rebuild inputs you already have. Copy an existing email field group from another page, selecting the whole parent group rather than the input, and paste it twice into the sign-up group.
  2. Naming conventions matter here because this page will end up with three email fields (sign up, log in, forgot password). Rename the first pair Group Email Sign Up / Input Email Sign Up, and the second Group Password Sign Up / Input Password Sign Up, changing its label text to Password.
  3. Set Input Password Sign Up’s content format to Password. A pasted email field still expects an email; once changed, the input obscures its characters (the value is still inspectable in debug mode, just hidden on screen).
  4. Turn on the password policy in Settings, then tick check the password while typing on the password input. In preview, “hello” fails validation and stays red; add a capital, a number and a punctuation character and it passes live as you type.
  5. Add a Continue button, full width, 40px high, with your design system’s spacing (16px gaps within the field stack, 40px above the button).
  6. Now the workflow. On Continue, add Account, Sign the user up. Set email to Input Email Sign Up's value and password to Input Password Sign Up's value. Leave password confirmation off (a second password input can feed it if your design wants one), and tick send an email to confirm the email, choosing a confirmation page. “Remember the email” makes the browser prefill it next time; you can drive it from an “is this a private computer?” checkbox.
  7. Follow with Reset relevant inputs, then Go to page (same page) with a parameter like form=confirm-email, so the auth screen switches to its confirmation state.
  8. Build the confirmation landing page itself: a simple page saying “Your email is confirmed” with a Continue button that goes to the contacts page when Current User is logged in. When the user clicks the link in their email, Bubble appends a token to this page’s URL, confirms the address and drops the token.

Preview it, press Continue, and the new user appears in the database. Two testing notes: signing up also logs you in immediately, and since Bubble rejects duplicate emails, use plus addressing while testing (you+1@gmail.com): Bubble treats each as a distinct account while Gmail delivers them all to your inbox.

Log in, log out and resending the confirmation

The login form is the same shape, so borrow everything from sign up and rename it: Group Email Login, Input Email Login, Input Password Login, and the buttons Button Continue Login / Button Continue Sign Up so they can’t be confused.

  1. On the login Continue button: Account, Log the user in, with email and password from the login inputs. The stay logged in checkbox controls session length: checked keeps the user signed in for 365 days, unchecked boots them after 24 hours.
  2. Add Reset relevant inputs, then Go to page contacts. No parameters needed.
  3. Log out lives in the navigation drawer: on the logout element, Log the user out, then Go to page auth.

The confirm-email state of the auth screen deserves three small touches. Display the address you sent to with Current User's email inside the text element (use the rich text editor to underline it, matching the design). Wire the Resend email button to the send a confirmation email action, pointing at the same landing page, followed by a toast alert: “Confirmation email sent”. And give the escape hatches somewhere to go: Close returns to the login state, and “the email address is incorrect” returns to sign up.

Forgot password and the reset page

  1. Build the forgot-password state from borrowed parts: one email field (Group Email Forgot / Input Email Forgot) and a Reset password button.
  2. On the button: Send password reset email with the input’s value. You can customise the email text, or take the token and send your own email.
  3. Add a toast that says: “If there is an account for this email, password reset instructions have been sent.” The phrasing is deliberate: you never confirm whether an account exists, which stops the form being used to probe for registered addresses.
  4. Reset relevant inputs, as users expect a submitted form to clear.
  5. Style the reset_pw page. This is one of Bubble’s mandatory pages (you can’t delete it), but you can restyle it completely: copy your auth page’s container settings and background across, then give it a password input, an Input Password Confirm beneath it, and a Change password button.
  6. Resetting the password also logs the user in, because the emailed token has authenticated them. So finish the reset workflow with Go to page contacts and land them straight in the app.

The settings screen: change email and password

Users who still know their password change their details in settings, which uses a different action from the forgot-password flow.

  1. Create a settings page cloned from contacts, borrow the breadcrumbs from the contact page, and strip out the table. Build a row per credential: a label (“Email address”) above Current User's email in body-medium text on the left, a tertiary Change button on the right, the row set to space-between with a 1px grey bottom border, max width 560. Duplicate it for Password, displaying dots (nobody knows the real length). Note Current User is correct here precisely because users edit themselves; an admin screen editing someone else would need this user from a search instead.
  2. Build the change-email form in a group below: an input for the new email, an input for the current password (Input Current Password Email), and Cancel / Save changes buttons, fit to content, in a 16px row. Set the form group to not visible on page load, and both it and the display row to collapse when hidden.
  3. Rather than writing show/hide logic three times, create a custom event called toggle email inputs whose actions toggle the form group and the display row, then trigger it from all three buttons: Change, Cancel and Save changes. One workflow, three triggers.
  4. The Save changes workflow uses Account, Update the user’s credentials. Supply the old password as Input Current Password Email's value (this is mandatory, and it’s what authorises the change), tick change email, and set it to the new email input’s value. The same action can change the password at the same time, but keep this one to email only.
  5. Finish with a toast (“Your account has been successfully updated”) and reset the inputs after the credential change has used their values.

Then make the change-password section yourself: it’s the same Update the user's credentials action ticking change password instead, with old password, new password and an optional confirmation field as the design shows.

One last behaviour worth knowing: Bubble creates a temporary user for every logged-out visitor. You can’t see these in the database, their data lives for 72 hours, and Current User works on them even logged out. If the visitor later signs up, everything the temporary user created is assigned to the new account, exactly what guest checkout and other act-first, register-later flows need.

This skill in the AI era

The lesson underneath this build is “don’t reinvent the wheel”: authentication is a solved problem, and the developer’s job is wiring the solved version in correctly, understanding which guarantees it enforces and which choices it leaves to you. That instinct transfers directly to AI-assisted development, where Claude Code will happily scaffold auth against a modern provider in minutes, and the person directing it still has to know about confirmation flows, password policy, session length and never revealing whether an account exists. That judgement is what we bring to every project when we build production apps with AI in Sydney, and it’s a recurring theme in how Bubble fundamentals map onto AI coding.

If this sparked something, let's talk.

No pitch, no pressure — just a conversation about what you're working on.

Let's talk
Share: