The direct answer: authentication checks who someone is; authorisation checks what that person may do. If your vibe-coded app only checks that a user is signed in, it may still let them view, change or delete another customer's data. Every private server request needs a permission decision for the action and the record involved.
A simple example
Imagine your app has two customers, Alex and Sam. Alex signs in and opens their invoice at /invoices/1001. If changing the address to /invoices/1002 shows Sam's invoice, the login worked: the app knows the visitor is Alex. The permission check failed: Alex was allowed to read a record that belongs to Sam.
The same mistake can affect updates and deletion. An app may hide Sam's invoice from Alex's list, yet still accept a direct request to download, edit or delete it. This is why checking the visible screen alone is insufficient.
Where AI-built apps often get this wrong
An AI assistant may add a polished sign-in page and protect a route with “must be logged in.” That is a useful first step. Trouble starts when server code then loads a record using only an ID from the browser. The server has answered “is someone signed in?” but not “does this person have permission for this exact record and action?”
Another common pattern is to send an owner's user ID from the browser and trust it. A user can change browser input. The server should establish the caller's identity from a validated session, then apply the app's ownership or team rules to the requested record. A difficult-to-guess ID helps reduce casual discovery, but it is not a permission check.
Three permission questions for each important action
- Who is making the request? Is the session valid, and what user or service does it represent?
- What are they trying to do? Reading a record, changing it, deleting it and using an admin tool can require different permissions.
- Which record or account is involved? Does it belong to this user, a team they belong to, or a role that is explicitly allowed to act on it?
A safe default is to refuse access unless a rule clearly permits it. This applies even when a screen normally hides a button. The server must make the decision because someone can send requests without using your buttons.
Practical checks before launch
Create two ordinary test accounts with separate test records. Log in as the first account and confirm it can see its own data. Then use the second account's test record ID in a link or request while still signed in as the first. The server should refuse the access or return no record. Try read, edit, download and delete routes where they exist. Keep all tests inside accounts and data you control.
Next, test roles. An ordinary account must not reach an admin action by typing its URL or calling its API directly. A team member should see only the teams and records their role allows. If one person belongs to two organisations, check that changing the organisation ID does not silently switch the data scope.
Finally, test new and forgotten routes. Exports, file downloads, search results, background actions and mobile API endpoints can use different code paths from the main page. Ask your developer or coding assistant to list every route that reads or changes customer data, then show where each one applies the access rule.
What a convincing answer from your coding assistant looks like
Ask: “For this route, show me where the server gets the signed-in user, where it checks their permission for the requested record, and what happens when the check fails.” A strong answer points to specific code and a test with two different accounts. “The page requires login” does not answer the record-level question.
Ask for a small table of roles and allowed actions. For example, a customer may read their own invoice; a support agent may read an invoice for an assigned case; an admin may issue a refund. The rules should match the real business, not a generic “admin can do everything” assumption. Decide who grants elevated roles and how they are removed.
If the cross-account test succeeds
Stop exposing the affected route while the issue is investigated, if practical. Have a competent reviewer identify all related routes and records, fix the server-side permission rule, and repeat the two-account tests. Check logs for signs that other records were accessed, while avoiding more private data in those logs. If real customer data may have been exposed, take incident and legal advice appropriate to your situation.
This is a well-documented risk. The OWASP authorisation guide recommends denying by default and checking permissions on every request. OWASP also describes broken object-level authorisation, where changing a record identifier can expose another person's data.
How Ship Doctor helps
KHDS Ship Doctor is an evidence-led production check for vibe coders, solo builders and non-technical founders. The free builder creates a starter instruction; the £49 one-off toolkit adds reusable workflows, evidence templates and a remediation plan. Its public sample report shows how findings and unverified areas are separated. For broader launch checks, use the non-technical founder checklist and vibe coding security checklist.
Frequently asked questions
What is the difference between authentication and authorisation?
Authentication establishes who a user is. Authorisation decides whether they may perform a particular action on a particular record or feature.
Does adding login protect customer data?
It protects access to the signed-in area, but the server must still check who may access each private record and action.
How can I test permissions in an AI-built app?
Use two test accounts with separate test records. Try accessing the other account's record and admin actions while signed in as an ordinary user.
Should permission checks happen in the browser or on the server?
The server must enforce them. Browser controls help the interface, but users can change requests or call an API directly.
Check the project you actually built
Find access gaps before customers do.
Create a free starter instruction or use the complete reusable Ship Doctor toolkit.