Tutorials Logic, IN info@tutorialslogic.com

Authorization: OAuth, Capability Filtering, and Enterprise Access Control

Authorization

Authorization is where MCP stops being a demo and starts behaving like a production interface to real systems. Remote MCP servers should authenticate callers, map them to scopes or entitlements, and enforce those checks per capability.

The current MCP authorization model is transport-level and OAuth-based for HTTP deployments. Capability filtering and per-call authorization still remain server responsibilities.

Mental Model

Treat a remote MCP server like a protected resource API that also happens to expose AI-friendly discovery and invocation semantics.

Authorization Layers

Layer What It Answers
Authentication Who is calling this server?
Capability filtering What should this caller even see in tools/list or resources/list?
Per-call authorization Can this caller perform this exact action on this exact target right now?
Auditing What happened, who did it, and why was it allowed or denied?

Authentication vs Authorization

Authentication establishes identity. Authorization establishes allowed actions. That distinction matters because many MCP servers serve both read-only and write capabilities, and users often need access to some but not all of them.

Do not rely on host names, friendly labels, or client UI identity alone. Remote MCP servers should verify real credentials and tie them to durable access policy.

  • Identity comes first
  • Scope mapping comes second
  • Every sensitive tool or resource should still enforce policy at execution time

OAuth in the Current MCP Spec

Current MCP authorization guidance for HTTP-based transports uses OAuth 2.x patterns. The specification requires clients to discover authorization information through OAuth protected resource metadata instead of guessing or hardcoding token endpoints.

That requirement matters for enterprise consistency. It lets resource servers describe how authorization works in a machine-readable way while keeping the MCP endpoint and auth metadata aligned.

  • Use protected resource metadata discovery for remote MCP servers
  • Keep transport-level auth aligned with standard OAuth practices
  • Design scopes around real capability boundaries rather than generic full-access tokens

Capability Filtering and Least Privilege

Authorization should influence discovery as well as execution. If a caller does not have permission to use deployment tools, they generally should not see those tools in normal listings at all.

That reduces accidental misuse and makes host UX cleaner. It also avoids teaching the model about capabilities it should never try to invoke for that user.

  • Filter tools, resources, and prompts to the caller where possible
  • Separate read scopes from write scopes
  • Keep especially destructive tools behind stronger policy and approvals

Per-Call Enforcement

Filtering alone is not enough. Access control must still run during the actual call because permissions can change, dynamic targets can be sensitive, and list views can become stale.

For example, a user may be allowed to read policy documents generally but not read one confidential HR investigation report. That check belongs in the resource read or tool handler, not only at list time.

Simple Scope Gate in a Tool Handler

Simple Scope Gate in a Tool Handler
type SessionUser = {
  id: string;
  scopes: string[];
};

function requireScope(user: SessionUser, scope: string): void {
  if (!user.scopes.includes(scope)) {
    throw new Error(`Missing required scope: ${scope}`);
  }
}

server.registerTool(
  'create_ticket',
  {
    description: 'Create an incident ticket in the approved queue.',
    inputSchema: {
      title: z.string().min(10),
    },
  },
  async ({ title }, extra) => {
    const user = extra.authInfo as SessionUser;
    requireScope(user, 'tickets:write');

    const ticketId = await createTicket(title, user.id);
    return {
      content: [{ type: 'text', text: `Created ticket ${ticketId}` }],
    };
  }
);
  • This demonstrates the shape of per-call enforcement.
  • Real systems usually combine scopes with object-level checks.

Authorization Has More Than One Layer

Authentication answers who is calling. Authorization answers what that caller may do now. In MCP systems, authorization must exist at transport, discovery, invocation, and object levels. A token with a broad read scope may allow connecting to the server, but it should not automatically allow reading every customer, ticket, file, or report.

Discovery filtering is helpful but not sufficient. A host may cache capabilities, a user role may change, or a model may call a capability through a path that was previously visible. The server must repeat authorization at invocation time using the current identity, tenant, scopes, target object, and action. Sensitive tools should also record the reason a request was allowed or denied.

