Login and access
Who can sign in and what they can see
Most apps need accounts. People sign up, log in, and expect to see only their own data. This page explains how login works and how to add it with Supabase Auth.
What is authentication?
Think of a hotel. At the front desk, you show your ID and get a key card. That is authentication: proving who you are. Your key card only opens your own room. That is authorization: deciding what you are allowed to do.
Your app needs both:
- Sign up creates a new account with an email and password
- Log in proves who you are and starts a session (the app remembers you are logged in)
- Log out ends the session
- Roles decide what you can do, for example
useroradmin
Supabase Auth is the login system built into Supabase. It stores passwords safely, so you never handle them yourself.
Turning on email login
First, check that email login is on in Supabase:
- Open your project in the Supabase dashboard
- Go to Authentication, then look for Sign In / Providers
- Make sure Email is enabled
Adding sign up, log in, and log out
Start your coding agent in your project folder and switch to plan mode. Then give it a clear prompt. For example, for a habit tracker app:
Add email and password login to this app using Supabase Auth.
- Create a /signup page and a /login page with simple, friendly forms.
- Show clear error messages (wrong password, email already used).
- Add a "Log out" button in the header when someone is logged in.
- Show "Log in" and "Sign up" links in the header when nobody is logged in.
- After login, send the user back to the page they came from.
- Use the existing Supabase client. Do not put any secret keys in frontend code.
Show me the plan first. Do not edit files yet.Let's break this down:
- Each bullet is one small, testable behavior
- "Use the existing Supabase client" stops it from creating a second, messy setup
- "Show me the plan first" lets you catch mistakes before any code changes
Read the plan. If it looks right, leave plan mode and say "Go ahead". When it works, ask the agent to commit your changes.
Adding roles with a profiles table
Supabase Auth knows your email, but not your role. So apps usually keep a profiles table with one row per user. Each row has the user's id, their name, and a role.
Make sure this app has a profiles table in Supabase:
- id (same as the Supabase Auth user id), full_name, role, created_at
- role is either 'user' or 'admin', and defaults to 'user'
- When a new user signs up, create their profile row automatically.
Give me the SQL to run in the Supabase SQL Editor, and explain each part in plain English.Paste the SQL into the SQL Editor in Supabase and run it. To make yourself an admin, open the profiles table in the Table Editor and change your own role to admin.
Protecting pages
Some pages should only open for logged-in users, like a dashboard or account settings. A protected page sends visitors to the login page if they are not logged in.
Protect these pages so only logged-in users can open them:
[list your private pages, for example /dashboard and /settings].
If someone is not logged in, redirect them to /login and bring them back after they log in.
Do the check on the server side, not only in the browser.Row Level Security per user
Hiding a page is not enough. A clever user could still ask the database directly. Row Level Security (RLS) is a set of rules inside the database itself. It is like a filing cabinet that only opens the drawers with your name on them.
The usual pattern: every private table has a user_id column, and the rule says "you can only touch rows where user_id is you".
Turn on Row Level Security for every table and add policies:
- habits and check_ins: users can only read and write rows where user_id is their own id.
- profiles: users can read and update only their own row. Users must not be able to change their own role.
- Public content: anyone can read; only admins can insert, update, or delete.
Give me the SQL and explain each policy in one sentence.| Feature | Visitor | User | Admin |
|---|---|---|---|
| public content (read) | Yes | Yes | Yes |
| public content (edit) | No | No | Yes |
| own private data | No | Yes | Yes |
| other people's data | No | No | Only if a policy allows |
Testing with two accounts
The only way to trust your rules is to try to break them. Use two accounts:
- Sign up as Account A in your normal browser window. Create some data, like a habit.
- Open a private (incognito) window. Sign up as Account B.
- Check that Account B does not see Account A's data.
- Log out and try to open a protected page. You should land on the login page.
Tip: many email services let you add +test to your address (like you+a@example.com) to make extra test accounts.
Common mistakes
Only hiding buttons
Wrong: "Hide the admin link if the user is not an admin."
Right: "Hide the admin link AND block non-admins on the server AND in RLS policies."Letting users change their own role
Wrong: profiles policy "users can update their own row" (all columns)
Right: users can update their name, but never the role column- Testing with only one account, so you never notice data leaking between users
- Putting the Supabase service_role key in frontend code to "fix" a permission error
Practice
Try these exercises to lock in what you just learned.
What's next?
People can now log in and keep their data private. Next, let's learn how to take payments safely with Stripe.