A token's audience identifies the resource server allowed to accept it; its scopes describe granted access in that resource's authorization model. An API needs both checks, in addition to validating the token itself and applying its own object-level rules. A familiar scope name cannot make a token issued for another API acceptable.
The distinction matters when several APIs share an authorization server. A token can have a valid signature from the expected issuer and still be intended for a different service.
Separate the participants and their questions
Imagine an invoicing application with an Invoices API and a Reports API. Both trust the same authorization server. A client wants to read invoices on behalf of a user.
Client -- requests resource + scope --> Authorization server
Client <-- receives access token ----- Authorization server
Client -- presents token ------------> Invoices API
checks token + audience + scope
then checks access to the invoice
This is a conceptual flow, not a captured OAuth exchange. The authorization server decides what it will grant; the client does not acquire permission simply by requesting it. The Invoices API then enforces the requirements for the call it actually receives.
RFC 8707 defines the resource request parameter so clients can identify the protected resource they intend to access. It distinguishes this destination from scope and allows the authorization server to map the resource identifier to an audience. Do not assume that every deployment uses the API's URL verbatim as its audience; use the issuer-resource contract.
For this example, the agreed Invoices audience is https://invoices.example.test/, and the scope for reading is invoices:read. These names are invented identifiers. No endpoint at that address was contacted.
A valid token can still be wrong for this API
Consider a request to read an invoice. Assume, for the moment, that token format, issuer, signature, and time validity have already been checked correctly.
| Audience in the validated token | Granted scope | Invoices read decision | Reason |
|---|---|---|---|
| Invoices API | invoices:read |
Continue to object authorization | Both token-level conditions match |
| Reports API | invoices:read |
Reject | The token is not intended for this API |
| Invoices API | invoices:write only |
Reject under this example's policy | Write does not implicitly include read |
| Reports API | reports:read |
Reject | Neither condition matches |
| Invoices and Reports APIs | invoices:read |
Continue if this multi-audience token is permitted | Invoices is an intended recipient; broader exposure still needs review |
The third row is a policy choice: this service defines read and write as separate grants. Another service may deliberately define a hierarchy. The important requirement is that the mapping is explicit and enforced, not inferred from English words in the scope name.
The multi-audience case also deserves deliberate treatment. RFC 8707 discusses the increased trust required among multiple recipients of a bearer token. When each API only needs its own access, narrowly targeted tokens make that relationship easier to reason about.
A scope is not a list of all the objects the caller may access. Passing the first row does not establish that the particular invoice belongs to the user or tenant. Keep that decision in the resource service.
Validate before consuming claims
Decoding a JWT reveals fields; it does not authenticate them. A program that reads aud and scope from arbitrary decoded JSON has skipped the boundary that makes those fields meaningful.
For deployments using the OAuth JWT access-token profile, RFC 9068, section 4 specifies validation of token type, expected issuer, intended audience, signature, and expiration. It also distinguishes access tokens from ID tokens. Use a maintained verifier configured for your issuer and profile rather than treating any correctly shaped JWT as an access credential.
The trust configuration must come from the application, not a location selected by an untrusted incoming token. Decide which issuer, keys, algorithms, and audience values are acceptable through the provider's supported integration. Token verification and the endpoint's authorization rule belong in a reviewed path that every relevant request uses.
Opaque tokens require a different validation mechanism. RFC 7662 defines token introspection, through which a protected resource can obtain an active-state result and authorization metadata from the authorization server. An active result alone does not replace the resource's checks on the returned authorization context. Configure the trusted introspection endpoint and protect the credentials used to call it.
Caching validation results introduces a freshness decision. Specify how long a cached result may be used and how revocation requirements affect that choice. Do not silently equate “was valid when first seen” with “may be used indefinitely.”
Test the two dimensions independently
Build negative tests that change only one relevant property at a time. A wrong-audience token with the expected scope tests something different from a right-audience token with insufficient scope. Also test invalid signatures, an unexpected issuer, expiration, missing required claims, and the token types your API must reject.
Use synthetic identities and a controlled issuer in an authorized integration environment. Keep tokens out of logs and assertion messages. Record the expected denial, the observed response, and whether the handler performed any protected operation before refusing the request.
The local fixture for this article exercises eight cases in a much narrower truth table. Its inputs are already trusted, normalized sets of audiences and scopes. It checks exact set membership, including empty sets, a similar-looking scope, and a multi-audience value containing the intended API. All eight passed on Python 3.14.2.
That fixture performs no JWT parsing, signature check, issuer verification, clock check, introspection call, or HTTP request. It demonstrates why the two predicates must both hold. It is not a token validator, and its success is not evidence that an OAuth deployment is secure.
Carry the distinction across service boundaries
If the Invoices API calls a downstream service, decide what credential that downstream service expects. Forwarding the incoming bearer token does not change its audience. Use the authorization architecture intended for the downstream call, with its own grant and recipient checks.
This is also relevant when auditing an MCP server: the connection can sit in front of several services, each with a different trust relationship. Trace the recipient and granted operation at each hop rather than treating one successful login as a universal credential.
A useful acceptance record identifies the issuer, resource identifier, token format, expected scopes, validation configuration, and negative cases exercised. It should separately state whether per-object access was tested. Those details make “token accepted” a decision someone else can evaluate.
Standards reviewed October 28, 2026: RFC 8707, RFC 9068, and RFC 7662. The examples are synthetic; only the eight-case set-membership fixture was executed.