How to Add Login to an AI-Built App (Without Building It Yourself)
Authentication is the one feature you should never let an AI write from scratch. What 'login' actually involves, the three sensible ways to add it, and the checks that tell you whether the login your AI tool built is protecting anything at all.
Ask an AI tool to "add login" and you'll get a sign-up form, a login form, and a page that says "Welcome back." It will look finished. Whether it's secure depends on dozens of details the demo never exercises: how passwords are stored, how sessions expire, what happens on a password reset, and whether the rest of the app actually checks who's logged in.
Authentication is the one feature where "looks like it works" and "works" are furthest apart. This guide explains what's involved and how to add it without writing — or trusting an AI to write — the dangerous parts.
What "login" actually involves
A real authentication system has to handle all of this:
- Storing passwords safely — hashed with a slow, purpose-built algorithm, never stored as plain text or with a fast hash.
- Sessions — once logged in, how the app remembers you: a secure cookie or token that expires, and that can be revoked.
- Password reset — emailing a single-use, time-limited link, without revealing whether an email address has an account.
- Email verification — confirming people own the address they signed up with.
- Rate limiting — stopping someone from trying ten thousand passwords.
- Social login — "Sign in with Google," which is its own protocol with its own pitfalls.
- Account security — optionally, two-factor authentication.
Each item is easy to get almost right. Almost right is where breaches come from.
Option 1: a hosted authentication service
Services like Clerk, Auth0, Supabase Auth, Firebase Authentication, and others handle the whole list for you. You add their sign-in components or redirect to their hosted page; they manage passwords, sessions, resets, verification, social login, and two-factor.
Good for: most AI-built apps. It's the fastest path and puts the hardest security problems in the hands of a company whose entire job is solving them.
Watch for: pricing that scales per monthly active user, and some lock-in — migrating users (and their password hashes) to another provider later is possible but fiddly.
Option 2: an authentication library in your own backend
If your app has its own server, a well-maintained library handles the mechanics inside your code: Auth.js or Better Auth for JavaScript apps, Django's built-in auth, Devise for Rails, Laravel's starter kits, and similar. Users live in your own database.
Good for: apps with a real backend where you want users in your own database and no per-user fees.
Watch for: you're responsible for configuring it correctly and keeping it updated — the library does the hard parts, but the settings are yours.
Option 3: your framework's or platform's built-in auth
If your app already uses a backend platform — Supabase is the common one for AI-built apps — use its authentication. It's integrated with the database, which matters for the next section.
Option 4: write it yourself
Don't. Not because it's impossible, but because the mistakes are invisible until someone exploits them, and an AI writing it will produce something that passes every test you think to run. If an AI tool generated custom password hashing, session handling, or reset logic for your app, replace it with one of the options above.
The part everyone forgets: checking who's logged in
Here's the mistake that matters more than which option you pick. Adding login decides who someone is. Your app still has to decide what they're allowed to do — on every request, on the server.
AI-built apps commonly get this wrong in one of two ways:
1. The check only exists in the interface. The "Admin" button is hidden from normal users. But the API behind it doesn't check anything, so anyone who finds the URL can call it.
2. The app trusts IDs from the browser. A request like GET /api/invoices?userId=42 returns user 42's invoices to whoever asks. Change the number, see someone else's data.
The rule: the server works out who the user is from their session, and only returns what that user is allowed to see. Never from a user ID, role, or "isAdmin" flag the browser sent.
If your app talks to Supabase directly from the browser, that rule is enforced by row-level security policies in the database — and if they're missing, your login protects nothing. Supabase Row-Level Security Explained walks through checking them.
Test it like an attacker would
Create two test accounts, A and B. Then:
- Logged in as A, try to view B's data by changing IDs in the URL or in API requests.
- Logged in as A, try to edit or delete B's data.
- Logged out, try every page and API URL directly. Everything private should refuse.
- As a normal user, try the admin URLs and API endpoints directly.
- Log out, then press the browser's back button. Private pages shouldn't still show data.
- Request a password reset. Use the link twice — the second use should fail. Wait past the expiry and try again.
- Try logging in with the wrong password twenty times quickly. Something should slow you down.
- Ask for a reset for an email that has no account. The response shouldn't reveal that.
If any of those succeed, you've found a real problem — before a user did.
A few production details
- Use your real domain before launch. Social login and reset emails are configured with URLs. Settings made for
localhostor a preview URL break in production. (Why Does My App Work Locally but Not in Production? has the full list of these.) - Send auth emails through a real email provider. Built-in email from auth services is often heavily rate-limited and lands in spam. See How to Send Email From Your App Without Landing in Spam.
- Keep auth secrets on the server. Session secrets and API keys for the auth provider never go in frontend code. (How to Keep API Keys Out of an AI-Built App.)
The short version
- Use a hosted service or a well-maintained library. Never custom auth code.
- Every request that touches private data checks the session on the server.
- Test with two accounts and try to see each other's data.
Login is the front door. Authorisation is the locks on every room. AI tools are good at building front doors.
EasySpawn runs AI-built apps with a real backend and a managed Postgres database — the foundation server-side authorization needs — with secrets in server-side environment variables and SSL on your own domain. See how it works for AI-built apps or join the waitlist.
Related: A Security Checklist for Vibe-Coded Apps · How to Add Stripe Payments to an AI-Built App · Authentication vs Authorization · Designing a REST API That Won't Embarrass You Later · "Sign in with Google" Explained · Password Hashing Explained · Form Validation Explained
Keep reading
How to Keep API Keys Out of an AI-Built App
AI-generated code hardcodes API keys all the time — and 'put it in an environment variable' isn't enough if the variable ends up in the browser. Which keys are safe to expose, which never are, and how to fix a key that's already leaked.
Why Does My App Work Locally but Not in Production?
The app runs perfectly on your machine and breaks the moment it's deployed. It's almost always one of about a dozen causes — missing environment variables, localhost URLs, a filesystem that doesn't persist. How to find which one, in the order most likely to be it.