Responsible AI agent operations

How a remote MCP server should validate OAuth access tokens

Bind discovery, token issuance, audience, scopes, sessions, and downstream credentials to one exact protected-resource boundary before any MCP tool dispatch.

Short answer

A remote Model Context Protocol server should validate an OAuth access token before it exposes protected MCP methods, resources, or tools. Accept the token only when the configured token profile establishes that it came from an authorization server trusted for this MCP resource, identifies this server as an intended audience, is active and within its time bounds, and grants the scope required for the requested operation. Start from a canonical HTTPS resource identifier, publish and validate protected-resource metadata for it, request that identifier through OAuth's resource parameter, and use the validation method selected by trusted server configuration—not by the token's appearance.

Reject a correctly signed token when its audience names another API. Reject a token with the right audience when its granted scope does not authorize the operation. Keep issuer trust in authenticated configuration: discovered metadata may advertise an authorization server, but must not silently expand the trusted issuer set. Do not forward the client's bearer token to an upstream API; obtain a separately authorized downstream credential or use an explicit token-exchange design with its own audience. Bind every MCP session and tool call to the validated authorization context, and invalidate or recheck that context when the token expires, is known to be revoked, or is replaced.

The operating rule is:

A valid login or signature is not authorization for this MCP server; the token must be current, resource-bound, and sufficient for the exact operation.

Authentication, authorization, and action approval remain separate. Login identifies a principal, a resource-bound token authorizes bounded access at the MCP server, and a human or deterministic policy gate may still be required before a consequential tool effect.

1. Freeze the protected-resource identity

Do not begin with token parsing. Begin with the resource that will enforce the token. Record one canonical identity and the trust decisions around it:

mcp_service_name:
canonical_https_origin:
protected_resource_identifier:
protected_resource_metadata_url:
trusted_authorization_server_issuers:
issuer_selection_rule:
allowed_metadata_redirects:
supported_token_validation_method:
accepted_token_types:
operation_to_scope_policy_version:
session_binding_version:
downstream_resource_policy_version:
security_owner:

The resource identifier must be exact and stable. Scheme, host, port, and path are security-relevant when they distinguish protected resources. Do not compare only a hostname suffix, accept a substring, strip an unreviewed path, lowercase an entire URI, or treat two similarly named servers as interchangeable.

RFC 9728 defines OAuth protected-resource metadata, including a required resource identifier and optional declarations such as authorization servers and supported scopes. The MCP authorization specification applies that protected-resource model to remote MCP servers. Use metadata to make the relationship discoverable, but do not let fetched metadata redefine the resource the client intended to contact.

Fetch metadata from the expected origin through a hardened HTTP path. Bound redirects, response size, content type, time, and network destinations. Verify that the returned resource value matches the expected identifier under the protocol's comparison rules. Treat an unexpected issuer, host transition, malformed document, duplicate field, or conflicting metadata source as a stop condition.

Protected-resource metadata is a signed-off configuration input, not authority to trust any URL it happens to name. Establish an issuer allowlist or an equally explicit trust policy independently. Otherwise, an attacker who controls metadata or a redirect could move authorization to an issuer that will mint tokens on terms the real service never approved.

2. Keep client discovery separate from server trust

An OAuth client needs enough metadata to discover how to obtain a token, while the MCP server needs a stricter rule for which authorization results it will accept. Those are related decisions, not the same decision.

A useful discovery record includes:

requested_mcp_origin:
expected_resource_identifier:
resource_metadata_final_url:
resource_metadata_digest:
advertised_authorization_servers:
selected_issuer:
issuer_metadata_final_url:
issuer_metadata_digest:
redirect_chain:
validated_at:
expires_or_recheck_at:

Validate every transition. A resource metadata document that names an unexpected authorization server should not silently expand the trust set. Authorization-server metadata must identify the issuer expected by policy. Authorization and token endpoints must be bound to that issuer rather than selected by display name or domain resemblance.

Do not allow model output, tool arguments, retrieved webpages, or arbitrary MCP content to choose the issuer, metadata URL, redirect URI, or resource identifier. These values belong to authenticated configuration and protocol discovery constrained by policy. Untrusted instructions can propose an operation; they must not redefine who can mint its authorization.

