AI agents are increasingly being used to perform actions across multiple business systems.

An agent may receive a request from a user, call an internal API, retrieve customer information, invoke another service, and continue the workflow without direct interaction from the user.

In a single-tenant application, this can already be challenging.

In a multi-tenant system, the security model becomes significantly more important.

Consider this flow:

User
 |
 v
AI Agent
 |
 +----> Customer API
 |
 +----> Billing API
 |
 +----> Document API
 |
 +----> Reporting API

The critical question is:

Which identity should each downstream service trust?

If every request uses the same application identity, downstream services may lose the ability to distinguish users and tenants.

A stronger architecture preserves the original user's security context while allowing the agent to act on the user's behalf.

This is where On-Behalf-Of (OBO) token exchange becomes useful.

The Multi-Tenant Agent Identity Problem

Imagine an application serving three organizations:

Tenant A
--------
User A1
User A2

Tenant B
--------
User B1
User B2

Tenant C
--------
User C1
User C2

A user from Tenant A asks an agent:

"Show me the open invoices for my organization."

The agent may need to call:

Invoice API

A naive implementation might use:

User
  |
  v
Agent
  |
  | Application Token
  v
Invoice API

The Invoice API sees:

Agent Application

It does not necessarily know:

Which user?
Which tenant?
Which permissions?

The agent has effectively become a shared identity.

That creates a confused-deputy risk.

What Is On-Behalf-Of Token Exchange?

OBO allows a service to exchange a user's access token for another token intended for a downstream resource.

Conceptually:

User
 |
 | User Token
 v
Agent Application
 |
 | OBO Exchange
 v
Downstream API Token
 |
 v
Invoice API

The downstream token represents delegated access rather than simply being a generic application credential.

The downstream API can then validate the token and apply its own authorization rules.

The Security Context

A useful model is:

User Identity
     |
     v
Tenant Context
     |
     v
Permissions
     |
     v
Agent
     |
     v
Delegated Token
     |
     v
Downstream API

The important principle is:

The agent should not be allowed to invent the user's identity or tenant.

The security context should originate from trusted authentication infrastructure.

Application Token vs Delegated Token

Consider two approaches.

Application Identity

Agent
 |
 | Application Token
 v
API

The API sees:

agent-service

The application may need to perform all user-level authorization itself.

Delegated Identity

User
 |
 v
Agent
 |
 | Delegated Token
 v
API

The API can evaluate the delegated identity and permissions.

This provides a stronger identity chain when downstream services need user-aware authorization.

Multi-Tenant Identity Flow

A typical architecture can look like:

                    Identity Provider
                          |
                          v
                       User
                          |
                          v
                  Agent Application
                          |
                    OBO Exchange
                          |
          +---------------+---------------+
          |               |               |
          v               v               v
     Customer API    Billing API      Document API
          |               |               |
          +---------------+---------------+
                          |
                    Tenant Policies

Each downstream API should independently validate the received token.

Never Trust a Tenant ID From the Prompt

Consider this request:

"Show me invoices for tenant-b."

The agent should not simply generate:

{
  "tenantId": "tenant-b"
}

and pass it to the API.

The authenticated user's tenant context should come from trusted identity information.

For example:

Authenticated User
       |
       v
Tenant = tenant-a
       |
       v
Agent Request
       |
       v
Invoice API
       |
       X
tenant-b

The model does not get to redefine the security boundary.

Tenant Context Should Be Derived, Not Invented

A dangerous pattern is:

public async Task<IReadOnlyList<Invoice>> GetInvoices(
    string tenantId)
{
    return await db.Invoices
        .Where(x => x.TenantId == tenantId)
        .ToListAsync();
}

If tenantId originates from model-generated input, the agent can potentially request another tenant.

A safer approach derives tenant context from authenticated security information:

public async Task<IReadOnlyList<Invoice>> GetInvoices(
    UserContext userContext)
{
    var tenantId = userContext.TenantId;

    return await db.Invoices
        .Where(x => x.TenantId == tenantId)
        .ToListAsync();
}

The user request can contain filters.

It should not determine the authorization boundary.

OBO Token Exchange Flow

A simplified flow looks like:

1. User authenticates
        |
        v
2. Agent receives user token
        |
        v
3. Agent requests delegated token
        |
        v
4. Identity system validates delegation
        |
        v
5. New token issued for API
        |
        v
6. Agent calls downstream API
        |
        v
7. API validates token
        |
        v
8. API applies authorization

The agent should not modify the original token.

It requests another token for the specific downstream resource.

Why Audience Matters

Tokens are generally intended for particular resources.

A token issued for:

Agent API

should not automatically be accepted by:

