API Security Authentication vs Authorization

Two words dominate API security conversations: authentication and authorization. Many people use them interchangeably, but they mean completely different things. Confusing them — or implementing one without the other — causes serious vulnerabilities.

Authentication answers the question: "Who are you?" Authorization answers the question: "What are you allowed to do?" Both checks must pass before an API grants access to any sensitive operation.

The Hotel Key Card Analogy

A hotel key card system illustrates both concepts perfectly.

At Check-In (Authentication):
  Guest presents ID and booking confirmation.
  Hotel staff verify identity: "Yes, you are Vikram Nair, you have a reservation."
  Hotel issues a key card programmed for Room 412.

At the Room Door (Authorization):
  Vikram swipes his card at Room 412.
  Door system checks: "Is this card authorized for Room 412? Yes."
  Door opens.

If Vikram tries Room 208:
  Door system checks: "Is this card authorized for Room 208? No."
  Door stays locked.

Authentication = Front desk verified WHO Vikram is.
Authorization = Door system checked WHAT Vikram can access.

Both checks are essential. The hotel would be unsafe if it issued cards without verifying identity (broken authentication). It would also be unsafe if any valid card opened any room (broken authorization).

Authentication in APIs

When a client calls an API, authentication is the process of proving that the client is who it claims to be. The API must be able to answer: "Is this request coming from a real, known entity?"

What Clients Use to Prove Identity

Three categories of authentication evidence:

Something You Know:
  - Passwords
  - PINs
  - Security question answers
  Risk: Can be guessed, phished, or leaked in data breaches

Something You Have:
  - API keys
  - OAuth tokens
  - One-time passwords from an authenticator app
  - Hardware security keys (YubiKey)
  Risk: Can be stolen if stored insecurely

Something You Are:
  - Biometric data (fingerprint, face recognition)
  Risk: Cannot be changed if compromised; privacy concerns

Strong authentication combines two or more categories — this is multi-factor authentication (MFA). An attacker who steals a password still cannot log in without the second factor.

Authentication Failure Examples

Example 1 – No Authentication:
  GET /api/admin/users
  → No token required. Anyone can call this endpoint.
  → All user records exposed to the world.

Example 2 – Weak Authentication (HTTP Basic):
  Authorization: Basic dXNlcjpwYXNzd29yZA==
  → Base64-encoded "user:password" (not encrypted, just encoded)
  → Anyone intercepting traffic can decode it instantly.

Example 3 – Expired Tokens Not Rejected:
  User logs out at 9 AM.
  Attacker stole the user's token at 8:59 AM.
  At 5 PM, attacker uses the same token.
  → API accepts it because tokens never expire.

Authorization in APIs

Once the API knows who is making a request, it must decide whether that identity is permitted to perform the requested action on the requested resource. This is authorization.

Three Levels of Authorization

Level 1 – Endpoint-Level Authorization
  "Is this user role allowed to call this endpoint at all?"

  Example:
    /api/admin/delete-user  → Only ADMIN role allowed
    /api/reports/export     → Only MANAGER or ADMIN role allowed
    /api/profile/update     → Any authenticated user allowed

Level 2 – Object-Level Authorization
  "Is this specific user allowed to access this specific resource?"

  Example:
    User Meera (ID 201) requests GET /api/orders/5501
    → Is order 5501 owned by user 201?
    → Yes → Allow
    → No  → Deny with 403 Forbidden

Level 3 – Field-Level Authorization
  "Is this user allowed to see this specific field in the response?"

  Example:
    Regular user requests GET /api/users/201
    → Can see: name, email, phone
    → Cannot see: internal_credit_score, fraud_flags, admin_notes
    → Admin requests same endpoint
    → Can see all fields including internal ones

Authorization Failure Examples

Scenario: An e-commerce API for "ShopEasy"

User types: Regular customer
Admin types: Store manager, finance team

Broken Function Level Authorization:
  Regular customer calls: DELETE /api/products/88
  → Server checks: "Is user authenticated?" Yes.
  → Server forgets to check: "Is user an admin?"
  → Product deleted by a regular customer.

Broken Object Level Authorization:
  Customer Raj (user_id 301) calls: GET /api/orders/9901
  → Order 9901 belongs to customer Sunita (user_id 302)
  → Server checks authentication but not ownership
  → Raj sees Sunita's order details, address, and payment info.

Broken Field Level Authorization (GraphQL):
  Regular user queries:
    { user(id: 301) { name salary ssn internal_rating } }
  → Server returns salary, SSN, and internal_rating
  → These fields should only be visible to HR or admin roles

The Combined Flow: Authentication Then Authorization

Every API request should pass through both gates in sequence.

API Request Processing Flow:

Incoming Request
  ↓
Step 1: Authentication Check
  Q: "Does this request carry valid credentials?"
  Valid token/key → Continue
  No token or invalid → Return 401 Unauthorized
  ↓
Step 2: Identity Extraction
  "Who is this? User ID 301, Role: customer, Plan: premium"
  ↓
