mcp-oauth
A reusable OAuth 2.1 layer for MCP (Model Context Protocol) servers, designed for compatibility with Claude.ai.
What is this?
mcp-oauth is a Rust library crate that wraps your axum router with a complete OAuth 2.1 implementation — discovery endpoints, dynamic client registration, authorization with WebAuthn/passkey approval, token exchange, and Bearer token middleware. Drop it in front of your MCP server and get Claude.ai-compatible authentication out of the box.
This is not a standalone binary. You import the crate and call build_oauth_router().
Features
- OAuth 2.1 with PKCE (S256) — authorization code flow with proof key for code exchange
- Dynamic client registration (RFC 7591)
- WebAuthn / passkey authentication — passwordless approval via hardware keys or biometrics
- Token refresh — long-lived sessions via refresh tokens
- Per-IP rate limiting — three tiers (auth, registration, general)
- In-memory state with TTL-based cleanup — no database required
- Strict security —
unsafeforbidden, constant-time secret comparison, PKCE enforced
Quick start
Add to your Cargo.toml:
[]
= "0.1"
Wrap your MCP router:
use Router;
use ;
use PathBuf;
let mcp_routes = new; // your protected MCP routes
let config = with_defaults;
let app = build_oauth_router;
// Serve `app` with axum / hyper as usual.
Configuration
OAuthConfig fields:
| Field | Description | Default |
|---|---|---|
server_url |
Public-facing URL of your server | (required) |
client_id |
Pre-registered OAuth client ID | (required) |
client_secret |
Pre-registered OAuth client secret | (required) |
app_name |
Human-readable name shown on approval pages | (required) |
passkey_store_path |
Path to JSON file for persisting registered passkeys | (required) |
setup_token |
One-time token for first passkey registration | None |
token_lifetime_secs |
Access token lifetime | 86400 (24h) |
code_lifetime_secs |
Authorization code lifetime | 300 (5min) |
OAuth flow
- Discovery —
/.well-known/oauth-protected-resourceand/.well-known/oauth-authorization-server - Client registration —
POST /register(RFC 7591, optional) - Authorization —
GET /authorizerenders a WebAuthn/passkey approval page - Token exchange —
POST /tokensupportsauthorization_codeandrefresh_tokengrants - Protected routes — Bearer token middleware validates access tokens on your MCP endpoints
Security
- No
unsafecode (#![forbid(unsafe_code)]) - Constant-time secret comparison via
subtle - PKCE S256 enforced (no plain)
- Per-IP rate limiting via
governor - Supply-chain auditing via
cargo-deny
See SECURITY.md for vulnerability reporting.
License
Licensed under either of
at your option.
Contribution
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.