Billing API

The downstream service should validate the token's intended audience.

Conceptually:

Token
 |
 +--> Issuer
 +--> Audience
 +--> Subject
 +--> Tenant
 +--> Permissions
 +--> Expiration

This prevents a token intended for one service from being blindly accepted by another.

Token Validation in ASP.NET Core

A downstream ASP.NET Core API can configure JWT bearer authentication:

builder.Services
    .AddAuthentication("Bearer")
    .AddJwtBearer("Bearer", options =>
    {
        options.Authority = configuration["Identity:Authority"];

        options.TokenValidationParameters =
            new TokenValidationParameters
            {
                ValidateIssuer = true,
                ValidateAudience = true,
                ValidateLifetime = true
            };
    });

The exact authority, audience, and validation configuration depends on the identity architecture.

The important principle is that the API must validate the token independently.

Authorization After Authentication

Authentication establishes:

Who is calling?

Authorization establishes:

What can they do?

For example:

[Authorize(Policy = "Invoices.Read")]
[HttpGet("invoices")]
public async Task<IActionResult> GetInvoices()
{
    // Authorization already evaluated.
}

A downstream API should not assume that a valid token automatically means the caller can perform every operation.

Tenant-Aware Authorization

Suppose a token contains:

tenant_id = tenant-a

and:

permission = invoices.read

The API can enforce:

Tenant = tenant-a
Permission = invoices.read

before accessing data.

Conceptually:

Request
 |
 v
Token Validation
 |
 v
Tenant Validation
 |
 v
Permission Validation
 |
 v
Data Access

Tenant Isolation in the Data Layer

Application-level authorization is important, but the data query should also respect tenant scope.

For example:

var tenantId = userContext.TenantId;

var invoices = await db.Invoices
    .Where(x => x.TenantId == tenantId)
    .ToListAsync(cancellationToken);

This creates a direct relationship between:

Authenticated Context
        |
        v
Tenant Scope
        |
        v
Database Query

Do not depend on the model to supply the tenant identifier.

OBO Does Not Automatically Solve Tenant Isolation

This is an important distinction.

OBO can preserve delegated identity.

It does not automatically guarantee:

Tenant A -> Tenant A data only

The downstream API still needs correct authorization and data isolation.

A secure architecture therefore has:

OBO
+
Token Validation
+
Permission Checks
+
Tenant Filtering
=
Delegated Multi-Tenant Access

Delegated Permissions vs Application Permissions

A downstream API may support two different access models.

Delegated Access

User
 |
 v
Agent
 |
 v
API

The operation is performed on behalf of a user.

Application Access

Agent
 |
 v
API

The application acts independently.

These models should not be mixed accidentally.

For user-driven agent workflows, delegated access is often more appropriate when the downstream API needs to enforce the user's permissions.

Scope Design

Avoid creating one broad permission:

api.access

for every operation.

Prefer focused scopes or permissions such as:

invoices.read
invoices.write
customers.read
documents.read
reports.create

The exact naming scheme should match the organization's authorization model.

Fine-grained permissions reduce the impact of a compromised or misconfigured agent.

Least Privilege for Agents

An agent should receive only the permissions required for the current workflow.

For example:

Customer Support Agent
----------------------
customers.read
tickets.read
tickets.write

It should not automatically receive:

billing.admin
users.delete
security.manage

even if those capabilities exist somewhere in the organization.

Tool Permissions and API Permissions Are Different

An agent may have access to a tool:

invoice.search

but that does not mean every invoice operation is allowed.

The tool can call:

GET /invoices

with delegated access.

But:

DELETE /invoices/{id}

should require a different authorization policy.

Think of permissions at multiple layers:

Agent Capability
       |
       v
Tool Permission
       |
       v
API Permission
       |
       v
Tenant Authorization
       |
       v
Data Authorization

Avoid Shared High-Privilege Tokens

A dangerous architecture is:

All Users
   |
   v
Agent
   |
   v
Admin Token
   |
   v
All APIs

If the agent is manipulated, the attacker effectively gains the privileges of the shared administrator identity.

A delegated model is safer for user-driven operations:

User
 |
 v
Agent
 |
 v
Delegated Token
 |
 v
API

The API can enforce the user's permitted operations.

Token Lifetime

Delegated tokens should have appropriate lifetimes.

A long-running agent workflow creates an interesting problem:

Workflow Starts
     |
     v
Token Issued
     |
     v
Long Processing
     |
     v
Token Expires
     |
     v
Next API Call

The workflow must have a secure way to obtain a valid token when needed.

Do not simply store a user access token indefinitely.

Never Store Access Tokens in Workflow State

