# Function-Level Access and CORS — OWASP Top 10

Source: https://www.skillbyai.com/en/owasp-top-10/a-function

> Roles, admin routes and cross-origin rules.

## Enforce roles on the server

Hiding an admin button in the UI does not protect the admin API: attackers call endpoints directly. Enforce roles and permissions on the **server** for every function, never trust role or price fields sent by the client, and protect state-changing requests against **cross-site request forgery** (SameSite cookies, CSRF tokens). **CORS** controls which other origins browsers let read your responses; misconfigurations such as reflecting any Origin while allowing credentials expose user data to malicious sites.

## Server-side role checks and a strict CORS policy

Sketch in Python and a configuration example.

```python
# VULNERABLE: role comes from the request body
if request.json.get("role") == "admin":
    delete_user(request.json["user_id"])

# FIXED: role from the server-side session/user record
@app.delete("/api/admin/users/<int:user_id>")
@login_required
def delete_user_route(user_id):
    if not current_user.has_permission("users:delete"):
        abort(403)
    delete_user(user_id)
    return "", 204

# CORS: allow-list exact origins; never echo arbitrary Origin with credentials
CORS(app, origins=["https://app.example.com"], supports_credentials=True)
```

## Test authorisation with two accounts

Automated tests that replay requests as a different or lower-privileged user catch most access control bugs.

**Quiz:** Why is hiding an admin button not enough?

- [ ] Buttons cannot be hidden
- [x] Attackers can call the API endpoint directly
- [ ] Admins need the button
- [ ] Browsers block hidden buttons

*Answer:* Attackers can call the API endpoint directly. Enforce on the server.
