Module 23 / Security and operations

Module 23 · lesson 2 of 9 · Read 8 min

Authorization and OAuth

Roles, permissions, and letting another app act for a user.

Once you know who is calling, you have a second question: is this caller allowed to do this, to this thing? A customer may cancel their own order, not yours. A restaurant owner may edit their menu, not the one across the street. A support agent may refund ₹200 without asking anyone, but not ₹20,000.

That's authorization. It sounds simpler than authentication, and that's exactly why it goes wrong more often. In this lesson you'll see the bug that tops every API security list, the common ways to model permissions, and OAuth, which is how one app gets to act for a user inside another.

The bug that tops every list

Here's a real-looking Tiffin endpoint:

GET /orders/48213
Authorization: Bearer <valid customer token>

The server checks the token, finds order 48213 and returns it, with the customer's name, phone number and home address. Now the customer changes the URL to /orders/48214. The token is still valid. The order still exists. Out it comes.

This is called broken object level authorization, or an insecure direct object reference. It has been number one on the OWASP API Security Top 10 since that list started. The server checked who was calling and never checked whether this order belonged to them.

The fix is to scope every lookup by the caller:

SELECT * FROM orders
WHERE id = :order_id
  AND customer_id = :caller_id;

If nothing comes back, return 404, not 403, so you don't confirm that order 48214 exists. Random IDs like UUIDs make guessing harder, but they are not the fix. IDs leak through logs, screenshots and support tickets. The ownership check is the fix.