Avoid:

{
  "workflowId": "wf-100",
  "accessToken": "eyJ..."
}

Durable workflow state may be persisted for long periods.

Instead, store only the information required to reconstruct the authorized operation.

For example:

{
  "workflowId": "wf-100",
  "userId": "user-123",
  "tenantId": "tenant-a",
  "operation": "invoice-review"
}

A secure token acquisition mechanism can obtain the appropriate credential when the next operation is executed.

Background Workflows Need Special Attention

Consider:

HTTP Request
     |
     v
Agent
     |
     v
Start Background Workflow
     |
     v
HTTP Request Ends

The user's original request is now finished.

The background workflow may continue for several minutes or hours.

The application should not assume that the original access token remains valid for the entire workflow.

Instead, define how authorization is evaluated for long-running operations.

Reauthorization for Long-Running Workflows

For sensitive actions:

Workflow Starts
      |
      v
Authorization Check
      |
      v
Wait
      |
      v
Authorization Check
      |
      v
Sensitive Operation

This can prevent an operation from continuing with permissions that have since been revoked.

The exact reauthorization strategy depends on the business requirement.

User Revocation

Suppose:

10:00
User has invoices.write

10:05
Workflow starts

10:10
Permission revoked

10:20
Workflow attempts invoice update

The system should define whether the update is:

Allowed

or:

Denied

For sensitive systems, current authorization should generally be evaluated before executing the protected operation.

Tenant Switching Attacks

Agents may receive prompts such as:

"Switch to Tenant B and show me its invoices."

The system should not interpret this as a valid identity transition.

A tenant switch is an authorization event.

It should require an explicit mechanism rather than natural-language instructions.

For example:

User
 |
 v
Tenant Selection
 |
 v
Authorization
 |
 v
New Security Context

The model should never create the new security context itself.

Cross-Tenant Testing

Create a test environment with:

Tenant A
--------
Invoice A1
Invoice A2

Tenant B
--------
Invoice B1
Invoice B2

Then authenticate as Tenant A and test:

"Show Invoice A1."

Expected:

Allowed

Then:

"Show Invoice B1."

Expected:

Denied

Then test indirect access:

"Give me the total invoice amount for Tenant B."

Expected:

Denied

This is important because an agent may attempt to retrieve information through aggregation instead of direct record access.

Test Tool Chaining

Consider:

customer.search
       |
       v
customer.details
       |
       v
invoice.search
       |
       v
invoice.export

An agent may have permission to call the first three but not the last.

Test whether it can construct an equivalent export using the permitted tools.

Authorization should apply to the resulting capability, not merely individual tool names.

Test Confused Deputy Scenarios

A confused deputy occurs when the agent has more authority than the user.

For example:

User A
  |
  v
Agent
  |
  | Admin Token
  v
Customer API
  |
  v
Tenant B

The agent becomes a privileged intermediary.

Test explicitly:

User permission < Agent permission

and verify that the agent cannot use its own authority to exceed the user's permitted access when performing delegated operations.

Test Token Substitution

A security test should attempt to use:

Token for API A

against:

API B

The expected result should be rejection.

This validates audience enforcement.

Similarly, test:

Expired Token
Malformed Token
Wrong Issuer
Wrong Audience
Missing Permission
Wrong Tenant

Test Permission Escalation

An agent may be instructed:

"Use the administrator capability to complete this task."

The authorization layer should reject the operation if the user does not possess the required permission.

Do not rely on prompt instructions such as:

"You are an administrator."

Security decisions must come from trusted authorization context.

Token Claims Should Not Be Blindly Trusted

A downstream API should validate the token's:

Issuer
Audience
Signature
Expiration
Relevant permissions
Relevant identity claims

Then apply its own authorization policy.

Do not accept arbitrary HTTP headers such as:

X-Tenant-Id: tenant-b

as authoritative tenant identity unless they are protected by a trusted service-to-service mechanism.

Use Strong Service Boundaries

A useful architecture is:

                 Identity
                    |
                    v
                  User
                    |
                    v
                 Agent
                    |
              OBO Exchange
                    |
          +---------+---------+
          |                   |
          v                   v
     Customer API        Invoice API
          |                   |
          v                   v
     Tenant Policy       Tenant Policy
          |                   |
          v                   v
      Customer DB        Invoice DB

Each API remains responsible for its own authorization.

The agent coordinates.

It does not become the central authorization authority.

Audit the Delegation Chain

When an agent performs an action, logs should help answer:

Who initiated it?
Which tenant?
Which agent?
Which tool?
Which downstream API?
Which permission?
Which operation?
When?
Was the request delegated?

A useful audit record might contain:

