Permission must be checked on the server; hiding nav is not authorization
Aliases: security through obscurity · server-side authz
What it is
Taking an entry off the navigation only changes how easy the place is to find on the interface. It does not change whether the server will accept the operation. Hiding navigation is not authorization. Who may read and who may write must be decided again on the server for every request. Show-or-grey on the navigation is a map for legitimate users. Authorization is responsible for every path that reaches the capability: bookmarks, search, the command palette, old links, and direct calls.
Why it happens
The interface is the most visible of many channels. The same capability usually also hangs off an object address, a notification link, a share, an export endpoint. Filtering items only when drawing the navigation is turning off the lamp over the front door while the side doors stay open. Any check that trusts only the client will be walked around by another channel: a modified client, an entry cached in an old session, a script that never uses the UI. If the server assumes that because “it is not on the nav” it will not see the request, it will run the capability under the wrong identity on those channels.
Once hiding and authorization are mixed as one job, people who ship interface think “it is hidden, so it is safe”, and people who ship endpoints think “the UI will block it, so the endpoint can be loose”. When both are loose, the capability remains reachable to people who should not have it. The right split: navigation draws a map from permission; every read or write carries identity and passes authorization on its own. Failure returns a permission-related refusal, instead of protecting data by “they will not find the button”.
Where it stops holding
Copy with no request behind it (the name of a marketing module) has no authorization to speak of; hide-or-show only affects cognition. Public resources are readable by anyone; whether they sit on the navigation is unrelated to authorization. A client may still draw the interface from permission to spare taps that will fail — that is an experience optimisation, not the last gate. Debug or admin “view as this user” must still hit the server under that user’s authorization, not merely paint the navigation as if it were them.
Applying it
- Every request that reads or writes a protected object is authorized on the server under the current identity. Whether the interface hid or greyed the item is not a reason to let it through.
- Deep links, search, notifications, and the command palette share the same authorization result as the navigation; there must not be “no button, but the link works”.
- On refusal, return insufficient permission. Do not pretend the resource is missing unless leaking existence is itself unacceptable.
- How to check: as an unauthorized account, open the capability without using the navigation, via a known address or search; it should be refused. After enablement, the same address should succeed. Hidden in the UI but reachable directly means authorization was parked on the navigation. Check server logs that authorization ran on every request, not only once when the menu was drawn.
Related
- Within the group: E5.18.1 Unauthorized items may be hidden, or shown disabled with a reason · E5.18.2 Hiding entirely makes people think the function does not exist · E5.18.3 After a permission change, navigation must update rather than cache the old structure
- Adjacent: E5.14 Command Palettes · E5.05 Breadcrumbs
- Search terms:
authorization·security through obscurity·server-side permission