A fast, fully configurable, in-memory OAuth 2.0 + OpenID Connect authorization server for testing, zero-HTTP mode and DCR support for testing auth flow in MCP Servers and MCP Clients.
This server was developed with the purpose of supporting testing and development of the rust-mcp-sdk, but it works perfectly as a general-purpose auth mocking in any Rust (or non-Rust) project , unit tests, integration suites, local dev, or quick prototypes.
Refer to Key Features to find out more.
⚠️ For testing/development only
- In-memory storage (not persistent)
- No rate limiting or attack protection
- Use in test suites, CI/CD, local development
Purpose
This server implements all major OAuth 2.0 flows and OpenID Connect core features in-memory, making it ideal for:
- Testing OAuth clients (web, mobile, SPA, backend)
- Specifically tailored for testing authentication flow MCP Servers and Clients, with DCR support
- End-to-end flow validation
- Local development
- Integration testing of authorization flows
- Local development against a real OAuth provider
- Demonstrating OAuth concepts
- CI/CD pipeline validation
Supported Standards
| Standard | Implemented |
|---|---|
| RFC 6749 – OAuth 2.0 | Full |
| RFC 6750 – Bearer Token | Yes |
| RFC 7636 – PKCE | Yes (plain, S256) |
| RFC 7591 – Dynamic Client Registration | Yes |
| RFC 7662 – Token Introspection | Yes |
| RFC 7009 – Token Revocation | Yes |
| RFC 7519 – JWT Access Tokens (RS256) | Yes |
| RFC 8628 – Device Code Flow | Yes |
| OpenID Connect Discovery 1.0 | Yes |
| OpenID Connect Core 1.0 | Yes (ID Tokens, UserInfo, Claims) |
Key Features
- Dynamic Client Registration (DCR) (
POST /register) with full metadata support - Authorization Code Flow with PKCE (
/authorize,/token) - Refresh Token Flow with rotation and revocation
- Client Credentials Grant
- Device Code Flow (RFC 8628) (
/device/code,/device/token) - JWT Access Tokens signed with RS256 (auto-generated RSA key pair)
- ID Tokens with
at_hash,c_hash,nonce, standard claims - Token Introspection (
POST /introspect) with expiration checking - Token Revocation (
POST /revoke) - OpenID Connect Discovery (
.well-known/openid-configuration) - JWKS Endpoint (
.well-known/jwks.json) - UserInfo Endpoint (
GET /userinfo) - In-memory stores (clients, codes, tokens, device codes) - no external DB required
- Background TTL cleanup for expired tokens/codes
- Full error handling with redirect errors and JSON error responses
- State parameter (required by default, configurable)
- Scope, redirect_uri validation
- Authorization parameters:
prompt,max_age,claims,ui_locales,response_mode - Configurable via YAML/TOML files or environment variables
Endpoints
| Method | Path | Description |
|---|---|---|
GET |
/.well-known/openid-configuration |
OIDC Discovery |
GET |
/.well-known/jwks.json |
Public keys for JWT validation |
POST |
/register |
Dynamic client registration |
GET |
/register/:client_id |
Retrieve registered client |
GET |
/authorize |
Authorization endpoint (code flow) |
POST |
/token |
Token endpoint (all grants) |
POST |
/device/code |
Device code flow - initiate |
POST |
/device/token |
Device code flow - poll token |
POST |
/introspect |
RFC 7662 introspection |
POST |
/revoke |
RFC 7009 revocation |
GET |
/userinfo |
OIDC user info (requires Bearer token) |
GET |
/error |
Human-readable error page |
Note:
/tokenendpoint supports all OAuth2 grant types:Authorization Code,Refresh Token,Client Credentials. The Device Code flow uses separate endpoints (/device/codeand/device/token) since it's a polling mechanism, but the main/tokenendpoint handles the three most common grants.
In-Memory Stores
clients:HashMap<String, Client>- registered clientscodes:HashMap<String, AuthorizationCode>- short-lived auth codestokens:HashMap<String, Token>- access tokens (JWTs)refresh_tokens:HashMap<String, Token>- refresh token mappingdevice_codes:HashMap<String, DeviceAuthorization>- device code flow state
Security & Testing
- No persistence - perfect for isolated tests
- Auto-generated RSA key pair on startup
- PKCE verification (
S256andplain) - Token revocation propagation
- Expiration enforcement (configurable TTL)
- Background cleanup of expired tokens/codes
- Scope and redirect_uri validation
- State parameter (required by default, configurable)
- ID Token security (
at_hash,c_hashvalidation) - Configurable token expiration times
Run as a Standalone Binary (Great for Manual Testing & Debugging)
You can run the server directly from your terminal - no code required.
1. Install it globally using one of the following methods:
-
Cargo
-
Shell script
| -
PowerShell script
-
Homebrew
-
NPM
The npm package is provided for convenience. It runs the same underlying Rust binary but can be installed and used as a standard npm package.
-
Download Binaries
2. Start the server
You’ll see:
OAuth Test Server running on http://127.0.0.1:8090/
• Discovery: http://127.0.0.1:8090/.well-known/openid-configuration
• Jwks: http://127.0.0.1:8090/.well-known/jwks.json
• Authorize: http://127.0.0.1:8090/authorize
• Token: http://127.0.0.1:8090/token
• Device Code: http://127.0.0.1:8090/device/code
• Device Token: http://127.0.0.1:8090/device/token
• Register: http://127.0.0.1:8090/register
• Introspection: http://127.0.0.1:8090/introspect
• UserInfo: http://127.0.0.1:8090/userinfo
• Revoke: http://127.0.0.1:8090/revoke
Quick test with curl:
# Register a client
How to Use in Tests
Quick Start
async
Authorization Code Flow with PKCE
async
Complete Auth Flow (One-Liner)
async
Device Code Flow
async
Token Introspection & Revocation
async
Custom Token Generation (for unit tests)
async
Loading from Config File
async
Migration Guide
Upgrading from 0.1.x to 0.2.x
1. Methods are now async - Add .await:
// Before (0.1.x)
let client = server.register_client;
let token = server.generate_token;
// After (0.2.x)
let client = server.register_client.await;
let token = server.generate_token.await;
2. Accessor methods return Vec instead of Arc<RwLock<HashMap>>:
// Before (0.1.x)
assert_eq!;
// After (0.2.x)
assert_eq!;
// Or for mutation (reset state between tests):
server.clear_all.await;