API Authorization and Security

By the Syncfusion DevTutorials team · Last updated

Check on every request that the caller is allowed to do this: own the record, have the role, carry the scope.

Authorization answers one question on every request: Is this caller allowed to do this?

Authentication tells the API who is calling. Authorization decides what that caller is allowed to see or do.

A valid token proves the identity of a user, but it does not automatically grant access to every resource. The API must still check ownership, roles, and permissions before allowing an action.

Watch Asha Read Ravi's Order

The API below correctly checks that the caller has a valid token. Press Run.

Program.cs — a BOLA hole

What happens? Asha requests order 101. Order 101 belongs to Asha, so the API returns 200 OK. So far, everything looks correct.

Next, Asha changes the URL from /orders/101 to /orders/102. Order 102 belongs to Ravi. The API still returns 200 OK, and it exposes the order of Ravi. The token was valid. The API knew the caller was Asha. The problem is that the API never checked whether Asha was allowed to access order 102.

In simple words: authentication proves who the user is. Authorization checks whether they are allowed to access a specific resource.

TL;DR

  • Authentication = Who are you?
  • Authorization = What are you allowed to do?
  • Missing or invalid credentials return 401 Unauthorized.
  • Ownership, role, or permission failures return 403 Forbidden, or 404 Not Found in some cases.
  • Check authorization on every request.
  • Always verify ownership before returning or modifying data.
  • Take ownership information from the token, not from the request body.
  • Use roles and scopes to control access to features.

A Real-World Example

Imagine a hotel. At the front desk, the staff checks your identity and gives you a room key card. That is authentication.

The key card then controls which doors you can open. It opens your hotel room, the elevator, and the gym. It cannot open the rooms of other guests, staff-only rooms, or maintenance areas. Every door checks the card before opening.

Authorization works exactly the same way. A valid token identifies the user, but each endpoint must still decide whether access should be allowed.

Authentication verifies identity. Authorization checks ownership, roles, and permissions before access is granted.

What You Will Learn

In this lesson, you will learn:

  1. The difference between authentication and authorization.
  2. How ownership checks prevent data leaks.
  3. What Broken Object Level Authorization (BOLA) is.
  4. How roles control access to privileged actions.
  5. Why ownership should come from the token, not the request.
  6. How scopes restrict what a token can do.

Authentication vs Authorization

QuestionCheck
Who is calling?Authentication
Is the caller allowed to do this?Authorization
Missing token?401 Unauthorized
Valid token, but not allowed?403 Forbidden or 404 Not Found

Authentication always happens first. Authorization happens after the identity of the user is known.

Check Ownership on Every Record

The bug from the first example is called Broken Object Level Authorization (BOLA). BOLA happens when an API checks that a user is signed in, but does not check whether they own the specific resource that they asked for. It is one of the most common API security vulnerabilities.

The API must compare the owner of the resource with the user identified by the token.

The fix is straightforward:

  1. Read the user id from the token.
  2. Read the owner of the resource.
  3. Compare them.
  4. Allow access only if they match.

Program.cs — ownership check

Results:

No Token

The response is 401 Unauthorized with WWW-Authenticate: Bearer. The API does not know who the caller is.

Asha Requests Order 101

The response is 200 OK. The order belongs to Asha.

Asha Requests Order 102

The response is 404 Not Found. The order belongs to Ravi.

Why return 404 Not Found instead of 403 Forbidden? A 403 tells the caller that the resource exists. A 404 makes "not yours" and "does not exist" look exactly the same. This stops attackers from finding out which resource ids are valid.

Roles: Staff-Only Actions

Sometimes ownership is not enough. Certain actions should only be available to users with special roles. Examples are Administrator, Manager, and Support Staff.

In Brew & Bytes, refunds can only be processed by staff members.

Program.cs — admin-only refund

Customer Token

Authentication succeeds, and the user is known. However, the role is customer. The API returns 403 Forbidden.

Admin Token

