Rust OAuth Test Server
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.
Caution
This server was developed with the purpose of supporting testing and development of the rust-mcp-sdk, and may not be maintained or updated regularly. Please consider this when integrating or using this server in other contexts.
⚠️ Warning: not for production use - in-memory, no persistence, no rate limiting.
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 |
| OpenID Connect Discovery 1.0 | Yes |
| OpenID Connect Core | Partial (UserInfo, sub, iss) |
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
- JWT Access Tokens signed with RS256 (auto-generated RSA key pair)
- Token Introspection (
POST /introspect) - 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) - no external DB required
- Full error handling with redirect errors and JSON error responses
- State parameter, scope, redirect_uri validation
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 |
/introspect |
RFC 7662 introspection |
POST |
/revoke |
RFC 7009 revocation |
GET |
/userinfo |
OIDC user info (requires Bearer token) |
GET |
/error |
Human-readable error page |
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 mapping
Security & Testing
- No persistence - perfect for isolated tests
- Auto-generated RSA key pair on startup
- PKCE verification (
S256andplain) - Token revocation propagation
- Expiration enforcement
- Scope and redirect_uri validation
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
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/register
• Token: http://127.0.0.1:8090/token
• Register: http://127.0.0.1:8090/authorize
• 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
#[tokio::test]
async fn my_oauth_test() {
let server = oauth2_test_server::OAuthTestServer::start().await;
println!("server: {}", server.base_url());
println!("authorize endpoint: {}", server.endpoints.authorize_url);
// register a client
let client = server.register_client(serde_json::json!({ "scope": "openid",
"redirect_uris":["http://localhost:8080/callback"],
"client_name": "rust-mcp-sdk"
}));
// generate a token for the client
let token = server.generate_token(&client, server.jwt_options().user_id("rustmcp").build());
assert_eq!(token.access_token.split('.').count(), 3);
assert_eq!(server.clients().read().iter().len(), 1);
assert_eq!(server.tokens().read().iter().len(), 1);
}
⚠️ Warning: not for production use - in-memory, no persistence, no rate limiting.