For remote servers, align MCP authorization with the organization existing identity model. Use OAuth metadata discovery where applicable, map scopes to capability families, and keep object-level policy close to the backend source of truth. Avoid inventing a parallel permission model that drifts away from production systems.

  • Authorize discovery and invocation separately.
  • Check tenant and object ownership on every sensitive call.
  • Use narrow scopes that map to capability families.
  • Treat cached capability lists as hints, not proof of access.
  • Audit denied requests as carefully as successful privileged actions.

Designing User-Visible Consent

Authorization is not the same as consent. A user may be allowed to send an email, but the host should still ask before a model-mediated workflow sends one. Consent prompts should explain the target system, action, important arguments, and consequence in plain language. Users should not have to inspect JSON to understand what will happen.

Consent should be risk-based. Reading a public document might not require an interrupt. Posting to a shared channel, deleting a record, granting access, or spending money should require explicit approval. Repeated approvals can sometimes be batched, but only when the user can review the exact scope and cancel before execution.

  • Show the server name and action category in approval UI.
  • Display the important arguments, not just a generic warning.
  • Let users edit drafts before public or external actions.
  • Never use prior consent for a materially different target or action.
  • Store approval decisions with trace and audit metadata.

Authorization Review Beyond Scopes

Scopes are necessary but not enough. A token may say a caller can read tickets, but the server still needs to know which tenant, project, customer, or ticket the caller may access. Object-level authorization is where many real security bugs live.

Remote MCP authorization also requires correct discovery and token audience behavior. Clients should learn protected resource metadata, request tokens for the intended MCP server resource, use secure flows such as PKCE where required, and avoid accepting tokens issued for another resource. These details prevent confused-deputy and token misuse problems.

Authorization should happen more than once. Discovery filtering decides which capabilities appear. Invocation authorization decides whether this caller can use this capability right now. Backend authorization decides whether the underlying data system permits the exact operation. Repeating checks may feel redundant, but each layer catches a different class of mistake.

Finally, design denial behavior carefully. A denial should be clear enough for the host and user to understand next steps, but not so detailed that it reveals hidden resource names, policy internals, or tenant information.

  • Combine scopes with tenant and object-level checks.
  • Use protected resource metadata and resource indicators for remote auth.
  • Authorize discovery, invocation, and backend access separately.
  • Log denials with reason codes while keeping user-facing errors safe.

Expert Practice Lab

Write an authorization matrix for one remote MCP server. Rows are capabilities; columns are scopes, tenant checks, object checks, approval needs, and audit requirements. This makes it obvious where a simple scope is not enough.

Then simulate a user whose role changes during a session. Discovery may have shown a capability earlier, but invocation must still check current access. This exercise reinforces why authorization must happen at multiple layers.

  • Build a capability authorization matrix.
  • Repeat checks at invocation time.
  • Test stale discovery and role-change scenarios.

Final Expert Note

For sensitive systems, review authorization decisions with sample identities from different tenants and roles, not only with an administrator token.

Scope and Tenant Enforcement

Discovery and invocation should apply the same trusted authorization context.

Scope and Tenant Enforcement
Authenticated subject: user-42
Tenant: tenant-a
Scopes: policies:read

tools/list:
  include search_policies
  omit update_policy

tools/call search_policies:
  verify policies:read
  constrain query to tenant-a
  emit audit event
  • Unauthorized capabilities are hidden during discovery.
  • Invocation repeats authorization instead of trusting prior discovery.
  • Tenant filtering belongs in the backend query path.
Key Takeaways
  • Authenticate remote callers with real credentials.
  • Use protected resource metadata and standard OAuth discovery patterns.
  • Filter visible capabilities when appropriate.
  • Enforce authorization again inside each sensitive call path.
Common Mistakes to Avoid
Returning every tool to every user and hoping the host will stop misuse.
Treating bearer token presence as enough without mapping it to real scopes.
Skipping object-level checks on dynamically addressed resources or actions.

Practice Tasks

  • Define separate scopes for docs read, incident read, and incident write.
  • Choose one capability that should be filtered from discovery for most users.
  • Write down one object-level authorization rule beyond simple scopes.

Frequently Asked Questions

Usually no, but it still needs trust review, local permission thinking, and server-side validation.

No. They should be explicit enough for operators and hosts to distinguish denial from server malfunction, while remaining safe for users.

Ready to Level Up Your Skills?

Explore 500+ free tutorials across 20+ languages and frameworks.