Course contents
On this page
Lesson 38 of 59

A valid user can still request the wrong row

Carry authorization through queries, caches, and stored copies.

Our engine now serves two shops, A and B. Each shop has an order numbered 501. A user belonging to shop A sends a request naming shop B. If the application trusts that supplied shop ID, a valid login can lead to the wrong customer’s data.

Authentication establishes identity. Authorization decides what that identity may do. The engine and application must preserve that distinction at every access path.

Bind a request to a trusted scope

Suppose the verified session establishes membership in shop A. The request asks for order 501. The access rule is not merely “find order 501”; it is “find order 501 within a shop this identity may access.”

  1. Verified identity

    The trusted session permits shop A.

  2. Scoped lookup

    Use the pair (shop A, order 501), and check the required read permission.

  3. Return only the permitted row

    A request body naming shop B does not grant membership in B.

A caller chooses what to request. Trusted identity and policy determine whether the request is allowed.

The pair of shop ID and order ID may form a composite key: two columns together identify one row. That prevents numeric collisions between shops, but a key alone does not enforce permission. The access path still needs the policy.

A role groups database privileges. Ordinary application work should use permissions appropriate to its task; a migration or recovery tool may need a different role. Running every request with administrative authority can bypass protections intended for less privileged callers.

The cache is also an access path

If the database query is correctly scoped but the application caches results under order:501, shop B might receive shop A’s cached row. Include the required identity and policy scope in cache design, and check what happens when permissions change.

Logs, exported files, backups, and long-lived subscriptions are also representations of the data. Protecting the main SELECT statement does not settle their access rules. Encryption protects particular storage or transport boundaries; it does not decide whether an authenticated caller owns a row.

Try the same ID in another shop

Both shops have order 501. The cache key is changed to (shop_id, order_id). Does that alone make arbitrary shop IDs supplied by callers safe?

Separate namespace from permission

No. The key prevents accidental collision, but the caller still needs authorization for the chosen shop. A perfect cache partition can faithfully return data from the wrong partition if the access decision trusts an unverified shop ID.

The engine’s security boundary must specify who establishes identity, where permission is checked, and which privileged operations can bypass ordinary paths.

PostgreSQL row-security documentation describes row policies and role-dependent exceptions. Apply its actual rules rather than assuming that a policy affects every administrator identically. These are course examples; the static reading site itself still requires no accounts or database.

Extended reference

The extended chapter preserves the original technical coverage, additional examples, and citations. The explanation above supplies the concepts needed for this page; the reference develops the specialist cases.

Find a section from the original chapter