Step 3: Endpoint Authorization
  Q: "Is this role allowed to call this endpoint?"
  Allowed → Continue
  Not allowed → Return 403 Forbidden
  ↓
Step 4: Object Authorization
  Q: "Does this user own or have permission to access this resource?"
  Owns it → Continue
  Does not own it → Return 403 Forbidden
  ↓
Step 5: Execute Request
  Process the business logic.
  ↓
Step 6: Filter Response
  Remove fields this role cannot see.
  Return response.

Skipping or shortcutting any step in this flow creates a vulnerability.

HTTP Status Codes for Auth Failures

Correct status codes communicate the specific type of failure. Using the wrong code confuses clients and breaks security logic.

401 Unauthorized:
  Meaning: "I don't know who you are. Please authenticate."
  When to use: No token provided, token is expired, token is invalid.
  Note: Despite the name "Unauthorized", it actually means "Unauthenticated"

403 Forbidden:
  Meaning: "I know who you are, but you cannot do this."
  When to use: Valid token, but the user lacks permission for this action.

Common mistake – returning 404 for auth failures:
  Some APIs return 404 Not Found instead of 403 Forbidden when a user
  tries to access a resource they do not own. This hides the existence
  of the resource from unauthorized users, which is sometimes intentional.
  However, consistent use of 403 is generally preferred for clarity.

Role-Based Access Control vs Attribute-Based Access Control

Two major models exist for implementing authorization. Understanding the difference helps you choose the right approach for your API.

Role-Based Access Control (RBAC)

Users are assigned roles. Roles have permissions. Simple, fast, and easy to understand.

RBAC Model for a Hospital API:

Roles:      patient, nurse, doctor, admin, billing_staff

Permissions:
  GET /api/records/{id}
    → patient (own records only), nurse, doctor, admin

  POST /api/prescriptions
    → doctor only

  GET /api/billing/{patient_id}
    → patient (own billing only), billing_staff, admin

  DELETE /api/users/{id}
    → admin only

RBAC works well for systems with clear, stable roles. It struggles when permissions need to be context-dependent — for example, "Doctor can see records of patients assigned to their ward, but not patients in other wards."

Attribute-Based Access Control (ABAC)

Permissions are granted based on attributes of the user, the resource, the action, and the environment. More flexible but more complex.

ABAC Policy Example:

ALLOW access to patient_record IF:
  user.role = "doctor"
  AND resource.assigned_doctor_id = user.id
  AND action = "read"
  AND environment.time = "business_hours"

This expresses: "Doctors can read records of their own assigned patients
during business hours." RBAC cannot express this level of specificity.

Common Authentication and Authorization Vulnerabilities

Vulnerability 1: JWT Algorithm Confusion
  JWT token specifies "alg": "none" → No signature required
  → Attacker modifies JWT payload to change their role to "admin"
  → Server accepts it because no signature is verified

Vulnerability 2: Privilege Escalation via Profile Update
  PATCH /api/users/301
  { "name": "Raj", "role": "admin" }
  → If server accepts the "role" field from clients, attacker promotes self

Vulnerability 3: Insecure Direct Object Reference
  GET /api/documents/55
  → Document 55 belongs to another user
  → API checks auth token is valid but not that user owns document 55

Vulnerability 4: Missing Authorization on Sensitive Operations
  POST /api/admin/reset-password (no auth required)
  → Anyone can reset anyone's password
  → Full account takeover without credentials

Vulnerability 5: Over-Permissive Tokens
  API key issued to a mobile app has read AND write AND delete permissions
  → If key is stolen, attacker can delete all data
  → Should have been read-only for a mobile app

Best Practices for API Authentication and Authorization

Building authentication and authorization correctly from the start saves enormous remediation effort later.

Always authenticate every request, including internal API calls between your own services. Never assume that a request originating from inside your network is safe without verifying identity.

Implement object-level authorization checks in every endpoint that accesses a specific resource. This check must use the authenticated user's identity from the verified token — never from a user-supplied parameter like user_id=301 in the request body.

Apply the principle of least privilege to all tokens, API keys, and service accounts. Grant only the minimum permissions needed for each specific use case. A mobile app that only displays data should never hold a token with delete permissions.

Log every authentication failure and authorization failure. A pattern of 403 errors against sequential resource IDs is a strong indicator of a scanning attack and should trigger an alert.

Key Points

  • Authentication asks "Who are you?" and must happen before authorization.
  • Authorization asks "What are you allowed to do?" and must happen at three levels: endpoint, object, and field.
  • A 401 status means unauthenticated (no valid identity). A 403 status means unauthorized (valid identity, insufficient permission).
  • RBAC assigns permissions to roles. ABAC assigns permissions based on multiple attributes including context.
  • The most common API vulnerabilities involve correct authentication but missing or incomplete authorization checks.
  • Always check object ownership using server-side identity, never trust a user-supplied ID in the request body for authorization decisions.

Leave a Comment