DEV Community

Anton Staykov
Anton Staykov

Posted on

Back to the basics - OAuth and its (ab-)use for agentic authorizations

OAuth already distinguishes the application requesting access from the authority under which it acts. Microsoft's own roles diagram puts those responsibilities in separate boxes. The uncomfortable question is whether your API preserves that distinction when the client is an AI agent.

The goal is to define which authority your API accepts when a user or workload acts through an agent. If an operation needs agent-specific restrictions, its authorization policy must represent the client as well as the subject. The examples use v2.0 access tokens, whose format is part of the resource's token contract.

The agent does not add a fifth OAuth role

Start with the four roles in Microsoft's protocols documentation. The resource owner can authorize access, the client requests it, the authorization server issues the token, and the resource server evaluates requests for the protected resource. In a delegated scenario, the resource owner is usually the human whose data the client accesses.

This adaptation follows the logical exchanges in the OAuth abstract protocol flow. It establishes the responsibilities before assigning any of them to an agent.

flowchart TB
    RO["Resource owner<br/>(human in this example)"]
    C["Client application"]
    AS["Authorization server<br/>(Microsoft Entra)"]
    RS["Resource server<br/>(API)"]

    C -->|"1. Request authorization"| RO
    RO -->|"2. Authorization grant"| C
    C -->|"3. Present grant"| AS
    AS -->|"4. Access token"| C
    C -->|"5. Access token"| RS
    RS -->|"6. Protected resource"| C

Conceptual adaptation of Microsoft's role model and RFC 6749's flow. The arrows describe logical exchanges in a human-delegated example, not a wire-level trace.

Microsoft Entra also acts as an identity provider, but that is not a fifth OAuth role. OpenID Connect supplies authentication information to the client through an ID token; the API receives an access token. Keep that distinction when deciding which token your resource accepts.

An agent can occupy different roles at different boundaries. A middle-tier agent API is a resource server when a frontend calls it and a client when it calls a downstream API through the on-behalf-of (OBO) flow. An autonomous client can instead use the client credentials grant, without a delegated human identity.

The subject and the client answer different questions

Consider an invoice API serving employees through an agent and an autonomous reconciliation workload. The operation is the same, reading an invoice, but the authority behind each request is different. Microsoft's claims-validation guidance separates the inputs the API needs to make that decision.

First, establish that the claims can be trusted here. Validate the signature and issuer (iss), the intended audience (aud), the token's lifetime (nbf, exp) and the accepted tenant (tid). These checks establish an acceptable token, not permission to read a particular invoice; they belong at the receiving resource, while clients treat other resources' access tokens as opaque. Follow the access-token validation guidance for that boundary.

Within it, sub identifies the represented principal. For directory-backed policy, oid identifies the user or service principal object and tid supplies its tenant context, so (tid, oid) can identify the principal whose invoice entitlements the API evaluates. Because sub is pairwise, it is not interchangeable with that directory lookup key or a universal identifier across applications. These purposes are distinct in the claims reference.

The client identified by azp answers a different question: which application is exercising the represented authority? The finance portal and the agent can act for the same employee, yet your policy may permit them to reach different invoice data. A subject-only decision cannot express that distinction, which is why subject and actor authorization need separate consideration.

The permission context connects the two. scp carries delegated scopes; roles can carry application permissions or roles assigned to a user on the resource application. Those claims describe granted permissions, but the resource must still combine them with the represented principal's entitlements and any restrictions on the client.

On-behalf-of preserves the user's authority, not the client's identity

In From OBO APIs to Agent Identities: Entra Conditional Access Still Works the Same, the middle tier changes without removing the delegated user context. The agent authenticates as a client and exchanges the incoming user assertion for a token intended for the downstream API. It does not simply forward the original token to another audience, as the OBO protocol documentation explains.

The agent also needs an authorized grant of the downstream delegated permissions. Why consent is the trust contract for Entra Agent ID covers that prerequisite; permissions and consent do not disappear because a user is represented. The API receives a request carrying both that delegated permission context and the user's identity.

This synthetic fragment shows the resulting policy inputs, including optional context claims where available. It is an illustration, not a complete token; the agent claims reference defines the meanings.

{
  "ver": "2.0",
  "aud": "11111111-1111-4111-8111-111111111111",
  "tid": "22222222-2222-4222-8222-222222222222",
  "sub": "user-subject-for-this-application",
  "oid": "33333333-3333-4333-8333-333333333333",
  "azp": "44444444-4444-4444-8444-444444444444",
  "idtyp": "user",
  "scp": "Invoices.Read",
  "xms_act_fct": "11"
}
Enter fullscreen mode Exit fullscreen mode

The API evaluates the employee's invoice access using (tid, oid) and requires Invoices.Read. It then uses azp if its policy distinguishes this agent from other authorized clients; the agent facet supplies classification, not another permission. That combination follows the documented subject and actor model.

