Add Authentication and Authorization Early
What it is
Two related but distinct protections every multi-user app needs: authentication (proving who a user is — login) and authorization (deciding what that user is allowed to do and see). AI-built apps often get a login screen but skip real authorization, so once you're logged in you can reach data that isn't yours.
Why it works
Authentication alone stops strangers at the door; authorization is what stops a logged-in user from walking into someone else's room. The classic vibecoding bug is checking that a user is logged in but never checking that the specific record they're requesting belongs to them — so anyone can read or edit anyone's data by changing an ID. Getting both right, early, is what makes the app safe to open to real users.
When to use it
As soon as the app has more than one user or any private data — ideally before you build the features that touch that data, so authorization is baked into every route from the start rather than retrofitted.
When not to use it
A genuinely single-user, local-only tool with no accounts and no private data doesn't need this yet. The moment it grows accounts or goes online, it does.
Prompt
Add proper authentication and authorization to this app using a well-established, mainstream auth solution — don't hand-roll it. Authentication: secure login and sessions. Authorization: every request that reads or writes data must verify the logged-in user is allowed to access that specific record. Show me where you enforce the ownership check on each protected route.Example
An app lets users save notes. Auth works — you must log in. But the note endpoint returns whatever ID you ask for, so changing /notes/123 to /notes/124 shows a stranger's note. Adding an authorization check — 'does this note belong to the current user?' — on every request closes the hole.
Advanced version
Enforce authorization at the data layer too (for example, database access rules), not only in application code, so a missed check in one route doesn't expose data. Use roles or permissions if users differ (admin vs member), and deny by default — a request is refused unless it's explicitly allowed.
Common mistakes
- Adding a login screen and assuming the app is now secure, with no per-record permission checks.
- Hand-rolling authentication instead of using a proven library, and getting the hard parts subtly wrong.
- Checking permissions only in the UI (hiding a button) while the underlying endpoint still serves anyone.