Skip to main content
API Security Tutorial
CHAPTER 08 Intermediate

Authorization and Access Control

Updated: May 13, 2026
20 min read

# CHAPTER 8

Authorization and Access Control

1. Introduction

Authentication proves *who* you are. Authorization determines *what* you are allowed to do. Once your API has validated a user's JWT or session, the security battle is only half won. If an authenticated user attempts to execute DELETE /api/users/99, the API must rigorously check if the user has the explicit right to delete user 99. In this chapter, we will explore Access Control logic, focusing on Role-Based Access Control (RBAC) and mitigating Broken Object Level Authorization (BOLA), the number one vulnerability in APIs today.

2. Learning Objectives

By the end of this chapter, you will be able to:
  • Clearly define Authorization logic.
  • Understand and implement Role-Based Access Control (RBAC).
  • Identify Broken Object Level Authorization (BOLA / IDOR) vulnerabilities.
  • Write secure PHP logic to verify ownership before modifying resources.
  • Apply the principle of "Least Privilege".

3. Beginner-Friendly Explanation

Imagine a high school.
  • Authentication: The security guard checks your ID badge at the front door. You are verified as a student. You are allowed inside.
  • Authorization: You walk down the hallway and try to open the door to the Principal's Office. The door is locked. Your student badge doesn't work here; you need an "Admin" badge. Furthermore, if you go to the locker room, your student badge only opens *your specific locker*, not the locker next to it.

Authorization in APIs is building the locks for the Principal's Office (Role validation) and building the locks for the individual lockers (Ownership validation).

4. Real-World Attack Scenarios

  • BOLA (Broken Object Level Authorization): A popular ridesharing app had an endpoint GET /api/receipts?receiptid=1001. A user logged in, viewed their own receipt, and noticed the ID in the URL. They changed the URL to ?receiptid=1002. Because the API failed to check if receipt 1002 *belonged* to the logged-in user, the API happily returned a stranger's ride history and credit card details.
  • Privilege Escalation: A user creates an account. They intercept the POST request and add "role": "admin" to the JSON body. The API blindly saves the data. The standard user is now an administrator and deletes the database.

5. Access Control Models

  1. 1. RBAC (Role-Based Access Control): Users are assigned roles (e.g., User, Editor, Admin). Endpoints are restricted based on these roles.
  1. 2. ABAC (Attribute-Based Access Control): More complex. Access is granted based on attributes (e.g., "Managers can only edit documents created in their specific department during business hours").

6. Vulnerable vs Secure Code Examples (BOLA/IDOR)

The most common and devastating API flaw occurs when developers trust the ID provided in the URL without checking ownership.

Vulnerable PHP (BOLA Flaw):

