A complete, production-ready OAuth2 authorization server built with Rust and Actix-web, featuring the actor model for concurrency, type safety, and comprehensive observability.
The Rust OAuth2 Server is a high-performance, secure, and scalable OAuth2 implementation designed for modern cloud-native applications. Built with Rust's safety guarantees and Actix's actor model, it provides enterprise-grade authentication and authorization services.
graph LR
A[Web Apps] -->|OAuth2| S[OAuth2 Server]
B[Mobile Apps] -->|OAuth2| S
C[Services] -->|OAuth2| S
S -->|Issues| T[JWT Tokens]
T -->|Authorize| API[Protected APIs]
style S fill:#ff9800,color:#fff
style T fill:#4caf50,color:#fff
- β Authorization Code Flow with PKCE support
- β Client Credentials Flow for service-to-service
- β Resource Owner Password Credentials Flow
- β Refresh Token Flow with rotation
- β Token Introspection (RFC 7662)
- β Token Revocation (RFC 7009)
- β Discovery Endpoint (RFC 8414)
- π Actor Model using Actix for concurrent request handling
- π Type-Safe Rust implementation
- π JWT Tokens with configurable expiration
- πΎ Database Support (SQLite/PostgreSQL via SQLx, optional MongoDB via
--features mongo) - ποΈ Flyway Migrations for database schema management
- π‘ Comprehensive Event System - Emit events for all auth operations
- π§ Configurable Filtering - Include/exclude specific event types
- π Pluggable Backends - In-memory, console, and extensible for Redis/Kafka/RabbitMQ
- π― Actor-Based - Non-blocking, concurrent event processing
- π Rich Metadata - Events include user/client IDs, timestamps, and custom data
- π‘οΈ Audit-Ready - Perfect for compliance and security monitoring
- See Eventing Documentation for details
- π Prometheus Metrics - Request rates, token metrics, database performance
- π OpenTelemetry Tracing - Distributed tracing with OTLP export
- π Structured Logging - JSON logs with correlation IDs
- β€οΈ Health & Readiness Checks - Kubernetes-ready endpoints
- π Admin Dashboard - Web-based monitoring and management
- π OpenAPI 3.0 Specification - Auto-generated from code
- π¨ Swagger UI - Interactive API documentation
- π Admin Control Panel - Web-based administration interface
- π€ MCP Server - Model Context Protocol server for AI integration
- π³ Docker - Container images with multi-stage builds
- βΈοΈ Kubernetes - Production-ready manifests with Kustomize
- π CI/CD - GitHub Actions with E2E testing
- π¦ Helm - (Planned) Helm charts for easy deployment
- π PKCE Support (Proof Key for Code Exchange)
- π Secure Client Credentials generation
- π‘οΈ Scope-based Authorization
- π« Token Revocation
- π Social Login Integration (Google, Microsoft, GitHub, Azure, Okta, Auth0)
- π« Session Management with secure cookies
β οΈ Rate Limiting (planned)
- Rust 1.70 or higher
- SQLite or PostgreSQL (default)
- MongoDB (optional, only if you want to run with
--features mongo) - Docker (optional, for containerized deployment)
- Flyway (optional, or use Docker for migrations)
git clone https://github.com/ianlintner/rust_oauth2_server.git
cd rust_oauth2_serverUsing the provided script (uses Docker if Flyway not installed):
./scripts/migrate.shOr using Docker directly:
docker run --rm \
-v "$(pwd)/migrations/sql:/flyway/sql" \
-v "$(pwd)/flyway.conf:/flyway/conf/flyway.conf" \
flyway/flyway:10-alpine migratecargo build --releasecargo runcargo run --releasedocker-compose up -dDeploy to Kubernetes using Kustomize:
# Development
kubectl apply -k k8s/overlays/dev
# Staging
kubectl apply -k k8s/overlays/staging
# Production
kubectl apply -k k8s/overlays/productionSee Kubernetes Deployment Guide for detailed instructions.
The project includes a Model Context Protocol (MCP) server that enables AI assistants like Claude to interact with the OAuth2 server through natural language commands.
- Register and manage OAuth2 clients
- Generate and manage access tokens
- Introspect and revoke tokens
- Check server health and metrics
- Access OpenID configuration
cd mcp-server
npm install
cp .env.example .env
# Edit .env with your OAuth2 server URLAdd to your Claude Desktop configuration:
macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
{
"mcpServers": {
"oauth2-server": {
"command": "node",
"args": ["/path/to/rust_oauth2_server/mcp-server/src/index.js"],
"env": {
"OAUTH2_BASE_URL": "http://localhost:8080"
}
}
}
}Once configured, you can ask your AI assistant:
- "Register a new OAuth2 client called 'My App'"
- "Get an access token for client ID abc123"
- "Check the health status of the OAuth2 server"
- "Show me the server metrics"
See MCP Server Documentation for more details.
The OAuth2 server uses HOCON (Human-Optimized Config Object Notation) for configuration, providing a human-readable format with powerful features like:
- Comments and documentation within config files
- Nested configuration structures
- Environment variable substitution with
${?VAR}syntax - Value composition and inheritance
- Fallback to environment variables for backward compatibility
The server loads configuration in the following priority order:
- HOCON file (
application.conf) - Main configuration file with sensible defaults - Environment variables - Override any HOCON setting using
OAUTH2_*prefix - Fallback defaults - Built-in defaults if no configuration is provided
Copy the example configuration:
cp application.conf.example application.confThen edit application.conf to customize your settings, or use environment variables to override specific values.
Using HOCON file (application.conf):
# Server Configuration
server {
host = "127.0.0.1" # Override with OAUTH2_SERVER_HOST
port = 8080 # Override with OAUTH2_SERVER_PORT
}
# Database Configuration
database {
# SQLite (default)
url = "sqlite:oauth2.db"
# PostgreSQL
# url = "postgresql://oauth2_user:password@localhost:5432/oauth2"
# MongoDB (requires building with --features mongo)
# url = "mongodb://localhost:27017/oauth2"
# Override with OAUTH2_DATABASE_URL
}
# JWT Configuration
jwt {
# MUST be changed for production (minimum 32 characters)
# Generate with: openssl rand -base64 48
secret = "insecure-default-for-testing-only-change-in-production"
# Override with OAUTH2_JWT_SECRET
}Using Environment Variables (legacy method, still fully supported):
export OAUTH2_SERVER_HOST=127.0.0.1
export OAUTH2_SERVER_PORT=8080
export OAUTH2_DATABASE_URL=sqlite:oauth2.db
export OAUTH2_JWT_SECRET=your-secret-key-change-in-productionConfigure the authentication eventing system using HOCON or environment variables:
Using HOCON (application.conf):
events {
enabled = true # Override with OAUTH2_EVENTS_ENABLED
backend = "in_memory" # Override with OAUTH2_EVENTS_BACKEND
filter_mode = "allow_all" # Override with OAUTH2_EVENTS_FILTER_MODE
# Redis Streams backend (requires --features events-redis)
redis {
url = "redis://127.0.0.1:6379"
stream = "oauth2_events"
maxlen = null # Optional max length
}
# Kafka backend (requires --features events-kafka)
kafka {
brokers = "127.0.0.1:9092"
topic = "oauth2_events"
client_id = null # Optional client ID
}
# RabbitMQ backend (requires --features events-rabbit)
rabbit {
url = "amqp://127.0.0.1:5672/%2f"
exchange = "oauth2.events"
routing_key = "oauth2.event"
}
}Using Environment Variables:
# Enable/disable events (default: true)
export OAUTH2_EVENTS_ENABLED=true
# Backend options: in_memory, console, both, redis, kafka, rabbit
export OAUTH2_EVENTS_BACKEND=console
# Filter mode: allow_all, include, or exclude (default: allow_all)
export OAUTH2_EVENTS_FILTER_MODE=include
# Event types (comma-separated, used with include/exclude modes)
export OAUTH2_EVENTS_TYPES=token_created,token_revoked,client_registered
# Redis Streams (requires --features events-redis)
export OAUTH2_EVENTS_REDIS_URL=redis://localhost:6379
export OAUTH2_EVENTS_REDIS_STREAM=oauth2:events
export OAUTH2_EVENTS_REDIS_MAXLEN=10000
# Kafka (requires --features events-kafka)
export OAUTH2_EVENTS_KAFKA_BROKERS=localhost:9092
export OAUTH2_EVENTS_KAFKA_TOPIC=oauth2-events
export OAUTH2_EVENTS_KAFKA_CLIENT_ID=rust-oauth2-server
# RabbitMQ (requires --features events-rabbit)
export OAUTH2_EVENTS_RABBIT_URL=amqp://guest:guest@localhost:5672/%2f
export OAUTH2_EVENTS_RABBIT_EXCHANGE=oauth2.events
export OAUTH2_EVENTS_RABBIT_ROUTING_KEY=auth.*See Eventing Documentation and Examples for more details.
Configure social login providers using HOCON or environment variables. Providers are only enabled when their credentials are provided.
Using HOCON (application.conf):
social {
google {
enabled = false # Set to true and provide credentials to enable
# These values are loaded from environment variables:
# OAUTH2_GOOGLE_CLIENT_ID
# OAUTH2_GOOGLE_CLIENT_SECRET
# OAUTH2_GOOGLE_REDIRECT_URI
}
microsoft {
enabled = false
# OAUTH2_MICROSOFT_CLIENT_ID
# OAUTH2_MICROSOFT_CLIENT_SECRET
# OAUTH2_MICROSOFT_REDIRECT_URI
# OAUTH2_MICROSOFT_TENANT_ID (optional, defaults to "common")
}
github {
enabled = false
# OAUTH2_GITHUB_CLIENT_ID
# OAUTH2_GITHUB_CLIENT_SECRET
# OAUTH2_GITHUB_REDIRECT_URI
}
okta {
enabled = false
# OAUTH2_OKTA_CLIENT_ID
# OAUTH2_OKTA_CLIENT_SECRET
# OAUTH2_OKTA_REDIRECT_URI
# OAUTH2_OKTA_DOMAIN (required)
}
auth0 {
enabled = false
# OAUTH2_AUTH0_CLIENT_ID
# OAUTH2_AUTH0_CLIENT_SECRET
# OAUTH2_AUTH0_REDIRECT_URI
# OAUTH2_AUTH0_DOMAIN (required)
}
}Using Environment Variables:
export OAUTH2_GOOGLE_CLIENT_ID=your-google-client-id
export OAUTH2_GOOGLE_CLIENT_SECRET=your-google-client-secret
export OAUTH2_GOOGLE_REDIRECT_URI=http://localhost:8080/auth/callback/googleexport OAUTH2_MICROSOFT_CLIENT_ID=your-microsoft-client-id
export OAUTH2_MICROSOFT_CLIENT_SECRET=your-microsoft-client-secret
export OAUTH2_MICROSOFT_REDIRECT_URI=http://localhost:8080/auth/callback/microsoft
export OAUTH2_MICROSOFT_TENANT_ID=common # or your tenant IDexport OAUTH2_GITHUB_CLIENT_ID=your-github-client-id
export OAUTH2_GITHUB_CLIENT_SECRET=your-github-client-secret
export OAUTH2_GITHUB_REDIRECT_URI=http://localhost:8080/auth/callback/githubexport OAUTH2_OKTA_CLIENT_ID=your-okta-client-id
export OAUTH2_OKTA_CLIENT_SECRET=your-okta-client-secret
export OAUTH2_OKTA_REDIRECT_URI=http://localhost:8080/auth/callback/okta
export OAUTH2_OKTA_DOMAIN=your-okta-domain.okta.comexport OAUTH2_AUTH0_CLIENT_ID=your-auth0-client-id
export OAUTH2_AUTH0_CLIENT_SECRET=your-auth0-client-secret
export OAUTH2_AUTH0_REDIRECT_URI=http://localhost:8080/auth/callback/auth0
export OAUTH2_AUTH0_DOMAIN=your-tenant.auth0.comGET /- Redirects to login pageGET /auth/login- Modern login page with social login optionsGET /error- Error page with detailed error information
GET /auth/login/google- Initiate Google loginGET /auth/login/microsoft- Initiate Microsoft/Azure AD loginGET /auth/login/github- Initiate GitHub loginGET /auth/login/azure- Initiate Azure AD loginGET /auth/login/okta- Initiate Okta loginGET /auth/login/auth0- Initiate Auth0 loginGET /auth/callback/{provider}- OAuth callback handlerGET /auth/success- Authentication success pagePOST /auth/logout- Logout endpoint
GET /oauth/authorize- Authorization endpointPOST /oauth/token- Token endpointPOST /oauth/introspect- Token introspectionPOST /oauth/revoke- Token revocation
POST /clients/register- Register a new OAuth2 client
GET /.well-known/openid-configuration- OAuth2 server metadata
GET /admin- Admin dashboardGET /health- Health check endpointGET /ready- Readiness check endpointGET /metrics- Prometheus metrics
GET /swagger-ui- Interactive API documentation
The server exposes Prometheus metrics at /metrics:
oauth2_server_http_requests_total- Total HTTP requestsoauth2_server_http_request_duration_seconds- Request duration histogramoauth2_server_oauth_token_issued_total- Tokens issued counteroauth2_server_oauth_token_revoked_total- Tokens revoked counteroauth2_server_oauth_clients_total- Total registered clientsoauth2_server_oauth_active_tokens- Active tokens gaugeoauth2_server_db_queries_total- Database queries counteroauth2_server_db_query_duration_seconds- DB query duration histogram
The server exports traces to an OTLP endpoint (default: http://localhost:4317). Configure your OpenTelemetry collector to receive traces.
Example with Jaeger:
docker run -d --name jaeger \
-p 4317:4317 \
-p 16686:16686 \
jaegertracing/all-in-one:latestThen access Jaeger UI at http://localhost:16686
cargo testcargo test --test integrationcargo test --test bddcurl -X POST http://localhost:8080/clients/register \
-H "Content-Type: application/json" \
-d '{
"client_name": "My Application",
"redirect_uris": ["http://localhost:3000/callback"],
"grant_types": ["authorization_code", "refresh_token"],
"scope": "read write"
}'- Get Authorization Code:
http://localhost:8080/oauth/authorize?response_type=code&client_id=CLIENT_ID&redirect_uri=http://localhost:3000/callback&scope=read
- Exchange Code for Token:
curl -X POST http://localhost:8080/oauth/token \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=authorization_code&code=AUTH_CODE&redirect_uri=http://localhost:3000/callback&client_id=CLIENT_ID&client_secret=CLIENT_SECRET"curl -X POST http://localhost:8080/oauth/token \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=client_credentials&client_id=CLIENT_ID&client_secret=CLIENT_SECRET&scope=read"curl -X POST http://localhost:8080/oauth/introspect \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "token=ACCESS_TOKEN"The server uses the Actor model for concurrent, fault-tolerant request handling:
graph TB
subgraph "Client Layer"
Client1[Web Apps]
Client2[Mobile Apps]
Client3[Services]
end
subgraph "OAuth2 Server"
LB[Load Balancer]
MW[Middleware Stack]
subgraph "Handlers"
OAuth[OAuth Handler]
Token[Token Handler]
ClientH[Client Handler]
end
subgraph "Actor System"
TokenA[Token Actor]
ClientA[Client Actor]
AuthA[Auth Actor]
end
end
subgraph "Data & Observability"
DB[(Database)]
Metrics[Prometheus]
Traces[Jaeger]
end
Client1 --> LB
Client2 --> LB
Client3 --> LB
LB --> MW
MW --> OAuth
MW --> Token
MW --> ClientH
OAuth --> AuthA
Token --> TokenA
ClientH --> ClientA
TokenA --> DB
ClientA --> DB
AuthA --> DB
MW --> Metrics
MW --> Traces
style LB fill:#ff9800,color:#fff
style TokenA fill:#4caf50,color:#fff
style ClientA fill:#2196f3,color:#fff
style AuthA fill:#9c27b0,color:#fff
style DB fill:#f3e5f5
- Actix-Web Server: High-performance async HTTP server
- Actor Model: Isolated, concurrent request processing
- SQLx Database: Compile-time verified queries
- JWT Tokens: Stateless authentication
- Middleware Stack: Metrics, tracing, CORS, authentication
- OpenTelemetry: Distributed tracing and observability
graph LR
subgraph AuthCodeFlow["Authorization Code Flow"]
User1[User] -->|Login| Auth1["/oauth/authorize"]
Auth1 -->|Code| Client1[Client]
Client1 -->|Exchange| Token1["/oauth/token"]
Token1 -->|Access Token| Client1
end
subgraph ClientCredsFlow["Client Credentials Flow"]
Service[Service] -->|Credentials| Token2["/oauth/token"]
Token2 -->|Access Token| Service
end
style Auth1 fill:#4caf50,color:#fff
style Token1 fill:#2196f3,color:#fff
style Token2 fill:#2196f3,color:#fff
For detailed architecture documentation, see Architecture Overview.
Contributions are welcome! Please feel free to submit a Pull Request.
For development guidelines, see Contributing Guide.
Comprehensive documentation is available in the /docs directory:
- Getting Started - Installation and quick start
- Configuration - Complete configuration guide
- Architecture - System design and components
- OAuth2 Flows - Detailed flow documentation
- API Reference - Endpoint documentation
- Deployment - Production deployment guides
- Kubernetes Deployment - K8s manifests and guides
- MCP Server - AI integration with Model Context Protocol
- Observability - Monitoring and troubleshooting
For AI-assisted development and operations, see:
- Development Agent - Coding guidelines and development workflow
- Operations Agent - Deployment and troubleshooting
- Database Agent - Database management and optimization
- Security Agent - Security best practices and guidelines
This project is licensed under either of:
- MIT License
- Apache License, Version 2.0
at your option.
- OAuth 2.0 RFC 6749
- PKCE RFC 7636
- Token Introspection RFC 7662
- Token Revocation RFC 7009
- Actix Web Documentation
- Keycloak - Inspiration for feature set
