Crate oauth2_test_server

Crate oauth2_test_server 

Source
Expand description

§Rust OAuth2 Server

A complete, standards-compliant OAuth 2.0 and OpenID Connect 1.0 Authorization Server, implemented in pure Rust using Axum. This server is specially designed to support testing authentication flow of MCP Servers and Clients, with full support for Dynamic Client Registration (DCR).

⚠️ Warning: NOT for production use - in-memory, no persistence, no rate limiting.

§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.

§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
  • Integration testing of authorization flows
  • Local development against a real OAuth provider
  • Demonstrating OAuth concepts
  • CI/CD pipeline validation

§Supported Standards

StandardImplemented
RFC 6749 – OAuth 2.0Full
RFC 6750 – Bearer TokenYes
RFC 7636 – PKCEYes (plain, S256)
RFC 7591 – Dynamic Client RegistrationYes
RFC 7662 – Token IntrospectionYes
RFC 7009 – Token RevocationYes
RFC 7519 – JWT Access Tokens (RS256)Yes
OpenID Connect Discovery 1.0Yes
OpenID Connect CorePartial (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

MethodPathDescription
GET/.well-known/openid-configurationOIDC Discovery
GET/.well-known/jwks.jsonPublic keys for JWT validation
POST/registerDynamic client registration
GET/register/:client_idRetrieve registered client
GET/authorizeAuthorization endpoint (code flow)
POST/tokenToken endpoint (all grants)
POST/introspectRFC 7662 introspection
POST/revokeRFC 7009 revocation
GET/userinfoOIDC user info (requires Bearer token)
GET/errorHuman-readable error page

§In-Memory Stores

  • clients: HashMap<String, Client> - registered clients
  • codes: HashMap<String, AuthorizationCode> - short-lived auth codes
  • tokens: 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 (S256 and plain)
  • Token revocation propagation
  • Expiration enforcement
  • Scope and redirect_uri validation

§Running

cargo run
# 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

§Example Usage

# Register a client
curl -X POST http://localhost:8090/register -H "Content-Type: application/json" -d '{
  "redirect_uris": ["http://localhost:8090/callback"],
  "grant_types": ["authorization_code"],
  "response_types": ["code"],
  "scope": "openid profile email"
}'

§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 jwt 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);
}

§Ideal For

  • Testing OAuth libraries
  • End-to-end flow validation
  • Local development
  • Security research
  • Teaching OAuth/OIDC

⚠️ Warning: Not for production use - in-memory, no persistence, no rate limiting.

Structs§

Client
IssuerConfig
JwtOptions
JwtOptionsBuilder
OAuthTestServer
Start a test server with full programmatic control.
OauthEndpoints
Token