API security best practices for the age of AI agents
Autonomous agents are becoming first-class API consumers. Your authorization model needs to treat them that way.
AI agents are no longer a novelty. Whether your users are building internal productivity tools on top of Claude or GPT-4, or your product exposes an MCP server so third-party agents can take actions on your platform, one thing is certain: your APIs are going to receive calls from non-human clients that have real permissions, real consequences, and often very little human oversight at runtime.
That creates a different threat model than the one most API security guidance is written for. An agent isn't clicking a button, it's reasoning about what to do, picking from a menu of available tools, and often operating in a loop where a single bad decision cascades into a chain of unintended actions.
In this article we’ll explore how AI agents change the API threat landscape and outline security best practices teams should adopt today.
TL;DR
- AI agents act on behalf of users and must be explicitly and narrowly authorized.
- OAuth is the right foundation. If your APIs aren't using it yet, now is the time.
- Use scopes for coarse-grained limits; use claims for context-aware, fine-grained decisions.
- Tokens should be audience-restricted and never recycled across trust boundaries.
- High-privilege actions require explicit user approval; don't rely on the agent to ask nicely.
- Validate every request fully; agents don't get implicit trust just because they look internal.
What makes AI agents different from other API clients
Traditional API clients (mobile apps, browser SPAs, backend services) call your API because a human triggered them to. The user pressed a button, submitted a form, or opened a screen. The surface area for unintended behavior is narrow because every action maps back to something a human deliberately did.
AI agents break that assumption. When a user asks an agent to "clean up my calendar for next week," the agent decides what that means. It might read events, delete some, reschedule others, and send decline emails; all without the user explicitly approving each individual action. The divergence between user intent and agent behavior is a feature, but it's also the core security challenge.
There are a few characteristics of agentic API traffic that your security posture needs to account for:
- Autonomous chaining. Agents execute multi-step workflows, so an overly permissive token granted early in a session can be exploited later in ways the user didn't anticipate.
- LLM-mediated decisions. The agent's "reasoning" about which API calls to make is probabilistic. Prompt injection attacks (where malicious content in API responses manipulates the agent) are a real and growing threat vector.
- Non-human speed. Agents can call APIs at machine speed and don't have the natural hesitation a human user would have before a destructive action.
- Delegation depth. In multi-agent architectures, one agent delegates to another. Each hop is an opportunity for privilege escalation if tokens aren't scoped properly.
The practices below address each of these directly.
1. Build on OAuth (it's non-negotiable)
OAuth 2.0 is the established standard for delegated API authorization, and it's the right foundation for agentic API security. It gives you short-lived access tokens issued by a central authority, a well-understood consent model, and a rich ecosystem of extensions that handle edge cases specific to AI agents.
If you're building a new API or MCP server today, target OAuth 2.1, the latest version of the spec, which consolidates a decade of security best practices: mandatory PKCE, removal of the implicit flow, exact redirect URI matching, and deprecation of the password grant.
The Model Context Protocol (MCP) (currently the most common protocol for agentic API access) is built on OAuth. If you're exposing an MCP server today, you're already in this world. Investing in a clean OAuth implementation now pays dividends as the agentic ecosystem evolves.
!!If your APIs don't use OAuth today, treat that as the highest-priority migration on your security roadmap. Everything else in this guide depends on it.!!
2. Apply scopes strictly
Scopes are how you define what a token is allowed to do. They're simple strings that map to specific capabilities: read:transactions, write:calendar, delete:files. When the authorization server issues a token, it includes only the scopes the client requested and the user approved.
For agentic access, scope discipline is critical. An agent with a token scoped to write:everything can do far more damage (accidentally or through prompt injection) than one with write:calendar:events. A few principles to enforce:
- Design scopes at a granular level. Avoid broad permissions like
adminorwrite:*that bundle unrelated capabilities. - Scope to actions, not just resources.
transactions:readandtransactions:writeare better thantransactions; you can grant read access without granting write. - Surface scope descriptions to users during consent. "Allow this agent to read your transaction history" is more meaningful than
transactions:readto a non-technical user. - Reject unknown scopes. Don't silently ignore scope values your API doesn't recognize; they indicate a misconfigured or potentially malicious client.
Scopes are a blunt instrument, though. They tell you what category of action is permitted, not whether this specific action by this specific agent in this specific context is appropriate. That's where claims come in.
3. Use claims for context-aware authorization
Scopes tell your API what category of action is permitted. Claims tell it who is asking and in what context; and that's where you get the information needed to make intelligent authorization decisions.
Standard claims like sub (the user on whose behalf the agent is acting) are essential. Your API needs to know which user's data it's operating on, and the token is the right place to carry that (not a URL parameter the agent constructs, which could be tampered with or confused by prompt injection).
Beyond identity, claims are particularly useful for encoding agentic context:
client_type: "ai-agent": Signals to your API that this request is coming from an agent, not a human-driven client. Use this to apply agent-specific authorization policies and to filter your audit logs.client_id: Identifies the specific agent application making the request.act(actor): In delegation scenarios, records which agent is acting on behalf of which user.
What claims are not good for is encoding business logic, things like transaction limits, date ranges, or category exclusions. Those constraints belong in your API's authorization layer or a policy engine, where they can be updated without reissuing tokens and evaluated against real-time state. Tokens carry identity and context; your API enforces rules.
Keep tokens focused on who is asking and in what capacity. Leave what they're allowed to do to your authorization logic.
4. Restrict token audiences and never reuse tokens across trust boundaries
The aud (audience) claim is how you specify which service a token is intended for. Every API should validate it on every request and reject any token where the audience doesn't match. This is standard OAuth practice and prevents a token issued for one service from being used against another; a real risk in multi-component agentic architectures where tokens flow between an AI application, MCP clients, MCP servers, gateways, and downstream APIs.
The harder question is what to do when one component in that chain needs to call another. Passing the same token through unchanged is the simplest approach, but it has security trade-offs: the token's claims and scopes were designed for the receiving component, not the one it's calling. If the token is over-scoped for the downstream service, you've expanded the blast radius unnecessarily. If it's under-scoped, the call fails.
The more secure pattern at trust boundaries (particularly between external-facing and internal components) is for each component to obtain a token appropriate for the next hop, rather than forwarding the one it received. The exact mechanism depends on your architecture, but the principle is consistent with OWASP's microservices security guidance: don't let external access tokens flow unchecked into your internal service layer.
In practice this means:
- Each API validates audience. Reject tokens where
auddoesn't include your service identifier. - Don't forward external tokens to internal services without scrutiny. At minimum, ensure the token's scopes and claims are appropriate for what the internal service will do with them.
- In multi-agent architectures, treat agent-to-agent calls like external calls. Each agent should present a token scoped to the action it's requesting, not a recycled token from earlier in the chain.
A token stolen from one component should not be usable against another. Audience restriction is the mechanism that enforces that boundary.
5. Require step-up authorization for high-privilege actions
Some actions are too consequential to delegate without explicit user confirmation: deleting records, initiating financial transfers, modifying billing information, revoking access. These are operations where the cost of a mistake is high and the user should be in the loop.
Step-up authorization is the mechanism for this. When your API receives a request for a sensitive action and the presented token doesn't meet the required assurance level, return a 401 with a challenge that tells the calling agent: the user needs to re-authorize at a higher assurance level. The agent redirects the user to the authorization server, which prompts them to authenticate more strongly (typically with MFA). The server issues a new token with the higher assurance level reflected in the acr claim, and the agent retries.
This pattern keeps humans genuinely in control of consequential decisions. The agent isn't blocked from being useful (it can automate everything else) but the specific actions that carry real risk require a deliberate human yes.
When designing which actions require step-up, consider:
- Irreversibility. Can this action be undone? Deletions and data exports are harder to reverse than reads.
- Scope of impact. Does this affect one record or many? Bulk operations warrant higher scrutiny.
- Financial consequence. Any action that moves money or commits budget should require explicit approval.
- Data sensitivity. Exporting, sharing, or modifying PII should trigger step-up.
6. Validate every request
Every request from an AI agent should be fully validated, regardless of what the agent asserts about itself. Validate the token signature. Check the expiry. Confirm the audience matches your API. Enforce scopes. Read the claims and apply your authorization logic. Don't short-circuit any of this because the request looks like it came from a trusted internal agent; agents can be compromised, prompt-injected, or misconfigured.
Additional validation checks worth building in:
- Replay protection. Short-lived tokens help, but consider also checking that you haven't seen this exact token before, especially for single-use high-privilege actions.
- Rate limiting. Agents call APIs at machine speed. Implement rate limits keyed to agent identity (or the delegating user) to limit the blast radius of a runaway agent.
- Input validation. Agents construct request payloads based on LLM output. Treat that input with the same skepticism you'd apply to user-supplied data; it can be malformed, malicious, or the product of a prompt injection.
Putting it all together
Let's trace through a realistic scenario. A user asks an agent to "summarize my pending invoices and flag any that are overdue."
- The agent initiates an OAuth authorization code flow. The authorization server prompts the user to approve a narrowly scoped set of permissions:
invoices:read. - The server issues an access token with claims including
subandscope: invoices:read. - The agent calls your invoice API with the token. The API validates the token signature, checks expiry, confirms the audience, enforces the scope, and reads
subto scope the query to the right user's data. - The LLM summarizes the results; it never sees the token itself.
- The agent determines an invoice should be marked as disputed. This is a write action. The token only has
invoices:read. The agent must initiate a new authorization request to obtain a token withinvoices:writescope; the user consents to the expanded scope, and a new token is issued. - If your policy requires stronger user assurance for write actions, the authorization server can require step-up authentication before issuing the new token. The agent surfaces this to the user: "To dispute invoice #1042, I need your approval." The user re-authenticates if required. The new token carries the appropriate
acrclaim. The API checks theacrvalue, confirms the required assurance level is met, and accepts the request.
At every step, the user was in control. The agent was useful, but couldn't take action beyond what was explicitly authorized.
The agentic era requires better API security, not just more of it
The practices described here aren't fundamentally new, they're extensions of OAuth, token design, and authorization patterns that have existed for years. What's new is the stakes. When APIs are called by autonomous agents operating in long-horizon loops with real-world consequences, every shortcut in your security model carries higher potential for damage.
The good news is that if you build a clean OAuth foundation with well-designed scopes, informative claims, and a step-up authorization pattern for high-privilege actions, your APIs will handle agentic traffic safely, whether the protocol is MCP today or something different in two years.
The agents are here. Make sure your APIs are ready.
How WorkOS helps
WorkOS is designed for the security requirements of modern B2B applications, and that includes the agentic ones.
- Machine-to-machine authentication and non-human identities. WorkOS supports OAuth client credentials flows out of the box, giving AI agents a proper authorization path that's separate from your human user sessions. You can assign agent identities, scope them to specific capabilities, and manage them independently from user accounts.
- Fine-grained authorization with AuthKit. AuthKit provides the building blocks for claims-rich tokens and structured authorization decisions. You control what goes into the token, including context-specific claims that encode user-approved constraints for agentic workflows.
- Audit logs. Every authentication and authorization event in WorkOS is logged with structured metadata. When you're trying to reconstruct what an agent did on a user's behalf, that audit trail is already there.
If you're building a product that agents will integrate with (or building agent-powered features into your product) WorkOS gives you the identity and authorization infrastructure to do it securely.