Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Authorization

Pattern

A reusable solution you can apply to your work.

Also known as: AuthZ, Access Control, Permissions

Context

This is a tactical pattern. Once authentication has established who is acting, authorization decides what they’re allowed to do. These are distinct concerns, often confused with each other. Authentication answers “who are you?” Authorization answers “are you permitted to do this?”

In agentic workflows, authorization matters a lot. An AI agent authenticated as acting on behalf of a developer shouldn’t automatically inherit every permission that developer holds. The agent’s permissions should be scoped to what the current task requires, a direct application of least privilege.

Problem

Not every authenticated actor should have access to everything. A junior developer shouldn’t deploy to production. A read-only API client shouldn’t delete records. An AI agent summarizing documents shouldn’t have write access to the database. But permission systems are easy to get wrong: too coarse and they grant excessive access, too fine and they become an unmanageable maze of rules. How do you decide and enforce what each actor can do?

Forces

  • Coarse-grained permissions are simple to manage but grant more access than necessary.
  • Fine-grained permissions are precise but complex to configure and audit.
  • Permissions must be enforced consistently across every path through the system, not just the main UI.
  • Requirements change over time. Roles expand, features get added, and permission models must evolve without breaking existing access.

Solution

Define a clear model for what actions exist and who can perform them. Common approaches include:

  • Role-Based Access Control (RBAC): Assign users to roles (admin, editor, viewer), and define what each role can do. Simple and widely understood.
  • Attribute-Based Access Control (ABAC): Decisions based on attributes of the user, the resource, and the environment (e.g., “editors can modify documents they own, during business hours”).
  • Capability-Based Security: Grant specific capabilities (tokens or references) that carry their own permissions, rather than checking a central permission table.

Whichever model you choose, enforce authorization at the server or service level. Never rely on the client to enforce permissions. A browser can hide a “Delete” button, but the API endpoint must independently verify that the caller has delete permission.

Check authorization as close to the action as practical. A function that deletes a record should verify the caller’s permission to delete that specific record, not trust that some upstream middleware already checked.

How It Plays Out

A SaaS application implements RBAC with three roles: admin, member, and viewer. During a security review, the team discovers that the “viewer” role can call the API endpoint for exporting all user data. The endpoint was added after the permission model was defined, and nobody updated the rules. The fix is straightforward, but the gap existed for months. This is why authorization must be part of the development checklist for every new endpoint, not a one-time setup.

A developer gives an AI agent a GitHub token with full repo scope because it was the easiest option. The agent only needs to read code and open pull requests. If the agent is compromised through prompt injection, the attacker can delete branches, push malicious code, and access private repositories. Scoping the token to read and pull_request:write would limit the damage without impeding the agent’s legitimate work.

Warning

The most common authorization failure isn’t a sophisticated bypass. It’s simply forgetting to add a permission check to a new endpoint or feature. Make authorization checks a required part of your development process.

Example Prompt

“Add role-based access checks to every API endpoint. Viewers can only GET, members can GET and POST, admins have full access. Write tests that verify each role is blocked from actions it shouldn’t perform.”

Consequences

Good authorization means that even authenticated actors can only perform actions appropriate to their role and context. It limits the damage from compromised accounts, reduces the blast radius of mistakes, and provides an audit trail of who did what.

The costs include design complexity (choosing the right model), maintenance burden (updating permissions as the system evolves), and the risk of lockout (overly restrictive permissions that prevent legitimate work). Authorization bugs are also notoriously hard to test. You need to verify not just that permitted actions work, but that forbidden actions are actually blocked across every access path.

  • Depends on: Authentication. Authorization requires verified identity.
  • Uses: Least Privilege. Permissions should be minimal by default.
  • Uses: Trust Boundary. Permission checks happen at trust boundaries.
  • Enables: Blast Radius. Good authorization limits how far damage can spread.
  • Contrasts with: Authentication. Identity vs. permission are separate concerns.