Glossary
Authorization
Authorization protects data and actions after login. A signed-in user is not automatically permitted to read another customer order, change a price, or modify another user role.
Short definition
Permission is evaluated for an action, resource, and context.
The server first identifies the subject from a session, token, or another verified credential. It then evaluates policy: a role may permit the action, but membership in an organisation, ownership of an order, record state, a business rule, or the scope of an access token often matters as well. This decision must not be left to the user interface alone.
Authorization must be enforced on every entry path, especially API endpoints, background jobs, and bulk operations. A link hidden in the frontend is not protection: a client can construct the request directly. Likewise, a valid JWT or session only identifies the subject; the server reevaluates current permissions for the operation being performed.
What it is used for
Protecting resources, tenants, and high-risk operations
An access rule should be named after the actual business action, not whichever button happens to trigger it.
- viewing and modifying an order only within the organisation to which the operator belongs
- separating the customer account, warehouse, accounting, and administration functions in an online store
- limiting an integration token to a particular API scope, store, or operation type
- approving a refund, personal-data export, or change to user roles
- checking access in an API, UI controller, CLI command, and asynchronous worker
Practical example
Cancelling an order in a specific organisation
An operator may have general permission to cancel orders, but that is not enough. After loading the order, the server must also verify its organisation, state, and any rule that prevents the role from changing an order that has already shipped. Only after that decision does it call the application service that performs the change.
The example deliberately shows an explicit server boundary. In a particular framework, the policy may be implemented as a voter, policy, or application service; what matters is that the check runs before the mutation and uses the actual resource, not only a value from the client.
$authorization->assertCan(
actor: $currentUser,
permission: 'order.cancel',
organizationId: $order->organizationId,
);
$orderService->cancel($order);
How it works
From the request to a server-enforced decision
Reliable authorization uses both a trusted identity and resource state loaded by the server.
- The request presents a credential A session or token lets the server identify the subject. An invalid or expired credential is rejected before any permission decision.
- The server loads the target resource It finds the order, account, or other object through a safe path and knows its owner, organisation, state, and sensitivity.
- The policy evaluates context It combines identity, role, tenant, requested action, scope, and business restrictions. This is more than an isAdmin condition.
- The server allows or denies the action The check runs before changing or disclosing data. On denial, the API returns an appropriate status without revealing sensitive data belonging to another subject.
- The sensitive step is recorded For important operations, who did what and when is recorded. Auditing does not replace prevention, but helps investigate an incident.
Models and concepts
Roles are the starting point; resource rules decide in practice
A system usually combines several layers of rules. A single universal role with access to everything quickly becomes a problem in a long-term project.
RBAC
Role-based access control assigns permissions such as order.cancel to roles. It simplifies the management of common job roles, but does not automatically address resource ownership.
Resource and tenant checks
The application determines whether the order belongs to the organisation of the current operator and whether the operator has a relationship with the customer. This protects against IDOR and cross-tenant leaks.
Scopes and delegated tokens
A scope limits the purpose of a token, such as reading the catalogue. It is useful at an API boundary, but does not replace a detailed policy for a specific record.
Principle of least privilege
A subject receives only the access needed for its work. The default is denial, and new permissions are added deliberately.
Centralised policy
A named policy, voter, or application service prevents the same rule from being implemented differently in controllers, jobs, and forms.
Benefits and limitations
Rules must protect the real system, not merely its URLs
Benefits
- protects sensitive resources even when a client bypasses the user interface
- improves separation of tenants, job roles, and machine integrations
- named policies are testable and reusable in APIs, UIs, and workers
- auditing sensitive operations supports traceability and incident management
Risks and common mistakes
- hiding a frontend button without checking the same action on the server
- checking a general role but not object ownership, organisation, or current state
- trusting an organisation ID, role, or price sent by the client instead of a server-side source of truth
- building an overly complex role model before the real actions and responsibilities are understood
Where it matters most
Every path to data needs the same server-side boundary
Authorization is critical wherever an application serves multiple users, organisations, or services. In e-commerce it typically distinguishes customers, warehouse staff, customer support, finance, administrators, and marketplace integrations. Each of these identities works with different data and is allowed different changes.
A simple project can start with a few clear permissions and ownership checks. As it grows, rules should be centralised, negative scenarios tested, and risky operations audited. A complex ABAC model or custom policy engine is not useful merely because it exists; boundaries should reflect real processes.
What to consider
Always check permission on the server and against the actual resource
When changing an endpoint, worker, or UI, reusing the policy is safer than copying it into another layer.
- evaluate permissions before the action in an API, controller, CLI, and asynchronous job
- load ownership, tenant, and object state on the server rather than trusting request values uncritically
- deny by default and give roles and tokens only the minimum scope they need
- test negative scenarios in particular: another tenant, another resource, an expired role, and UI bypass
- add auditing, appropriate reauthentication, and clear permission management for sensitive changes
Common questions
Access decisions in practice
What is the difference between authorization and authentication?
Authentication verifies identity. Authorization evaluates whether the authenticated subject may perform a specific action on a specific resource.
Is hiding a button from a user without the role enough?
No. Hiding a button only changes the interface. A user or another client can send the request directly, so the server must deny the same action.
Is RBAC enough for a multi-tenant application?
Often not. A role describes general permission, but the relationship to the specific organisation, order, or customer must also be checked.
Does an OAuth scope replace application authorization?
A scope limits the purpose of a delegated token. The resource server still evaluates local rules and the relationship of the subject to the specific resource.
How I approach architecture in practice
I keep access rules close to application actions and resources.
When designing a backend, I separate login, roles, tenant rules, and business operations so they can be reused and tested safely.