Get featured

Add user login safely to an AI-built app

Guide · checked against the docs on

You ask your AI agent to "add login", and a few minutes later there's a sign-in page. It looks finished. But login is where an app decides who someone is and what they can see, and small mistakes there can show one user's data to another.

This guide is a checklist of 8 checks for anyone building a small web app with AI coding agents. It's quoted from OWASP, MDN, Supabase, Firebase and Auth.js docs, checked Oct 2026.

Not affiliated with or endorsed by the OWASP Foundation, Mozilla, Supabase, Google/Firebase or Auth.js. Check their current docs before relying on these details.

Keys and exposed databases are covered elsewhere. See Keep secrets safe with AI coding tools and Before you ship: lock the database, back it up, and log what happens. This guide doesn't repeat them.

Part 1: Don't start from scratch

Check 1: Use a login service or library, not home-made code

Our advice, not a vendor quote: don't build your own login. Use a managed login service or an established library, and let it handle the hard parts.

Managed services exist for this. Supabase says "Supabase Auth makes it easy to implement authentication and authorization in your app." (source) Libraries do too. As one example, Auth.js describes itself as "a runtime agnostic library based on standard Web APIs that integrates deeply with multiple modern JavaScript frameworks". (source)

Even small details are better left to tested code. OWASP says "the user-supplied password should be compared to the stored password hash using a secure password comparison function provided by the language or framework, such as the password_verify() function in PHP." (source)

Check 2: If you store passwords, hash them with a slow algorithm

If passwords end up in your own database, they must never be stored as plain text. OWASP says "they must be protected using strong, slow hashing algorithms such as Argon2id, bcrypt, or PBKDF2." It explains why: "Using slow, memory‑hard algorithms makes brute‑force attacks significantly more difficult, expensive, and time‑consuming." (source)

OWASP's settings: "To sum up our recommendations: Use Argon2id with a minimum configuration of 19 MiB of memory, an iteration count of 2, and 1 degree of parallelism." And: "For legacy systems using bcrypt, use a work factor of 10 or more and with a password limit of 72 bytes." (source)

OWASP's Top 10 lists apps that "Uses plain text, encrypted, or weakly hashed passwords data stores" as a login failure. (source) Note that "encrypted" is on that list. OWASP explains: "Since encryption is a two-way function, attackers can retrieve the original plaintext from the encrypted data." (source)

It also flags apps that "Permits default, weak, or well-known passwords, such as 'Password1' or 'admin/admin'." (source)

Part 2: The sign-in form

Check 3: Give the same error for a wrong email and a wrong password

If your form says "no account with that email", an attacker learns which emails are real. OWASP says "An application should respond (both HTTP and HTML) in a generic manner." It adds that login, password reset and password recovery "must respond with a generic error message regardless of whether" the user ID or password was wrong or the account doesn't exist. (source)

Check 4: Limit login attempts

Attackers try many passwords, or reuse leaked ones. OWASP's Top 10 warns against apps that permit "automated attacks such as credential stuffing, where the attacker has a list of valid usernames and passwords." (source)

OWASP describes the defense: "Login Throttling is a security mechanism used to prevent an attacker from making too many attempts at guessing a password through normal interactive means". It also says "The most common protection against these attacks is to implement account lockout, which prevents any more login attempts for a period after a certain number of failed logins." (source)

Our advice, not a vendor quote: this guide doesn't give numbers for limits or lockouts. Check your login service's settings to see what it already limits and what you can change.

Part 3: Staying signed in

Check 5: Lock down session cookies

After sign-in, a cookie usually keeps the user logged in. MDN explains three settings:

OWASP agrees that HttpOnly "instructs web browsers not to allow scripts" to read the cookie. (source)

Renew the session when someone signs in. OWASP says "The session ID must be renewed or regenerated by the web application after any privilege level change within the associated user session." And "The most common scenario where the session ID regeneration is mandatory is during the authentication process". (source)

Keep it out of links, too. OWASP's Top 10 lists apps that "Exposes session identifier in the URL." (source)

Check 6: Offer two-step login, and know what counts

OWASP says "Multifactor Authentication (MFA) requires evidence from at least two distinct authentication factors: something you know, something you have, and something you are." A password plus a PIN isn't MFA: "requiring multiple instances of the same authentication factor (such as needing both a password and a PIN) does not constitute MFA and offers minimal additional security." (source)

The Top 10 counts it as a failure when an app "Has missing or ineffective multi-factor authentication." (source) OWASP is honest about the cost: "The biggest disadvantage of MFA is the increase in management complexity for both administrators and end users." (source)

Part 4: Who can see what

Check 7: Tie your database to the signed-in user

Login only tells you who someone is. Your database still has to decide what they can see.

Supabase: "Auth integrates with Supabase's database features, making it easy to use Row Level Security (RLS) for authorization." (source) In those rules, "auth.uid() returns the ID of the user making the request." Supabase warns that "A table in an exposed schema without RLS is readable and writable by any role with a grant on it." Its advice: "Enable RLS on every table in an exposed schema." It also says the service_role role has "Full access. It bypasses RLS, so keep it server-side". (source) For RLS basics see lock the database, and for handling the service key see Keep secrets safe.

Firebase: Firebase's basic rules page shows this example (we haven't tried it ourselves):

// Allow only authenticated content owners access
allow read, write: if request.auth != null && request.auth.uid == userId

(source)

Watch for open rules left over from building. Firebase says "As you set up your Firebase project, you might have set your rules to allow open access during development." and warns: "If you're not authenticating users and configuring security rules, then anyone who guesses your project ID can steal, modify, or delete the data." (source)

Check 8: Check permissions on the server, every time

OWASP says "Permission should be validated correctly on every request, regardless of whether the request was initiated by an AJAX script, server-side, or any other source." And: "The application must always make a decision, whether implicitly or explicitly, to either deny or permit the requested access." (source)

Our advice, not a vendor quote: hiding a button isn't a check. Anyone can send the request the button would have sent, so the server has to check it. See How to review AI-written code for checking what your agent wrote.

Ask your agent to review your login

Give your agent a prompt like this (we haven't tried it ourselves):

Review how this app handles sign-in. Use the existing auth provider
rather than custom password code. Check that login, reset and
recovery return the same generic error, that login attempts are
limited, that session cookies are HttpOnly, Secure and SameSite and
the session is renewed at sign-in, and that every server route and
database rule checks the signed-in user (RLS with auth.uid() or
Firebase rules with request.auth). List the problems and proposed
changes before editing anything, and don't touch the live database
or any keys.

See AI agent permissions for beginners to make the agent ask before it changes anything.

Next steps

Sources

All checked Oct 2026:

Not affiliated with or endorsed by the OWASP Foundation, Mozilla, Supabase, Google/Firebase or Auth.js. Check their current docs before relying on these details.