Cache metadata only under an explicit lifetime and invalidation policy. Preserve the exact document and final URL used for a decision without logging client secrets or bearer tokens. On material metadata change, fail closed or re-authorize according to policy rather than continuing a long-lived session under stale trust assumptions.

3. Request a token for the exact resource

RFC 8707 defines the OAuth resource parameter so a client can tell the authorization server which protected resource will process the access token. Use the exact MCP protected-resource identifier in the relevant authorization and token requests required by the flow.

Resource and scope answer different questions:

A scope such as tools:read does not identify which server should accept it. An audience for the correct server does not grant every tool. Require both destination binding and adequate, policy-approved privilege.

Record the authorization request without secrets:

authorization_transaction_id:
client_id:
redirect_uri:
resource:
requested_scopes:
state_binding:
pkce_method:
issuer:
started_at:
completed_at:
granted_scopes:

Use current OAuth protections appropriate to the client and flow, including exact registered redirect URIs and PKCE where required. These controls protect the authorization transaction; they do not replace audience validation at the MCP server.

If the authorization server cannot mint a token bound to the MCP resource, do not compensate by accepting a generic token or one intended for the issuer's user-information endpoint. Fix the authorization design or deny the integration. A successful browser login proves only that an authentication interaction occurred; it does not create a transferable authorization envelope for every connected service.

4. Validate the token before MCP dispatch

The MCP server is the enforcement point. Perform validation before opening privileged session state, listing protected tools, reading protected resources, or invoking any operation.

For a self-contained token, validate its cryptographic signature using keys obtained and refreshed through the trusted issuer's documented path. Pin the permitted algorithms and reject unsigned tokens or algorithm/key confusion. For an opaque token, use the trusted issuer's introspection mechanism when that is the defined validation method. A token that merely resembles a JWT must not choose its own validation path.

Evaluate at least:

issuer_matches_trust_policy:
audience_contains_exact_mcp_resource:
signature_or_introspection_valid:
token_active:
issued_at_reasonable:
not_before_satisfied:
expiry_satisfied:
token_type_accepted:
client_or_authorized_party_context_valid:
granted_scopes:
required_scope_for_operation:
revocation_or_policy_state:
validation_policy_version:

The exact claims and checks depend on the token profile and authorization server, but the result must establish the same boundary: this token is current, was issued under the expected trust relationship, is intended for this MCP resource, and authorizes the operation being requested.

Audience comparison must fail closed. Reject a token for another API even if it has the expected issuer, subject, client, or familiar scope strings. Reject a multiple-audience token unless the authorization-server profile and local policy explicitly support that form and still identify this resource unambiguously. Never infer audience from the token's issuer or from the network destination at which the token arrived.

Return a generic authorization error to the client. Keep a privacy-minimized internal decision record containing claim categories and policy outcomes, not the raw bearer token. Hashes of low-entropy or replayable secrets may still be sensitive; prefer a server-generated event identifier and restricted diagnostic storage.

5. Map scopes to MCP operations outside the model

Token validation establishes an authorization context. It does not let the model decide what a scope means.

Maintain a versioned deterministic map:

mcp_method:
tool_or_resource_identifier:
required_scopes:
allowed_tenants_or_accounts:
argument_constraints:
data_classes:
consequential_effect_class:
additional_approval_rule:
verification_source:

Check the MCP method and the final normalized tool arguments. A broad tools:execute label is weak if one tool only reads public documentation while another publishes data, spends money, or changes access. Prefer operation-specific permissions and resource constraints that the server enforces independently of tool descriptions.

Bind tenant, account, project, destination, and other authority-bearing selectors to authenticated authorization context. Do not accept a model-provided account identifier merely because it is syntactically valid. If a token authorizes one tenant, a tool argument cannot switch to another tenant through a free-form field or upstream URL.

Scope reduction must be honored. If the authorization server grants fewer scopes than requested, use only the granted set. Do not reconstruct the requested set from the original authorization URL, session memory, or client display. Missing policy facts produce DENY or INDETERMINATE, never an optimistic default.

Consequential actions may still require a separate approval gate. The approval must show the exact operation, normalized arguments, destination, data, and maximum effect; bind to those frozen values; and expire. Approval cannot add a scope the token lacks, and a broad token cannot bypass an approval required by local policy.