php
1234567891011
<?php
// 1. Authenticate user (We know who they are)
$logged_in_user_id = $_SESSION[&#039;user_id']; 

// 2. Get the ID of the document they want to delete from the URL
$doc_id_to_delete = $_GET[&#039;document_id'];

// 3. VULNERABILITY: Blindly deleting the document without checking ownership!
$db->query("DELETE FROM documents WHERE id = $doc_id_to_delete");
echo "Document deleted.";
?>

Secure PHP (Ownership Validation):

php
12345678910111213141516
<?php
$logged_in_user_id = $_SESSION[&#039;user_id'];
$doc_id_to_delete = $_GET[&#039;document_id'];

// SECURE: Enforce ownership in the SQL query itself!
$stmt = $db->prepare("DELETE FROM documents WHERE id = ? AND owner_id = ?");
$stmt->execute([$doc_id_to_delete, $logged_in_user_id]);

if ($stmt->rowCount() > 0) {
    echo "Document deleted.";
} else {
    // Return generic error (403 Forbidden or 404 Not Found)
    http_response_code(403);
    echo "You do not have permission to delete this document.";
}
?>

7. PHP Examples (Role-Based Access)

Securing an administrative endpoint.
php
12345678910111213141516
<?php
// Function to run at the top of protected API routes
function require_admin() {
    $user_role = $_SESSION[&#039;role']; // Or extracted from JWT payload
    
    if ($user_role !== &#039;admin') {
        http_response_code(403);
        echo json_encode(["error" => "Forbidden. Admin access required."]);
        exit; // Stop execution immediately!
    }
}

// Apply to endpoint
require_admin();
$db->query("DROP TABLE users"); // Only runs if admin
?>

8. The Principle of Least Privilege

Always grant the minimum level of access required to complete a task.
  • If an API key is used by a script to backup database files, that key should only have READ access, never DELETE access.
  • If a user is a "Guest", they should not have access to endpoints that modify data.

9. Best Practices

  • Never Trust the Client: The frontend UI hiding the "Delete" button is an illusion. Hackers bypass the UI. Authorization MUST be enforced on the backend.
  • Use UUIDs instead of Sequential IDs: If your API uses sequential IDs (/users/1, /users/2), it is trivial for a hacker to guess IDs and test for BOLA vulnerabilities. If you use UUIDs (/users/550e8400-e29b-41d4-a716-446655440000), they are impossible to guess, adding an extra layer of defense (though ownership checks are still mandatory).
  • Centralize Authorization Logic: Don't scatter if ($user == owner) statements throughout hundreds of files. Create a centralized middleware or function (e.g., checkownership($resourceid, $userid)) to handle it uniformly.

10. Common Mistakes

  • Confusing 401 and 403:
  • 401 Unauthorized means "I don't know who you are. Please log in."
  • 403 Forbidden means "I know who you are, but you are not allowed to do this."
  • Mass Assignment: Failing to define which fields a user is allowed to update. If your UPDATE query blindly takes all JSON data and writes it to the database, a user can update their balance or role fields.

11. Mini Exercises

  1. 1. Define the acronym RBAC.
  1. 2. If an API uses long, complex UUIDs instead of sequential numbers for user IDs, do you still need to write backend code to verify ownership? (Yes or No).

12. Practice Challenges

Challenge: Review the following vulnerable SQL query designed to fetch a user's private message based on an ID from the URL: "SELECT content FROM messages WHERE message
id = " . $GET['id'] Rewrite this query conceptually to include a check against $currentuserid to prevent a BOLA attack.

13. MCQs with Answers

Question 1

What is the difference between Authentication and Authorization?

Question 2

An attacker changes a URL from /api/invoice/10 to /api/invoice/11 and successfully downloads another user's invoice. What is this vulnerability called?

Question 3

What HTTP status code should an API return if a logged-in User attempts to access an Admin-only endpoint?

14. Interview Questions

  • Q: What is Broken Object Level Authorization (BOLA), and how is it mitigated at the code level?
  • Q: Explain Role-Based Access Control (RBAC). How would you architect this in a MySQL database?
  • Q: What is Mass Assignment, and how can it lead to Privilege Escalation?

15. FAQs

Q: Should I return a 403 Forbidden or a 404 Not Found if a user tries to access a document they don't own? A: Returning a 403 tells the attacker "This document exists, but you can't see it." In highly secure systems, it is often better to return a 404 Not Found. This hides the existence of the document entirely, preventing attackers from probing to see which IDs exist in your database.

16. Summary

In this chapter, we tackled the critical logic of Authorization. We explored Role-Based Access Control to separate Admins from Users, and tackled Broken Object Level Authorization (BOLA)—the catastrophic flaw where developers blindly trust IDs provided by the client. We learned that robust API security requires appending ownership checks (e.g., WHERE owner
id = ?) directly into our database queries, strictly enforcing the principle of least privilege.

17. Next Chapter Recommendation

We have secured the identity and the permissions. Now, we must secure the actual data the user is sending us. Proceed to Chapter 9: Input Validation and Data Sanitization to learn how to filter malicious data before it touches your database.

Finish this Chapter

Save your progress on your learning path and prepare for coding interview challenges.

Discussion

Join the discussion

Log in or create a free account to participate.

Sort: ·