How to Implement Per-User OAuth for AI Agents in Multi-Tenant SaaS
Per-user OAuth for AI agents in multi-tenant SaaS prevents data leakage. Full OAuth 2.1 + PKCE implementation: token isolation, delegation, and revocation.
OAuth for AI agents in multi-tenant SaaS is not a future problem. It is the problem your team is solving today, whether it has named it yet or not. The moment an AI agent acts on behalf of a user — reading their calendar, writing to their CRM, calling their organization's internal APIs — that agent needs an authorization boundary that is scoped to that user, revocable by that user, and impossible to widen to another tenant's data. Static API keys and shared service accounts cannot provide that boundary. Only per-user OAuth token delegation can.
The scale of the gap is visible in the data. A 2026 report from NeuralTrust found that 72 percent of organizations scaling AI agents have no comprehensive security controls over those agents. For multi-tenant SaaS, the blast radius of that gap is not one user's data — it is every tenant's. A missing tenant_id check on a token scope, a shared credential that one agent uses for all users, a refresh token stored in a database column accessible to all tenants: any of these turns an AI feature into a cross-tenant data breach.
This guide covers the full OAuth 2.1 + PKCE implementation pattern for per-user AI agent authorization in multi-tenant SaaS: the authorization flow, token storage isolation, multi-hop delegation with RFC 8693, revocation, the MCP server authorization requirements, and audit trail design. The non-human identity patterns for AI agents guide covers the broader machine identity problem; this post goes deep on the specific OAuth implementation.
Why API Keys Break Down in Multi-Tenant AI Agent Deployments
A static API key is a credential that says who you are but not on whose behalf you are acting. When a single AI agent serves hundreds of tenants, an API key-based design collapses into one of two failure modes. The first is a shared key: one key for all tenants, with the agent responsible for adding a tenant filter to every query. When the agent misses a filter — or when a prompt injection attack convinces the agent to act on broader data — there is no authorization layer to catch it. The second failure mode is per-tenant service accounts: a key minted for each tenant, stored in a configuration table. This is better isolated but introduces credential sprawl, no expiry, and no mechanism for the user to revoke the agent's access without deleting their account.
- →No user-level revocation. An API key grants access to everything the key owner can reach. If a user wants to disconnect the AI agent from their account without deleting their data, there is no clean way to do it.
- →No scope limitation per task. A key either has the access it needs for the most demanding task or the agent cannot complete some tasks. Neither option reflects least-privilege authorization.
- →No audit trail tied to a user identity. API key usage logs say the key was used, not which of your users triggered the action. That gap is a compliance problem for SOC 2 and a forensic problem for incident response.
- →Shared credentials create a path for cross-tenant escalation. A single compromised key — or an agent that processes user instructions without validating them — can reach data across tenants. There is no token boundary preventing it.
The OAuth 2.1 Authorization Code + PKCE Flow for AI Agents
OAuth 2.1 consolidates the security improvements layered onto OAuth 2.0 over the past decade. For AI agents, the Authorization Code + PKCE (Proof Key for Code Exchange) flow is the correct choice. It is the only standard flow that results in a user-granted, tenant-scoped token, works for both public and confidential clients, and prevents authorization code interception through the PKCE challenge-verifier mechanism. OAuth 2.1 makes PKCE mandatory for all clients, removes the implicit flow, and prohibits the resource owner password credentials flow.
- →PKCE setup: before redirecting the user to the authorization endpoint, the agent generates a code_verifier — a cryptographically random string of 43 to 128 characters. It computes code_challenge = BASE64URL(SHA256(code_verifier)) and sends the code_challenge and code_challenge_method=S256 with the authorization request.
- →Authorization request: redirect the user to the authorization endpoint with response_type=code, client_id, redirect_uri, scope (request the minimum scopes the agent needs), state (a random value to prevent CSRF), and the PKCE parameters.
- →Code exchange: after the user consents, the authorization server redirects back with an authorization code. The agent exchanges this for tokens by sending the code plus the original code_verifier. The server recomputes the challenge and verifies the match — the agent that holds the verifier is the same one that initiated the request.
- →Token response: the authorization server returns an access_token (short-lived, typically 15 to 60 minutes), a refresh_token (longer-lived), the token type, expiry, and the granted scopes. Confirm the granted scopes match what was requested — the user may have approved a subset.
- →Refresh token rotation: OAuth 2.1 requires refresh token rotation for public clients. When the agent uses a refresh token to get a new access token, the authorization server issues a new refresh token and immediately invalidates the old one. If the old refresh token is ever presented again, the server must treat it as a compromise signal and revoke all tokens in the family.
Per-User Token Storage and Tenant Isolation
How you store tokens in a multi-tenant system determines whether the OAuth boundary you built in the authorization flow actually holds at runtime. The goal is that a database query that leaks one tenant's token store does not expose any other tenant's tokens, and that an agent operating in one tenant's context can never read a token issued for another tenant's users.
- →Encrypt each token at rest with an envelope encryption scheme. Use a data key unique to the tenant — not shared across tenants — encrypted under a key encryption key managed by your KMS. When a tenant is offboarded, rotating or deleting the tenant's data key renders all their token records unreadable without a database row delete.
- →Store the refresh token server-side only. The agent running in the user's browser or the agent calling your API should never receive the refresh token. Keep it in a server-side token store, keyed by user_id and tenant_id. The agent requests a new access token from your server, which performs the refresh behind a session-authenticated call.
- →Access tokens can live in a short-term server-side cache (Redis with a TTL matching the token expiry). Never persist access tokens to a database — they are short-lived credentials. If your cache is compromised, the access tokens it holds expire in minutes.
- →Index token records by (tenant_id, user_id, agent_id, provider). This index structure makes it structurally impossible to query across tenants without supplying a tenant_id. Add a row-level security policy on the token table so that even a SQL query without an explicit tenant filter returns zero rows.
Multi-Hop Agent Delegation with RFC 8693 Token Exchange
Multi-agent workflows create a delegation chain: Agent A calls Agent B on User X's behalf. The token Agent B receives needs to prove both that User X originally authorized the action and that Agent A is acting as the intermediary. Without a standard for recording this chain, Agent B has no way to enforce that the token came from a trusted agent acting within the user's granted scope. RFC 8693 (OAuth 2.0 Token Exchange) solves this. It is the foundation of the IETF draft on agent delegation that emerged in early 2026, and it is the authorization pattern that MCP server security architecture depends on.
- →Token exchange request: Agent A sends its own access token as the subject_token and an assertion identifying itself as the actor_token to your authorization server's token endpoint, with grant_type=urn:ietf:params:oauth:grant-type:token-exchange.
- →Issued delegation token: the authorization server returns a token whose claims include sub (the user's identifier), act.sub (Agent A's identifier), and the intersection of the user's granted scopes and Agent A's permitted scopes. The token is scoped to exactly what Agent B needs for the specific task.
- →Verifying the chain: Agent B validates the delegation token, confirms that act.sub is an agent it trusts, and confirms that the requested action falls within the token's scope. If any step fails, Agent B rejects the request — it does not fall back to a broader credential.
- →Scope intersection enforcement: the delegation token's scope must be the intersection of what the user granted and what the calling agent is allowed to request. An agent that requests broader scopes than the user originally granted must receive a token with the user's granted scopes only — never wider.
Scoping, Rotation, and Revocation Design
Authorization boundaries are only as strong as the scope design that implements them. An AI agent that requests openid, email, profile, and write access to everything is not a least-privilege system — it is a broad credential with an OAuth veneer. Defining granular scopes, enforcing rotation, and providing per-user revocation are the three practices that keep the boundary meaningful over time.
- →Design scopes at the resource-action level, not the role level. calendar:events:read is a scope. admin is not. Each scope should map to a specific resource type and operation, so the user knows exactly what they are authorizing and your server can enforce it at the query level.
- →Request scopes incrementally, at the moment they are needed. If the agent only needs to read the user's calendar today, request the read scope. When a later workflow requires writing, request the write scope in a new authorization flow — with a new user consent prompt. This keeps the user's mental model of agent permissions accurate.
- →Implement revocation at three levels: per-user (the user disconnects the agent from their settings), per-agent (you remove an agent integration from the platform), and per-token-family (compromise response). Support RFC 7009 so users can revoke from your settings UI and so automated tooling can revoke on compromise detection.
- →On refresh token reuse detection, invalidate the entire token family immediately and set an alert for security review. A reused refresh token almost always means the token was leaked. Silent rotation without invalidation lets the attacker keep access while the legitimate user is also still using the token.
MCP Server Authorization Requirements in 2026
If you are building an MCP server that your SaaS product exposes to AI agents, the MCP authorization spec defines requirements your server must meet. This is not optional guidance: AI agent frameworks that implement the spec will reject your server if it does not comply, and the spec requirements exist specifically to prevent the token security failures that have surfaced in production agent deployments.
- →OAuth 2.1 with PKCE (S256) is required. The spec prohibits the implicit flow and the resource owner password credentials flow. Any MCP server that accepts tokens issued through those flows is non-compliant and should be treated as a security regression.
- →Authorization Server Metadata must be discoverable via RFC 9728 (OAuth 2.0 Protected Resource Metadata). An AI agent calling your MCP server should be able to discover your authorization server's endpoint by fetching /.well-known/oauth-protected-resource from your MCP server's base URL.
- →Token passthrough is prohibited. Your MCP server must not pass the user's access token through to a downstream service unchanged. If the MCP server calls a downstream API on the user's behalf, it must perform a token exchange to mint a downstream-scoped token. Passthrough collapses the scope boundary.
- →Dynamic Client Registration (RFC 7591) support is recommended. This allows AI agent frameworks to register as clients of your authorization server programmatically, without manual configuration steps that break automated agent deployments.
Audit Trails for Agent Token Use
An AI agent that acts on a user's behalf must leave an audit trail that answers: which user, which agent, which action, at what time, using which scopes, in which tenant. Without this record, incident response is guesswork, SOC 2 audit evidence is incomplete, and anomaly detection has no baseline. The audit trail is also the mechanism that lets your security team detect agents requesting scopes beyond the task they were dispatched to complete — a signal that could indicate prompt injection or a misconfigured agent.
- →Log at token issuance: record the user_id, tenant_id, agent_id, provider, granted_scopes, issued_at, and expires_at. Never log the token value — log the token_family_id (a stable identifier for the token lineage) so you can correlate refresh events without storing the credential.
- →Log at every token use: record the timestamp, user_id, tenant_id, agent_id, action (the API call made), scopes_used (the subset of granted scopes the action required), and the response status code. This log is the basis for anomaly detection.
- →Log at revocation: record who triggered the revocation (user action, security event, offboarding), which token family was revoked, and the timestamp. This is the evidence chain for a SOC 2 user data deletion or access revocation request.
- →Flag scope escalation attempts: build an alert that fires when an agent presents a token and requests an action whose required scope was not in the token's granted_scopes. This is a signature of a prompt injection attack attempting to escalate the agent's access mid-session.
Frequently Asked Questions
What OAuth flow should AI agents use?
AI agents should use the OAuth 2.1 Authorization Code + PKCE flow. It is the only standard flow that results in a user-consented, tenant-scoped token and works for both public clients (agents running in the browser or on a user's device) and confidential clients (server-side agents). OAuth 2.1 makes PKCE mandatory for all clients, removes the implicit flow, and requires refresh token rotation.
How do you prevent an AI agent from accessing another user's data in multi-tenant SaaS?
Issue per-user, tenant-scoped tokens rather than shared API keys. Each user authorizes the agent through the OAuth flow and receives a token that includes their user_id and tenant_id in its claims. Store tokens in a table with row-level security enforcing tenant_id isolation. Validate the tenant_id on every API call the agent makes, server-side, independent of the token claims — treat the claims as a hint, not as the authorization decision.
Should AI agents use API keys or OAuth tokens?
OAuth tokens for any agent that acts on behalf of a user. API keys are acceptable for machine-to-machine calls where there is no user context — a background job, a monitoring agent, a data pipeline. As soon as the agent is acting on behalf of a specific user and needs to scope its access to that user's data and permissions, an OAuth per-user token is the right credential. API keys cannot express user-level scope and cannot be revoked per-user.
What is per-user token delegation for AI agents?
Per-user token delegation means the AI agent holds a separate OAuth token for each user it serves, obtained through that user's consent in an Authorization Code + PKCE flow. When the agent acts for User A, it uses User A's token. When it acts for User B, it uses User B's token. These tokens are stored in isolation from each other, encrypted with per-user or per-tenant keys, and revocable independently. The agent cannot use User A's token for a request on User B's behalf — the token is bound to the user identity in its claims.
How do you revoke an AI agent's OAuth access in multi-tenant SaaS?
Implement revocation at three levels. User-level revocation: a UI action in the user's settings page calls your revocation endpoint (RFC 7009) with the user's token family identifier, invalidating all tokens for that user-agent pair. Agent-level revocation: when you remove an agent integration from your platform, invalidate all token families associated with that agent across all users and tenants. Compromise revocation: on detection of refresh token reuse, immediately invalidate the entire token family and return a 401 on any further use of tokens from that family.
How Belsoft Helps Secure AI Agent Authorization
Building AI agents into a multi-tenant SaaS product introduces an authorization surface that most security audits do not cover. A generic penetration test will check your API endpoints for IDOR and broken access control. It will not check whether your per-user token delegation is correctly scoped, whether refresh token rotation is enforced across all grant flows, whether your MCP server implementation prohibits token passthrough, or whether a prompt injection in an agent chat could convince the agent to request scopes beyond the user's granted permissions. The Belsoft security audit covers AI feature attack surfaces by design — including OAuth delegation review, agent authorization boundary testing, and prompt injection scenarios that escalate token scope.
For SaaS teams building the platform itself — multi-tenant architecture, Stripe billing, SSO/RBAC, and embedded AI features — the authorization boundary is a design constraint, not an afterthought. Our SaaS platform engineering work builds per-user token delegation, tenant-scoped storage, and audit logging into the platform from the first migration. We also run DeployReady against every project as a CI gate — it catches the automated baseline of RLS gaps, exposed credentials, and missing security headers before anything reaches production. The AI-specific authorization review goes deeper than what automated tools can verify, and it runs alongside the full security audit.
“An AI agent is only as trustworthy as the authorization boundary it cannot cross.”
Written by
Marco Silva
Security Engineer, Belsoft Solutions
More from the blog
Ready to partner?
Let's talk about your company.
30 minutes. No pitch. We talk through how you run today and where AI and automation would help.
Book a free audit