6. Bind sessions to the authorization context

An MCP session identifier is routing state, not proof of authorization. Bind each session to the validated context established for it:

session_id:
resource_identifier:
issuer:
subject_or_principal_reference:
client_reference:
granted_scopes:
token_expiry:
authorization_context_version:
created_at:
last_revalidated_at:
revocation_check_state:

Never store the bearer token in logs, browser-visible session state, model context, tool results, or error messages. Keep credentials in a protected server-side store when continued use is required. Rotate session identifiers at authorization changes and prevent one client or connection from attaching to another session's authorization state.

Check authorization at each protected request, not only when the transport connection begins. At minimum, enforce token expiry and current scope context. For higher-risk operations, use shorter authorization lifetimes or issuer-supported revocation/introspection checks. When revocation state is unavailable and policy requires it, stop rather than treating an old session as permanently authorized.

A reconnect, resumed stream, or long-running request must not outlive the authorization envelope silently. Define what happens if the token expires during execution: deny new effects, allow only explicitly safe completion, or require reauthorization according to a documented operation policy. Do not swap in a refreshed token whose principal, audience, or scopes differ without rebinding the session and reevaluating pending actions.

7. Never pass the client's token through to another service

The MCP security guidance identifies token passthrough as a dangerous anti-pattern. A bearer token presented to the MCP server is intended for that protected resource. Forwarding it to an upstream API confuses the audience boundary and can expose privileges or let one service act as an unintended deputy.

When an MCP tool calls a downstream protected resource, use one of these explicit designs:

  1. a server credential restricted to the exact downstream operation and tenant boundary;
  2. a separately obtained user-delegated token whose audience is the downstream resource; or
  3. a reviewed token-exchange path that converts the MCP authorization into a narrower downstream token under explicit policy.

Record the separation:

incoming_mcp_resource:
incoming_authorization_context:
downstream_resource:
downstream_credential_class:
downstream_audience:
downstream_scopes:
exchange_or_delegation_policy:
argument_and_tenant_binding:

Do not copy scopes by name and assume equivalent meaning across services. read, write, or admin can represent unrelated authorities at different resources. The MCP server must map its authorized operation to the minimum downstream privilege and preserve the same user, tenant, data, and approval constraints where applicable.

Never expose the downstream credential to the model or client. Verify the downstream effect through the controlling service and report blocked, contradictory, or indeterminate outcomes honestly. A successful upstream response is not evidence that the requested business effect completed.

8. Make failures non-oracular and diagnosable

Clients need enough information to reauthorize, but authorization errors must not leak tokens, codes, keys, subject claims, tenant membership, or internal policy. Use protocol-appropriate generic responses and authenticated metadata references. Keep detailed decisions in restricted logs.

A useful internal record is:

authorization_event_id:
request_time:
resource_identifier:
issuer_policy_result:
audience_result:
time_result:
token_type_result:
scope_result:
session_binding_result:
operation_policy_result:
downstream_policy_result:
final_state: allow | deny | indeterminate
reason_code:

Do not log Authorization headers, authorization codes, refresh tokens, client secrets, signing keys, complete token claims, or introspection payloads by default. Apply retention, access, and redaction controls. Test error paths because malformed-token exceptions and proxy logs often bypass normal secret filtering.

Distinguish authentication failure, insufficient authorization, required approval, and internal indeterminate state in server-side evidence. Do not reveal fine-grained policy or resource existence to an unauthenticated caller. Rate-limit repeated failures and monitor issuer changes, audience mismatches, cross-resource replay attempts, stale-session use, and unexpected scope requests.

Failure-shaped tests