Suppose the employee may read invoices across several projects, but this agent is approved only for one. The API must apply that project restriction as well as the employee's rights and the delegated scope. A granted scope is not a complete business policy. Scope validation already participates in client authorization; it simply cannot express a more specific restriction that your resource has not modeled.

The same resource-policy question remains when an exchange crosses authorization domains, although the trust arrangement becomes more complex. To exchange or not to exchange (a token) addresses that separate architectural choice. A different token does not relieve the receiving API of its authorization decision.

App-only changes the subject, not the need for authorization policy

The autonomous reconciliation workload uses its own authority instead. In the app-only scenario, the agent identity service principal is the subject, not the employee who sponsors or requests its work. The API must therefore evaluate what the workload itself is authorized to access.

This fragment keeps the same API and agent client but changes the subject and permission context. Invoices.Read.All is an illustrative application permission defined by this API; the access-token claims reference explains the use of roles for application permissions.

{
  "ver": "2.0",
  "aud": "11111111-1111-4111-8111-111111111111",
  "tid": "22222222-2222-4222-8222-222222222222",
  "sub": "agent-subject-for-this-application",
  "oid": "55555555-5555-4555-8555-555555555555",
  "azp": "44444444-4444-4444-8444-444444444444",
  "idtyp": "app",
  "roles": ["Invoices.Read.All"],
  "xms_act_fct": "11",
  "xms_sub_fct": "11"
}
Enter fullscreen mode Exit fullscreen mode

The workload now occupies both subject and client roles, but sub, oid and azp still have different meanings. Their strings need not be equal. The API evaluates the workload's permission and resource restrictions without borrowing the employee's entitlements.

Establish that context deliberately rather than classifying tokens by one convenient claim. User tokens can also contain roles, and the agent token model includes autonomous agents using their own user accounts. That produces three distinct sources of represented authority:

Access model Represented subject Client Permission context
Human delegation Human user Agent identity Delegated scopes and user authority
App-only agent Agent service principal Agent identity Application permissions under the API's model
Agent user account Agent's own user account Agent identity User-context permissions for that account

An agent user account carries its own authority, not the employee's. Consequently, idtyp: user alone does not establish a human subject. If your API authorizes an app-only subject by azp, Microsoft's validation guidance requires checking idtyp: app for that approach; recognizing the client ID in a delegated token is not equivalent.

Agent facets describe the principal, not a new permission grant

The optional agent claims help distinguish those contexts. xms_act_fct describes the client actor identified by azp; xms_sub_fct describes the subject. Values include 11 for an agent identity and 13 for an agent's user account, interpreted as space-separated, unordered facets. The agent claims reference shows the supported combinations.

A resource can use that classification where its policy requires it, but a missing optional facet is not evidence of a human caller. Other context claims have narrower purposes: xms_tnt_fct describes the tenant, xms_idrel describes the subject's relationship to the resource tenant, and xms_par_app_azp supports parent-application attribution. Microsoft recommends the parent claim for auditing rather than authorization, since a parent-based grant can admit many agents.

These claims do not establish a complete delegation chain. RFC 8693's structured act claim is a different representation, not something implied by finding azp or an agent facet. As discussed in The industry does not have an agent identity propagation standard yet, visible attribution is not proof of every upstream trust relationship.

Revocation must follow the authority the resource actually accepts

The same policy must identify what loses access when authority is withdrawn. A user-wide operation such as revokeSignInSessions is not an agent-specific denial, and stopping token issuance does not itself prove rejection of existing tokens. That distinction is part of token revocation's enforcement boundary.

Continuous access evaluation (CAE) can help participating resources reject access before expiry; use the documented user-context behavior and workload support for implementation details. Your design still needs to state which subject or client is denied and where that denial takes effect. Rejecting further API requests is also different from stopping execution or accepted work, the wider problem in The AI agent kill switch is a procedure, not a feature.

Your API must decide whether the client is part of the trust contract

The result should be an operation-level contract, not a claim checklist. For the invoice API, an employee's delegated request must satisfy that employee's invoice rights, the client's delegated permission and any approved project boundary. An app-only request must satisfy the workload's own grant and resource restrictions. Subject, permission and client checks make those different decisions explainable.

Not every API needs a client allowlist, but every architecture should deliberately decide whether client identity changes authorization. This remains a resource responsibility, the same boundary examined in Your API gateway is not an identity provider, and promoting it to one is a liability. Also distinguish client attribution from sender assurance: azp in a bearer token does not prove that the presenter possesses the client's credentials.

This guidance reflects the documentation reviewed in October 2026. Record the agent claim contract your policy depends on rather than assuming that evolving agent features change the represented authority automatically.

You should be able to explain each accepted operation in one coherent statement: this principal, using this permission through this client, may access this resource under these restrictions. The subject identifies whose authority is represented. Your resource's policy decides whether that authority, exercised through this client, is sufficient.

References

Top comments (0)