How AuthSec protects your MCP server
This page is the mental model. If you just want to ship, jump to Protect your first Application.
Your MCP server (or API, or AI agent) sits at some URL. AI clients — Claude Desktop, Codex, your own — want to call tools on it. You need to know:
- Who's making this call?
- Are they allowed to call this specific tool?
- If not, what should the AI client do next?
AuthSec answers all three, automatically, every request.
The shape of the flow
Once your Application is registered and the SDK is mounted, every tool call looks like this:
- The AI client calls your tool. First call has no token — that's fine.
- AuthSec replies "you need to authenticate" with a pointer to where the AI client should send the user (the OAuth login page).
- The user logs in through whatever identity provider you've configured (your own login, Google, GitHub, SAML — set under Identity Providers).
- The user sees a consent screen listing what the AI client is asking for, in plain English. They approve.
- The AI client retries the tool call with a token. The SDK validates it, checks whether the requested tool is allowed for that user's scopes, and either runs the tool or returns a structured denial.
That's it. Steps 1–4 happen once per user per AI client. Step 5 happens every request.
What the SDK actually checks
When a tool call lands with a bearer token, the wrapper does five checks. The first one that fails returns a denial — with a code the AI client knows how to act on.
| # | Check | Failure → denial code | What the AI client does |
|---|---|---|---|
| 1 | Token signature + expiry | invalid_token | Re-authenticate the user |
| 2 | Token matches your Application (audience) | invalid_audience | Re-authenticate against the right server |
| 3 | User's scopes include what this tool requires | scope_insufficient | Ask the user to re-consent for more scope |
| 4 | Token isn't revoked (live introspection check) | token_revoked | Re-authenticate |
| 5 | Tool-specific policy (MFA, IP, time, etc.) | step_up_required / policy_denied | Trigger step-up MFA, or report blocked |
The full list of denial codes is in the Denial taxonomy reference page.
What you configure
You don't write any of the above. What you do configure, in the admin UI:
- The Application's protected path — which URL prefix the SDK should guard.
- Scopes — the named permissions your Application offers (e.g.
repo.read,repo.writefor a GitHub MCP). - Tool manifest — which tools require which scopes. Published by the SDK; reviewed in the UI before launch.
- Roles and bindings — which users get which scopes, under what conditions.
- Identity providers — where end users log in (your IdP, Google, GitHub, SAML).
All of these surface as a guided checklist on the Application detail page: Protection not verified → Needs review → Live.
Why bother with OAuth at all?
OAuth 2.1 is the protocol AI clients already speak. Claude Desktop, Codex, and every other MCP-aware client know how to do the login flow described above without you teaching them. By exposing standard OAuth endpoints, your MCP server works with everything in the ecosystem, instead of needing a custom auth scheme per client.
AuthSec implements the OAuth machinery — authorization server, JWKS endpoint, introspection, RFC 9728 protected-resource metadata, consent screens — so you don't write or operate any of it. You think in Applications, scopes, and tools; AuthSec speaks OAuth on the wire.
Where things commonly go wrong
In rough order of frequency:
- Wrong Resource URI in the SDK config. The token's
audclaim must match what your SDK validates. The admin UI shows the canonical Resource URI on the Application detail page — copy it from there. - Scope on the token doesn't match what the tool requires. Open the Application's Tools tab to see each tool's required scope. Compare to the granted scopes in the user's consent.
- Token validation always passes. You skipped the SDK and rolled your own. Send
Authorization: Bearer garbage— if you get 200, your middleware isn't running. tools/listreturns tools the user can't call. The SDK filters this automatically; if you skipped the SDK, you have to filter manually.
See Troubleshoot OAuth tokens for the four-claim debug checklist.
When you need more
The standard flow above handles 90% of cases. AuthSec also supports:
- Step-up MFA — high-risk tools that require fresh MFA, per-call.
- Conditions — bindings that only apply from specific IPs, repos, or times.
- Quotas — per-user or per-plan rate limits, enforced at the policy layer.
- Token exchange — chaining MCP servers (agent calls server A, server A calls server B with a downscoped token).
- Dynamic Client Registration — letting any AI client register without an admin step.
These ship in later phases. Track Phase E in the roadmap for ETA.
Related
- Protect your first Application — the actual 10-minute walkthrough
- Scope design for MCP tools — how to model your scopes
- JWT vs token introspection — which validation mode to pick
- Troubleshoot OAuth tokens — when something's denying when it shouldn't