The role is admin. The refund succeeds, and the API returns 200 OK.

Use a "deny by default" approach. Only users who are clearly allowed should get access. Everything else should be denied automatically.

Never Trust the Owner in the Request Body

A common mistake is allowing the caller to specify ownership information.

Example request: {"customerId": "customer-8", "item": "Latte"}

What if Asha sends the id of Ravi? If the API trusts the request body, Asha could create or change records that belong to Ravi. Instead, ownership must always come from the authenticated token.

Program.cs — owner from the token

Correct approach: Owner = token.sub. Not: Owner = request.customerId

Never trust user identity information that comes from request bodies, query strings, URLs, or form fields. Identity should always come from a validated token.

Scopes: Limit What a Token Can Do

Roles control broad access. Scopes control specific permissions.

Examples: orders:read, orders:write, payments:read, and payments:refund

Scopes allow the API to grant only the permissions that are required.

Program.cs — partner scopes

Example: the partner token contains the scope orders:read. The request GET /partner/orders succeeds. The request POST /partner/orders fails, because it requires the scope orders:write.

The API returns 403 Forbidden with WWW-Authenticate: Bearer error="insufficient_scope", scope="orders:write". The response clearly explains which permission is missing.

Authorization Policies in ASP.NET Core

Real applications often keep authorization rules in one place by using policies. Examples are StaffOnly, OrdersWrite, and ManagersOnly. Policies are easy to reuse across multiple endpoints.

Good candidates for policies are roles, claims, and scopes.

Ownership checks usually stay inside the endpoint logic, because each resource has a different owner. For example, order.CustomerId == currentUserId must be checked using the specific resource that is being accessed.

Browsers and CORS

Authorization protects your API. CORS solves a different problem. CORS tells browsers which websites may read responses from your API.

Examples: https://shop.brewandbytes.in and https://admin.brewandbytes.in

A browser may send a preflight request, OPTIONS /orders, before it sends the actual request. The API replies with the headers Access-Control-Allow-Origin, Access-Control-Allow-Methods, and Access-Control-Allow-Headers.

Program.cs — CORS for the web shop

Allowed Website

The response contains the header Access-Control-Allow-Origin. The browser allows the JavaScript code to read the response.

Unapproved Website

The response does not contain the CORS permission headers. The browser blocks access.

CORS is not a security system for your API. It only controls what browser-based JavaScript can read. Tools such as curl, Postman, mobile apps, and server-to-server calls ignore CORS completely. You still need authentication and authorization on every protected endpoint.

Where You See This

  • Banking applications only show accounts that belong to the signed-in user.
  • GitHub uses scopes to control repository access.
  • Admin dashboards use roles to restrict management features.
  • E-commerce systems verify ownership before displaying orders.
  • Security reviews test APIs with multiple users to identify BOLA vulnerabilities.

Common mistakes

SymptomCauseFix
Browser console: blocked by CORS policyThe API sends no Access-Control-Allow-Origin for the origin of that pageAdd the origin of the page to the allowed list
Users can read the orders of others by changing the idThere is no ownership check (BOLA)Compare the owner of the record with the caller from the token
Customers can refund or delete menu itemsOnly authentication is checkedAdd a role check, and return 403
Orders are saved under the wrong customerThe owner is taken from the request bodyTake the owner from the token
A 403 on a guess reveals which ids exist403 is used for the records of other peopleReturn 404 instead
A partner token can do everythingThere are no scopes, or the scopes are never checkedCheck the needed scope on each endpoint

Exercises

What to Remember

  • Authentication asks who are you? (401). Authorization asks are you allowed? (403 or 404).
  • Check ownership on every record. BOLA is the number one API risk.
  • Use 404 for records that the caller should not know about. Use 403 for actions that they may not do.
  • The owner, the user id and the role always come from the token, never from the body.
  • Give tokens only the scopes that they need, and deny by default.

Next: API Performance and Caching. You will make your API faster with caching headers, ETags and 304 Not Modified.