Table of Contents

6. Authorization & Access Control — Keeping Capabilities in Their Lane

Authentication answers who the user is.
Authorization answers what the user can do.

A secure system treats capabilities as boundaries
— not conveniences.
Every action, every resource, every piece of data has a lane,
and users must stay within it.

This page introduces the mental model for
designing authorization that is predictable, explicit, and difficult to misuse.


1. Authorization Is About Capabilities, Not Roles

Roles are labels.
Capabilities are actions
.

A secure system focuses on:

Roles are just a way
to group capabilities.

Capabilities are the real boundary.


2. Prefer Capability‑Based Access Over Role‑Based Access

Role‑based access control (RBAC) is simple,
but often too broad.

Capability‑based access control (CBAC) is:

Example:

Instead of:

"Admin can manage users"

Use:

"CanCreateUser"
"CanEditUser"
"CanDisableUser"
"CanResetPassword"

Capabilities are small, clear, and testable.


3. Authorization Must Be Checked at the Boundary

Authorization belongs at the entry point of an action:

Do not:

Every action must enforce its own boundary.


4. Avoid “Soft” Authorization

Soft authorization is when the system:

…but does not enforce the rule on the backend.

That's not security.
That's convenience
.

A secure system:


5. Authorization Must Be Explicit, Not Implicit

Avoid implicit rules like:

"Admins can do everything"
"If the user created it, they can edit it"
"If the ID matches, it’s allowed"

Implicit rules drift.
Explicit rules endure
.

Prefer:

if (!$auth->can('edit_post', $post)) {
    throw new UnauthorizedException();
}

Explicit authorization is readable, testable, and predictable.


6. Use Policy Objects for Clarity

Policies encapsulate authorization logic.

Example:

class PostPolicy {
    public function edit(User $user, Post $post): bool {
        return $user->id === $post->author_id;
    }
}

This keeps authorization:

Policies are the architectural home for capability rules.


7. Avoid Overloading the Session With Authorization Data

Do not store:

…inside the session.

Why?

Always fetch authorization data fresh from a trusted source.


8. Authorization Must Support Revocation

A secure system must be able to say:

"This user no longer has this capability."
"This role has changed."
"This permission is revoked."

Revocation must take effect immediately.

This is why authorization data must not be cached in:

Authorization is dynamic.


9. Least Privilege Is the Default Posture

A secure system gives users:

Least privilege reduces risk by reducing surface area.


10. Authorization Is Not Authentication

Common mistakes:

Authentication is identity.
Authorization is capability
.

They must remain separate.


Summary

Authorization is the discipline of keeping capabilities in their lane.

A secure system:

Security is not about trusting the user —
it’s about trusting the boundaries
.


This page describes secure defaults and common practices in modern PHP. It is not a complete security guide, and it does not replace formal audits or framework‑specific documentation. These principles are consistent enough to be useful, but security always requires context, judgment, and ongoing review.