What Is Authorization and How Does It Differ From Authentication in Web Applications?

Authorization is the step that decides what an already-identified user is allowed to do; authentication is the step that verifies who that user is. In practice, authentication runs first and produces an identity (a user ID, a session, or a token), and authorization then compares that identity against a policy to allow or deny a specific action. If you only need to confirm "is this person who they claim to be," you need authentication. If you need to control "can this person read this record, edit this setting, or call this endpoint," you need authorization on top of it.

Authentication vs. authorization at a glance

Question Authentication Authorization
What it answers Who are you? What are you allowed to do?
Typical inputs Credentials, OAuth callback, session cookie User identity, roles, attributes, resource
Typical outputs Verified identity, session, token Allow or deny decision
Failure signal 401 Unauthorized 403 Forbidden
Runs First After authentication succeeds

The 401 vs. 403 distinction is the fastest way to tell which layer failed. A 401 means the request had no valid identity (missing, expired, or malformed credentials). A 403 means the identity was valid but the policy said no. Debugging the wrong layer wastes time, so check the status code before touching your policy code.

Common authorization models

Role-based access control (RBAC)

Users are assigned roles (admin, editor, viewer), and roles map to permissions. It is simple to reason about and easy to cache, but it gets awkward when access depends on context, such as "editors can edit only documents they own."

Attribute-based access control (ABAC)

Decisions use attributes of the user, the resource, and the environment (department, resource owner, time of day). It is more expressive than RBAC but harder to audit because the policy is spread across many attributes.

Permission- and scope-based checks

Permissions are fine-grained actions (invoice:read, invoice:write), and scopes are the subset of permissions a client or token is granted. This is common in APIs and OAuth flows, where a token carries scopes and the API enforces them per endpoint.

Most production systems mix these: roles for coarse grouping, permissions for the actual check, and attributes for the exceptions.

Where authorization checks belong

Authorization should be enforced at the point where the action actually happens, not only in the UI.

  • API middleware / route guards: the authoritative check. Every protected endpoint verifies identity, then evaluates the policy for that route and method.
  • Token claims and sessions: roles, scopes, and claims travel with the request so the server can evaluate policy without an extra lookup. Treat these as inputs to a check, not as the check itself.
  • Client-side guards: useful for hiding UI a user cannot use, but never a security boundary. Anyone can call your API directly, so the server must re-check.

A practical rule: the client decides what to show, the server decides what to allow.

How tokens and sessions carry authorization data

Sessions and tokens commonly carry roles, scopes, or custom claims. This is convenient because the server can authorize without a database round trip, but it has limits:

  • Staleness: a role removed in the database still lives in an unexpired token. Short token lifetimes or a revocation check reduce this window.
  • Size: stuffing many permissions into a token bloats every request and can hit header limits.
  • Trust: claims are only as trustworthy as the signing and validation around them. Never accept an unsigned or unverified claim as proof of a role.

For sensitive actions, prefer a server-side lookup or a fresh policy evaluation over trusting a long-lived claim.

Troubleshooting common authorization failures

  1. 401 instead of 403 (or vice versa): confirm whether identity was established at all. If not, fix authentication first; the policy never ran.
  2. Stale roles: the user's permissions changed but the token still carries the old role. Check token lifetime and whether your system supports revocation.
  3. Privilege escalation: a user can reach an endpoint that only checks "is logged in" without checking ownership or role. Audit every protected route for an explicit policy check, not just an authentication guard.
  4. Inconsistent checks: the UI hides a button but the API allows the call. Enforce the same policy server-side that the UI assumes.
  5. Missing resource-level check: role checks pass but the user can access another user's record. Add ownership or tenant checks to the policy, not just the role.

Where SuperTokens fits

SuperTokens is an open-source user authentication product, and its site describes it as covering authentication with session management, JWT tokens, anti-CSRF, and rotating refresh tokens. Those are the mechanisms that establish identity and carry session state into your authorization checks. Authorization policy itself — roles, permissions, and resource rules — is something you define and enforce in your application, using the verified identity and session data SuperTokens provides. The site lists pricing separately, so check the pricing page for current terms rather than assuming a tier.

If you are building the access-control layer, start by writing down the actions your app exposes, who may perform each one, and where the server enforces it. That list is your authorization model; the authentication layer only tells you who is asking.

supertokens.com
Open Source User Authentication. Build fast, maintain control, with reasonable pricing.
zitadel.com
ZITADEL is the identity infrastructure platform that is built for developers and works for all users and applications.