Auth & Protected Routes

Mini-project: a gated dashboard with email/password and Google sign-in.

20 min read·6 parts·intermediate

Lesson 9 gave you the map. This lesson puts the first pillar to work. By the end you'll have a gated /dashboard page that shows a login screen to strangers and a welcome to signed-in users — built entirely by talking to the agent, with no code to copy.

Auth is the pillar most builders trip on, not because it's hard, but because the mental model is fuzzy. We'll fix that first, then ship.


Part 1 · What auth actually is

Two words get muddled all the time: authentication (who are you?) and authorization (what are you allowed to do?). This lesson is about the first. The second shows up in Lesson 11 (row-level rules) and Lesson 16 (roles).

"Logged in" isn't a feeling — it's a physical thing. When a user signs in, Cloud hands the browser a small piece of text called a session token. The browser keeps it. Every time that browser asks Cloud for something, it shows the token, and Cloud looks up who it belongs to. Sign out, and the token is thrown away.

Figure 1.1
BrowserCloud (Auth)1. email + password2. session token3. every future request carries the token
The auth handshake. The browser presents credentials once, gets a token, and shows that token on every follow-up request.
Cookies vs localStorage — not your problem
Cloud picks a safe place to store the token for you. You never write that code by hand. If someone asks "are you using cookies or localStorage?" the honest answer is "whatever Cloud chose" — and that's fine.

Part 2 · The mini-project

One page, two states. Visit /dashboard while signed out and you get a login card. Sign in and the same URL shows your name, your email, and a sign-out button. That's the whole scope — small on purpose, so every moving part is visible.

Figure 2.1
yoursite.com/dashboard
Signed out
Sign in to continue
or continue with Google
yoursite.com/dashboard
Signed in
Welcome, Ahmad
ahmad@example.com
Sign out
The same route, two states. Auth is what decides which one you see.
Why so small? Because "signed in vs signed out" is the whole idea. Once you can flip between those two states reliably, every future feature — profiles, dashboards, admin panels — is just decorating that switch.

Part 3 · Email/password sign-in

Start with the classic. It's the most familiar shape for users and it forces Cloud to scaffold everything else you'll need — the users list, session storage, the auth screen. One prompt does it all.

Prompt: "Add email and password sign-in. Create a /dashboard page that shows the user's email and a sign-out button when they're signed in, and a login card when they aren't."
Figure 3.1
  1. 1Ask

    You describe the /dashboard behavior in one sentence — no talk of tables or tokens.

  2. 2Enable

    Cloud turns on if it isn't already. A users table appears; session storage is set up.

  3. 3Scaffold

    The agent adds an auth page, a login form, and the /dashboard route with both states.

  4. 4Verify

    Sign up with a test email, sign out, sign back in. The two states should swap.

The four things that happen the first time you ask for auth. You watch, you don't wire.

What Cloud created behind the scenes

  • A users table — one row per person who ever signs up. You can see it under the backend view.
  • A place to store session tokens so refreshes don't kick people out.
  • An auth page with the login and sign-up forms — you didn't have to design it.
Test with a throwaway email first
Sign up with an alias like you+test1@gmail.com before you use your real one. If you decide to reset the users table later, throwaways are less painful to lose.

Part 4 · Adding Google sign-in

Passwords are fine, but most real users don't want another one. Google sign-in is one prompt away, and for consumer apps it's usually the primary button — with email/password kept as a fallback.

Prompt: "Add Google sign-in to the auth page. Put it above the email/password form."
Figure 4.1
Email + password
Familiar to everyone. Works without a Google account. Users forget passwords — you'll need a reset flow (Part 6). Slightly higher friction: they type twice and pick a password.
Google sign-in
One click, no password to forget. Google has already verified the email, so no confirmation email is needed. Requires users to have a Google account — usually fine for consumer apps, sometimes not for enterprise.
Both methods survive in the same app. Pick which one leads based on who your users are.

