# Authentication vs authorization

Source: https://www.plutonapps.com/resources/authentication-vs-authorization

Published 2026-09-30, updated 2026-10-24, sources checked 2026-10-24. By Irfan Habib (https://www.plutonapps.com/authors/irfan-habib).

**Authentication vs authorization:** Authentication is proving who someone is, by password, one-time code or Google sign-in, while authorization is deciding what that signed-in person is allowed to do, such as which records they may read or change. Authentication happens once per session; authorization is checked on every request.

Also known as: AuthN vs AuthZ.

Two words that sound alike and fail differently. Most AI-built apps have the first and are missing half of the second.

## Why do AI-built apps get authentication right but not authorization?

Sign-in is the part everyone sees, so it is the part AI builders get right: add a provider, and users can log in. Authorization is invisible when it works and invisible when it is missing, because the interface only shows each person their own things. The data layer may still answer anyone who asks for someone else's.

|  | Authentication | Authorization |
| --- | --- | --- |
| Question | Who are you? | What may you do? |
| Example | Signing in with Google | Only editing your own invoices |
| Where it is enforced | The sign-in provider, such as Clerk | Your server and database, on every request |
| When it fails | Strangers get in | Signed-in users reach other people's data |

The second failure is the common one. Broken access control is first on the OWASP Top 10:2025.

## How does an authorization check actually work on each request?

Every request carries proof of who is asking, usually a session token. The server or database reads that identity, looks at the record being asked for, and decides yes or no for that one object. OWASP's guidance is to deny by default and to check permissions on every request, not just when a page loads.

A concrete example: an invoice app loads /invoices/42. Authentication says the request comes from user A. Authorization asks whether invoice 42 belongs to user A. OWASP warns that a hidden or hard-to-guess id is no protection. If the check is missing, user A can change 42 to 43 and read user B's invoice.

## How is authorization enforced in a Lovable or Supabase app?

In a Supabase app, authorization usually lives in [row-level security](https://www.plutonapps.com/resources/what-is-row-level-security) policies. Each policy acts like a WHERE clause added to every query on its table. A policy such as auth.uid() = user_id limits each signed-in user to their own rows, because auth.uid() returns the id of the user making the request.

- Enable RLS on every table in an exposed schema. Supabase warns that a table without it is readable and writable by any role with a grant on it.
- Name the role in each policy, for example to authenticated, so it does not run for anonymous visitors.
- Add an explicit auth.uid() is not null check. For a signed-out request auth.uid() returns null, and Supabase recommends saying what you mean.
- Keep the secret key on the server. It uses a role that bypasses RLS.

Lovable's quick security scan, which runs when you publish, flags tables without per-record access control and rules that let everyone through. Its own docs say the tools cannot guarantee complete security. Our [Lovable security checklist](https://www.plutonapps.com/guides/lovable-security-checklist) walks through the rest, and the [production readiness check](https://www.plutonapps.com/tools/production-readiness-check) is a quick first pass on your own app.

## Frequently asked questions

### Is role-based access control authentication or authorization?

Authorization. Roles decide what a signed-in person may do; they say nothing about who that person is. Authentication happens once per session, but a role has to be checked on every request, on the server or in the database, never only by hiding buttons in the interface.

### Does Clerk or Supabase Auth handle authorization?

They tell your app who the user is and can carry roles in the session token. The rules about which data each user may touch still have to be written by you, in server code or in database policies such as Supabase row-level security, and checked on every request.

### Which comes first, authentication or authorization?

Authentication comes first, because the app cannot decide what someone may do until it knows who they are. Authorization then runs on every later request. A signed-out visitor can still be authorized for public data, which Supabase treats as requests from its anon role.

### What happens when authorization is missing but authentication works?

Strangers cannot sign in, but any signed-in user can reach data that is not theirs, often by changing an id in a request. OWASP calls this broken access control and ranks it first in its Top 10:2025. The interface looks fine, so it usually goes unnoticed.

## Read next

- [The Bell case study: the database refuses any send no person approved](https://www.plutonapps.com/work/bell)

## Sources

- [OWASP Top 10:2025 (A01 Broken Access Control)](https://top10.owasp.org/2025)
- [OWASP: Access control](https://owasp.org/www-community/Access_Control)
- [OWASP Authorization Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Authorization_Cheat_Sheet.html)
- [Supabase docs: Row Level Security](https://supabase.com/docs/guides/database/postgres/row-level-security)
- [Lovable docs: Security](https://docs.lovable.dev/features/security)