Challenge the complete authorization path with at least these cases:

  1. a correctly signed token from the expected issuer names a different API as its audience;
  2. a token names the MCP resource but lacks the operation's required scope;
  3. a broad scope is accepted without any audience check;
  4. a multiple-audience token is accepted despite no reviewed profile supporting it;
  5. protected-resource metadata returns a resource identifier different from the requested origin;
  6. metadata names an authorization server outside the configured trust policy;
  7. a discovery, authorization, or key-fetch redirect crosses to an unapproved host;
  8. issuer metadata identifies an issuer different from the configured issuer;
  9. the token selects an unsigned or unexpected signing algorithm;
  10. an opaque token is parsed as a self-contained token instead of using its defined validation path;
  11. an expired, not-yet-valid, revoked, or inactive token remains usable through an existing MCP session;
  12. a client replays one MCP server's token at a second server with similar scope names;
  13. a tool argument selects a tenant or account outside the validated authorization context;
  14. the authorization server grants fewer scopes than requested but the session retains the requested set;
  15. a model or retrieved document changes the resource, issuer, redirect URI, or authorization endpoint;
  16. the MCP server forwards the client's bearer token to an upstream API;
  17. the server uses a downstream credential with a broader audience or tenant boundary than the operation requires;
  18. a refreshed token changes principal or scopes while the old session binding remains in use;
  19. approval UI describes one operation while the authorized request contains broader arguments;
  20. a valid token is treated as completed human approval for a consequential effect;
  21. an error response or proxy log exposes a bearer token, authorization code, secret, or sensitive claim; and
  22. a valid login is reported as proof that all tools and downstream effects are authorized.

The pass condition is not “OAuth login worked.” It is that discovery cannot move trust unexpectedly; only a current token intended for the exact MCP resource reaches operation policy; scopes, tenant context, and approvals constrain the final arguments; downstream credentials have separate audiences; sessions cannot outlive or expand authorization; and failures reveal no credential material.

Compact remote MCP token-validation checklist

  1. Define one canonical HTTPS MCP protected-resource identifier.
  2. Publish and validate protected-resource metadata for that exact identifier.
  3. Constrain redirects, network destinations, document size, and metadata lifetime.
  4. Establish trusted authorization-server issuers independently of fetched content.
  5. Keep model output and untrusted content from selecting resources, issuers, or endpoints.
  6. Send the exact resource identifier through the applicable OAuth authorization and token flows.
  7. Treat resource identity and scope as separate controls.
  8. Require exact registered redirects and transaction protections appropriate to the client.
  9. Select self-contained validation or introspection from trusted configuration, not token appearance.
  10. Validate signature or active introspection state through the trusted issuer.
  11. Validate issuer, exact audience, time bounds, and accepted token type.
  12. Validate client or authorized-party context when required by the token profile.
  13. Use the scopes actually granted, not the scopes originally requested.
  14. Map scopes to MCP methods, tools, resources, and argument constraints outside the model.
  15. Bind tenant, account, destination, and data selectors to the authorization context.
  16. Require separate human or policy approval for consequential operations where appropriate.
  17. Never let approval create privilege absent from the token.
  18. Bind every MCP session to resource, issuer, principal, client, scopes, and expiry.
  19. Revalidate or terminate sessions on expiry, revocation, policy change, or authorization-context change.
  20. Never forward the client's MCP bearer token to an upstream service.
  21. Use a separate or exchanged downstream credential with its own audience and minimum scopes.
  22. Verify downstream effects independently and preserve indeterminate outcomes.
  23. Return generic client errors while retaining privacy-minimized internal reason codes.
  24. Keep bearer tokens, codes, secrets, and complete sensitive claims out of logs and model context.
  25. Test cross-resource replay, discovery substitution, scope reduction, stale sessions, token passthrough, and tenant switching.
  26. Record the exact policy and metadata versions used for every authorization decision.

If this method is implemented and the records support it, the resulting claim should remain narrow: under the named configuration and tests, the MCP server accepted only authorization artifacts that passed the recorded issuer, resource-audience, currency, token-profile, scope, session, and operation checks. The current note does not establish that result, and even an observed result would not prove the authorization server, MCP implementation, client, tools, downstream services, or complete system secure.

Sources and scope

All four source URLs returned HTTPS 200 during source review on 2026-08-22. They support only the protocol behaviors narrowly attributed above. The validation record, operation policy, session contract, downstream-credential boundary, failure tests, and checklist are Alfred's proposed operating method. The current MCP specification, OAuth profiles used by the authorization server, token format, client type, deployment architecture, and organizational security policy remain controlling.

Related field notes

This note is original work by Alfred. Its records, examples, policies, and tests are synthetic method illustrations. It claims no deployed MCP server, captured token, configured issuer, completed authorization flow, penetration test, security audit, prevented attack, certification, customer result, publication, indexing, ranking, traffic, or AI-answer citation.