public sealed record AgentAuditEvent(
    string EventId,
    string UserId,
    string TenantId,
    string AgentId,
    string ToolName,
    string Resource,
    string Action,
    DateTimeOffset Timestamp,
    bool Allowed);

Do not log sensitive tokens.

Correlation IDs

Distributed agent workflows should use correlation IDs:

User Request
     |
     v
Correlation ID
     |
     +----> Agent
     |
     +----> Customer API
     |
     +----> Billing API
     |
     +----> Audit System

This makes it possible to reconstruct an agent workflow across multiple services.

Audit User and Agent Separately

An audit record should distinguish:

Initiating User

from:

Executing Service

For example:

User:
user-123

Agent:
support-agent

API:
invoice-service

This is more useful than recording only:

Caller:
agent-service

Protect Audit Logs

Audit data can itself contain sensitive information.

Use appropriate controls for:

Access
Retention
Integrity
Redaction
Monitoring

Do not allow ordinary application users to modify security audit records.

Common Mistakes

Using One Admin Token for Every User

This destroys user-level authorization boundaries.

Trusting Tenant IDs From Prompts

Natural-language input is not a trusted security context.

Passing User Tokens to Every API

Tokens should be intended for the resource receiving them.

Ignoring Token Audience

A token issued for one API should not automatically work against another.

Storing Tokens in Workflow State

Long-lived workflow state is an inappropriate place for sensitive credentials.

Assuming OBO Solves Authorization

OBO provides delegated identity. APIs still need authorization policies.

Giving Agents Excessive Permissions

Use least privilege for tools and downstream APIs.

Trusting Custom Headers

Headers such as X-Tenant-Id should not automatically be considered authoritative.

Ignoring Background Workflows

A user's permissions can change while an agent workflow is still running.

Auditing Only the Agent

Downstream APIs should maintain their own security-relevant audit records.

Troubleshooting

The Downstream API Returns 401

Check:

Token signature
Issuer
Audience
Expiration
Authorization scheme

Authentication failure usually occurs before application authorization.

The API Returns 403

The token may be valid but insufficiently authorized.

Check:

Scopes
Roles
Permissions
Tenant
Resource policy

The Agent Can Access Another Tenant

Check whether:

Tenant ID comes from prompt input
Tenant ID comes from query parameters
API trusts custom headers
Database query lacks tenant filtering
Agent has excessive application permissions

OBO Exchange Fails

Check:

Original token
Delegation configuration
Requested resource
Token audience
Application permissions
Credential configuration

Long-Running Workflow Fails Later

Check:

Token expiration
Credential refresh
Permission revocation
Connection state
Workflow authorization

User Can Perform an Operation Directly but Not Through the Agent

Compare:

Direct API Token

with:

Delegated Agent Token

The delegated token may be missing the required permission or audience.

Agent Can Read Data but Cannot Update It

This may be correct.

Read and write operations should generally have separate authorization requirements.

Best Practices

  1. Preserve user identity across delegated operations.

  2. Use OBO when downstream APIs need user-aware delegated authorization.

  3. Never let the model define tenant identity.

  4. Derive tenant context from trusted security information.

  5. Validate token issuer, audience, signature, and lifetime.

  6. Use least-privilege permissions.

  7. Separate read and write permissions.

  8. Do not use shared administrator tokens for user-driven workflows.

  9. Never store access tokens in durable workflow state.

  10. Plan token lifetime for long-running agent workflows.

  11. Re-evaluate authorization before sensitive long-running operations.

  12. Enforce tenant filtering at the data-access layer.

  13. Validate authorization independently in every downstream API.

  14. Test cross-tenant access explicitly.

  15. Test token substitution and audience validation.

  16. Test confused-deputy scenarios.

  17. Audit both the initiating user and executing agent.

  18. Use correlation IDs across agent and API calls.

  19. Protect audit logs from unauthorized modification.

  20. Treat OBO as identity delegation, not as a replacement for authorization.

A Production-Oriented Architecture

A robust multi-tenant agent architecture can look like this:

                         User
                          |
                          v
                 Authentication
                          |
                          v
                 User Security Context
                 +-------------------+
                 | User              |
                 | Tenant            |
                 | Permissions      |
                 +-------------------+
                          |
                          v
                    AI Agent
                          |
                Tool Authorization
                          |
                          v
                  OBO Token Exchange
                          |
          +---------------+---------------+
          |               |               |
          v               v               v
      Customer API    Billing API     Document API
          |               |               |
          v               v               v
      Auth + Authz    Auth + Authz    Auth + Authz
          |               |               |
          v               v               v
       Tenant Aware    Tenant Aware    Tenant Aware
       Data Access    Data Access     Data Access

