Lesson 5 / 25
Function-Level Access and CORS
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.
# 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.
Quick check: Why is hiding an admin button not enough?
- Buttons cannot be hidden
- 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.