What the user sees

  • They click "Continue with Google".
  • A Google consent screen appears — "YourApp wants to see your name and email". This is Google's screen, not yours; you don't design it.
  • They approve, get bounced back to your app, and land signed in on /dashboard.
Ship both, feature one
For consumer apps, put Google on top as a big button and put email/password below as "or use email". You keep the fallback without cluttering the primary path.

Part 5 · Protecting routes

There's a difference between hiding a page and protecting a page. Hiding it means you don't put a link in the header. Protecting it means someone who guesses the URL still can't see it.

Hiding a route is a UI trick. Protecting a route is a real check — every load asks Cloud "is this session still valid?" before rendering anything.
Figure 5.1
Visit/dashboardCheckSigned in?Redirect/auth?next=/dashboardSign inemail or GoogleBack/dashboardIf yes, skip straight to the page.
A protected route redirects strangers to the login page — and, importantly, remembers where they were trying to go.

Show the current user in the header

The sign-in state should be visible everywhere, not just on the protected page. A logged-in user seeing a big "Sign in" button in the header thinks your app is broken.

Prompt: "In the site header, show a 'Sign in' link when signed out, and the user's name plus a small account menu with 'Sign out' when signed in."

Ask for the real block, not the fake one

  • Fake block: "Hide the dashboard link when signed out." — the page is still reachable by typing the URL.
  • Real block: "Protect the /dashboard route so signed-out users are redirected to the auth page." — Cloud enforces it before the page loads.
  • Both, ideally. Hide it from strangers so they don't guess it exists; protect it so it doesn't matter if they do.

Part 6 · Sign-out, errors & the reset flow

Sign-out

Signing out throws away the session token and sends the user somewhere public. Ask for both in the same prompt — many beginners get the first but forget the second, and users end up staring at a dashboard they can no longer refresh.

Prompt: "When the user clicks 'Sign out', clear the session and send them to the home page."
Figure 6.1
Sign intoken issuedSessionstored in browserRefreshstill signed inSign outtoken cleared
The full session lifecycle in one loop. Refresh should keep them in; sign-out should truly kick them out.

Common error states

  • "Invalid email or password" — the classic. Never say which was wrong; that's a hint for attackers. The default message is fine.
  • "Email not confirmed" — the user signed up but never clicked the link in their inbox. Ship a "Resend confirmation email" button so they aren't stuck.
  • Rate limited — too many failed attempts. Cloud handles the limit for you; your job is to show a gentle message instead of a scary red banner.

Forgot password

The moment you ship email/password, you also ship "I forgot my password" — otherwise every user with a typo is locked out forever. This is two prompts, not one, because the reset link needs a landing page.

Prompt 1: "Add a 'Forgot password?' link on the auth page that sends a reset email."
Prompt 2: "Create a /reset-password page that lets the user set a new password when they click the link in that email."
If you only ship Google, skip the reset flow
Google users don't have a password with your app to forget — they log in through Google every time. You still need the forgot-password flow the moment you support email/password too.

Auth cheat sheet

  • Auth = who. A session token in the browser is what "signed in" physically means.
  • Ship email/password first, then add Google. Feature Google on top for consumer apps.
  • Protect the route, don't just hide the link. The URL should redirect strangers to the auth page.
  • Header must reflect state. A stale "Sign in" button for a signed-in user looks broken.
  • Sign-out clears the session AND navigates away. Ask for both in the same prompt.
  • Email/password ⇒ ship the reset flow too. Users will typo their password on day one.
  • Never tell attackers which half was wrong. "Invalid email or password" beats "wrong password".

Recap

Auth is a token the browser holds and shows on every request. Cloud does the storage, the login screens, and the checks; you describe the two states of your page and the routes that need to be behind the wall. Email/password plus Google covers almost every consumer app — with a sign-out button, a reset flow, and a header that reflects reality.

Next up, Lesson 11 turns Auth into something useful: a personal notes app where each signed-in user only sees their own rows — the first taste of the Database pillar and row-level security.