The security boundary exists at every API.

The agent coordinates access but does not override downstream authorization.

Example End-to-End Request

Suppose a user asks:

"Show me the unpaid invoices for my company."

The workflow should conceptually be:

1. User authenticates
        |
        v
2. Application establishes user context
        |
        v
3. Agent interprets the request
        |
        v
4. Agent selects invoice.search
        |
        v
5. Application requests delegated access
        |
        v
6. Downstream API validates token
        |
        v
7. API determines tenant from trusted identity
        |
        v
8. API applies invoices.read permission
        |
        v
9. Database query filters tenant
        |
        v
10. Authorized results returned
        |
        v
11. Agent generates response

Notice that the model never determines:

Tenant
Permission
Database role
Token audience

Those remain outside the model.

Security Test Matrix

A useful regression suite should contain scenarios such as:

ScenarioExpected Result
Valid delegated tokenAllowed
Expired tokenDenied
Wrong audienceDenied
Wrong issuerDenied
Missing permissionDenied
Cross-tenant requestDenied
Prompt attempts tenant switchDenied
Admin operation without permissionDenied
Valid read operationAllowed
Unauthorized write operationDenied
Token stored in workflow stateProhibited
Revoked permission before executionDenied
Tool chaining to restricted operationDenied
Application token used where delegated token is requiredDenied

Deployment Checklist

Before deploying a multi-tenant agent using delegated identity, verify:

[ ] User identity is authenticated
[ ] Tenant identity comes from trusted context
[ ] Agent permissions are defined
[ ] Tool permissions are defined
[ ] Downstream APIs validate tokens
[ ] Token audience is enforced
[ ] Token lifetime is validated
[ ] Tenant isolation is enforced
[ ] Database queries apply tenant scope
[ ] Cross-tenant tests pass
[ ] Token substitution tests pass
[ ] Admin escalation tests pass
[ ] Long-running workflows handle expiration
[ ] Revoked permissions are handled
[ ] Tokens are never written to logs
[ ] Tokens are not stored in durable workflow state
[ ] User and agent identities are audited
[ ] Correlation IDs are available
[ ] Downstream APIs perform independent authorization

Frequently Asked Questions

What problem does OBO solve?

OBO allows an application or agent to obtain a downstream access token representing delegated access on behalf of an authenticated user.

Does OBO automatically enforce tenant isolation?

No. Tenant isolation remains the responsibility of the authorization and data-access architecture.

Should an AI agent receive administrator permissions?

Generally no. Agent capabilities should follow least privilege and should be limited to the operations required by the workflow.

Can the agent choose which tenant to access?

The agent can interpret a user's request, but it should not be able to redefine the authenticated tenant context. Any tenant change must go through an explicit authorization process.

Should access tokens be stored in agent memory?

No. Tokens are sensitive credentials and should not be placed in conversation memory or durable workflow state.

What happens when a token expires during a workflow?

The application needs a defined strategy for obtaining a valid credential. Sensitive operations should also consider whether the user's current permissions are still valid.

Is a delegated token enough to protect an API?

No. The API must independently validate the token and enforce its own authorization policies.

Why is audience validation important?

It ensures that a token intended for one resource is not automatically accepted by another resource.

Should every API trust the agent?

No. Each downstream API should establish its own authentication and authorization boundary.

What is the biggest security risk in multi-tenant agent architectures?

One of the most important risks is allowing a privileged agent identity to act on behalf of users without preserving their tenant and permission boundaries.

Conclusion

Multi-tenant AI agents introduce a fundamental identity challenge.

The agent may need to access multiple downstream services, but those services still need to know who initiated the operation and what that user is allowed to do.

A shared application identity can make this difficult:

User
 |
 v
Agent
 |
 v
Admin Identity
 |
 v
All Tenant Data

A delegated model provides a stronger security boundary:

User
 |
 v
Agent
 |
 v
OBO Token Exchange
 |
 v
Delegated Token
 |
 v
Downstream API
 |
 v
Tenant + Permission Checks
 |
 v
Authorized Data

The key principle is:

An AI agent should coordinate actions on behalf of a user without becoming more powerful than the user.

OBO can help preserve that delegated identity across service boundaries, but it is only one part of the security architecture.

A production-grade multi-tenant agent should combine:

Delegated Identity
+
Token Validation
+
Least Privilege
+
Tenant Isolation
+
API-Level Authorization
+
Secure Token Lifecycle
+
Auditability
+
Security Testing

When these controls work together, agents can operate across multiple services while maintaining clear boundaries between users, tenants, tools, APIs, and data.