Deny by Default: Route-Aware Authorization With c.Endpoint() in Fiber v3.6
A pull request adds GET /api/admin/export, a CSV download of every customer
record. The handler is fine, the test for the CSV format is fine, and the
reviewer approves it. Two weeks later somebody notices that the route was
registered on the api group instead of the admin group, so the only thing
it checked was a valid login. Every customer with an account could download
every other customer. Nobody wrote a wrong access rule. The route simply never
had one, and nothing in the app noticed.
This is the most ordinary way to end up in A01 of the OWASP Top 10
2025, broken
access control, whose first piece of advice is to deny by default. In a Fiber
app, "default" usually means "whatever middleware the route happens to inherit
from its group". That works until the day a route lands in the wrong place.
Fiber v3.6.0 added
c.Endpoint(), which lets global middleware see the route
that will handle a request before any handler runs. This post uses it to build a
single policy table keyed by route name, a middleware that rejects every route
the table does not mention, and a startup check that refuses to boot when the
table and the routes disagree. Everything was built and tested against Fiber
v3.6.1. c.Endpoint(),
c.Bearer() and c.SetLocal() need v3.6.0 or later, which requires Go 1.26.
