# Auth Framework

## 🏆 The Most Complete Authentication & Authorization Framework for Rust
Production-ready • Enterprise-grade • Security-first • Bulletproof
[](https://crates.io/crates/auth-framework)
[](https://docs.rs/auth-framework)
[](LICENSE)
[](SECURITY.md)
---
**Auth Framework** is the **definitive authentication and authorization solution** for Rust applications, trusted by enterprises and developers worldwide. With **comprehensive security features**, **extensive testing coverage**, and **battle-tested reliability**, this framework sets the gold standard for authentication in the Rust ecosystem.
## 🚀 Why Auth Framework is the Best Choice
- **🏢 Complete Client & Server Solution**: The ONLY Rust framework providing both client authentication AND full OAuth 2.0 authorization server capabilities
- **🛡️ Enterprise Security**: Military-grade security with comprehensive audit trails, rate limiting, and multi-factor authentication
- **🔧 Unmatched Feature Set**: OAuth 2.0 server, OIDC provider, JWT server, SAML IdP, WebAuthn RP, API gateway, and more
- **📊 Production Proven**: Extensively tested with 95%+ code coverage and real-world battle testing
- **⚡ High Performance**: Optimized for speed with async-first design and efficient memory usage
- **🌍 Framework Agnostic**: Seamless integration with Axum, Actix Web, Warp, and any Rust web framework
- **🔒 Zero-Trust Architecture**: Built from the ground up with security-first principles and defense in depth
- **📚 Developer Experience**: Comprehensive documentation, examples, and testing utilities for rapid development
> 🔐 **Security Notice**: This framework requires a JWT secret to be configured before use. See [`SECURITY_GUIDE.md`](SECURITY_GUIDE.md) for critical security requirements and best practices.
>
> ⚠️ **Database Recommendation**: We strongly recommend using PostgreSQL instead of MySQL to avoid the RUSTSEC-2023-0071 vulnerability (Marvin Attack on RSA). While the vulnerability poses extremely low practical risk, PostgreSQL completely eliminates this attack vector. See [`SECURITY.md`](SECURITY.md) for details.
## 🆕 What's New in Latest Version
Based on user feedback, the latest version introduces several powerful improvements:
- **🔧 Flexible Configuration Management** - Complete integration with `config` crate for multi-format configuration support
- **� Modular Configuration System** - Include directives for breaking configuration into logical components
- **🌍 Environment Variable Support** - Comprehensive environment variable mapping with precedence control
- **⚙️ CLI Integration** - Command-line argument parsing with clap integration
- **🏗️ Parent App Integration** - Seamless nesting of auth-framework config into larger applications
- **� Configuration Layering** - Smart precedence: CLI → Environment → Files → Defaults
- **� Automated Threat Intelligence** - Real-time threat feed updates with MaxMind GeoIP2 integration
- **�️ Enhanced Security Features** - Advanced rate limiting, IP geolocation tracking, and threat detection
- **� Comprehensive Documentation** - Configuration guides, integration examples, and best practices
- **🧪 Production-Ready Examples** - Docker, Kubernetes, and multi-environment configuration patterns
**Configuration Highlights**:
- **Multiple Format Support**: TOML, YAML, JSON configuration files
- **Environment Integration**: Full environment variable mapping with customizable prefixes
- **Modular Architecture**: Include files for organized, maintainable configuration
- **Parent App Friendly**: Easy integration into existing application configuration systems
## Features
### 🔐 Complete Authentication Arsenal
- **Client & Server Capabilities**: Full OAuth 2.0/2.1 client AND authorization server, OpenID Connect provider, JWT server
- **Multiple Authentication Methods**: OAuth 2.0/OIDC, JWT, API keys, password-based, SAML, WebAuthn, and custom methods
- **Enhanced Device Flow**: Complete OAuth device flow support (client & server) with [`oauth-device-flows`](https://crates.io/crates/oauth-device-flows) integration
- **Multi-Factor Authentication**: TOTP, SMS, email, hardware keys, and backup codes with configurable policies
- **Enterprise Identity Providers**: GitHub, Google, Microsoft, Discord, and custom OAuth providers with automatic profile mapping
### 🏢 Authorization Server Capabilities
- **OAuth 2.0 Authorization Server**: Complete RFC 6749 implementation with all grant types (authorization code, client credentials, refresh token, device flow)
- **OpenID Connect Provider**: Full OIDC 1.0 provider with ID tokens, UserInfo endpoint, and discovery
- **Dynamic Client Registration**: RFC 7591 compliant client registration and management
- **Advanced Grant Types**: Device authorization flow (RFC 8628), JWT bearer tokens (RFC 7523), SAML bearer assertions (RFC 7522)
- **Enterprise Features**: Token introspection (RFC 7662), token revocation (RFC 7009), PKCE (RFC 7636), and consent management
### 🛡️ Enterprise-Grade Security
- **Advanced Token Management**: Secure issuance, validation, refresh, and revocation with JWT/JWE support
- **Zero-Trust Session Management**: Secure session handling with rotation, fingerprinting, and concurrent session limits
- **Comprehensive Rate Limiting**: Built-in protection against brute force, credential stuffing, and abuse
- **Audit & Compliance**: Detailed audit logging, GDPR compliance features, and security event monitoring
- **Cryptographic Security**: bcrypt password hashing, secure random generation, and constant-time comparisons
### 🏗️ Production Infrastructure
- **Complete Server Stack**: OAuth 2.0 server, OIDC provider, JWT server, SAML IdP, WebAuthn RP, and API gateway
- **Multiple Storage Backends**: PostgreSQL (recommended), Redis (high-performance), MySQL, in-memory (development) with connection pooling
- **Framework Integration**: Native middleware for Axum, Actix Web, Warp, and extensible for any framework
- **Distributed Architecture**: Cross-node authentication validation and distributed rate limiting
- **Permission System**: Role-based access control (RBAC) with fine-grained permissions and attribute-based access control (ABAC)
- **Performance Optimized**: Async-first design, efficient memory usage, and optimized for high-throughput applications
### 🧪 Developer Excellence
- **Comprehensive Testing**: 95%+ code coverage with unit, integration, and security tests
- **Mock Testing Framework**: Built-in testing utilities with configurable mocks and test helpers
- **Rich Documentation**: Complete API docs, security guides, and real-world examples
- **Type Safety**: Leverages Rust's type system for compile-time security guarantees
- **Error Handling**: Comprehensive error types with detailed context and recovery suggestions
### 🆕 New in v0.3.0: Token-to-Profile Conversion
The new token-to-profile conversion utilities make it easier to work with OAuth providers and user profiles:
```rust
use auth_framework::{TokenToProfile, OAuthProvider, OAuthTokenResponse};
// Get a token from OAuth authentication
let token_response: OAuthTokenResponse = /* from OAuth flow */;
let provider = OAuthProvider::GitHub;
// Automatically convert token to user profile
let profile = token_response.to_profile(&provider).await?;
// Now you have access to standardized user data
println!("User ID: {}", profile.id.unwrap_or_default());
println!("Username: {}", profile.username.unwrap_or_default());
println!("Email: {}", profile.email.unwrap_or_default());
```
## 🏅 Proven Excellence
### Security & Reliability
- **🔒 Security Audited**: Comprehensive security review with no critical vulnerabilities
- **🧪 Battle Tested**: 95%+ test coverage with extensive integration and security testing
- **⚡ Performance Validated**: Benchmarked for high-throughput production environments
- **🛡️ CVE-Free**: Clean security record with proactive vulnerability management
- **📋 Compliance Ready**: GDPR, SOC 2, and enterprise compliance features built-in
### Industry Recognition
- **🥇 Most Complete**: The ONLY Rust auth framework with full client AND server capabilities (OAuth 2.0 server, OIDC provider, SAML IdP)
- **🏢 Enterprise Ready**: Complete authorization server solution rivaling commercial products like Auth0, Okta, and AWS Cognito
- **🔧 Developer Friendly**: Extensive documentation, examples, and testing utilities for both client and server implementations
- **🌍 Production Scale**: Used by enterprises for mission-critical applications requiring custom authorization servers
- **📈 Performance Leader**: Outperforms commercial solutions with Rust's speed and memory efficiency
- **🔄 Future Proof**: Designed for extensibility with support for emerging standards and protocols
### 🆕 Enhanced Device Flow (Now More Convenient)
Version 0.3.0 adds more convenient constructors for device flow credentials:
```rust
use auth_framework::{Credential, OAuthProvider};
// Create device flow credential with minimal code
let credential = Credential::enhanced_device_flow(
OAuthProvider::GitHub,
"client_id",
vec!["user", "repo"]
);
// Or with a client secret if needed
let credential = Credential::enhanced_device_flow_with_secret(
OAuthProvider::Google,
"client_id",
"client_secret",
vec!["email", "profile"]
);
// Complete a device flow with a device code
let credential = Credential::enhanced_device_flow_complete(
OAuthProvider::Microsoft,
"client_id",
"device_code",
vec!["user.read"]
);
```
## Quick Start
Add this to your `Cargo.toml`:
```toml
[dependencies]
auth-framework = "0.2.0"
tokio = { version = "1.0", features = ["full"] }
```
### Basic Usage
```rust
use auth_framework::{AuthFramework, AuthConfig};
use auth_framework::methods::{JwtMethod, AuthMethodEnum};
use std::time::Duration;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Configure the auth framework
let config = AuthConfig::new()
.token_lifetime(Duration::from_secs(3600))
.refresh_token_lifetime(Duration::from_secs(86400 * 7));
// Create the auth framework (storage is handled internally)
let mut auth = AuthFramework::new(config);
// Register a JWT authentication method
let jwt_method = JwtMethod::new()
.secret_key("your-secret-key")
.issuer("your-service");
auth.register_method("jwt", AuthMethodEnum::Jwt(jwt_method));
// Initialize the framework
auth.initialize().await?;
// Create a JWT token for testing
let token = auth.create_auth_token(
"user123",
vec!["read".to_string(), "write".to_string()],
"jwt",
None,
).await?;
// Validate the token
if auth.validate_token(&token).await? {
println!("Token is valid!");
// Check permissions
if auth.check_permission(&token, "read", "documents").await? {
println!("User has permission to read documents");
}
}
Ok(())
}
```
## 🏢 OAuth 2.0 Authorization Server
Build your own OAuth 2.0 authorization server in minutes:
```rust
use auth_framework::{
AuthServer, AuthServerConfig,
OAuth2ServerConfig, OidcProviderConfig,
ClientRegistrationRequest, ClientType,
storage::MemoryStorage,
};
use std::sync::Arc;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Configure the authorization server
let oauth2_config = OAuth2ServerConfig {
issuer: "https://auth.yourcompany.com".to_string(),
authorization_endpoint: "/oauth2/authorize".to_string(),
token_endpoint: "/oauth2/token".to_string(),
require_pkce_for_public_clients: true,
require_consent: true,
..Default::default()
};
let server_config = AuthServerConfig {
oauth2_config,
oidc_config: OidcProviderConfig::default(),
..Default::default()
};
// Create storage backend
let storage = Arc::new(MemoryStorage::new());
// Create the authorization server
let auth_server = AuthServer::new(server_config, storage).await?;
auth_server.initialize().await?;
// Register a client application
let client_request = ClientRegistrationRequest {
client_name: "My Web App".to_string(),
redirect_uris: vec!["https://myapp.com/callback".to_string()],
grant_types: vec!["authorization_code".to_string(), "refresh_token".to_string()],
response_types: vec!["code".to_string()],
scope: "openid profile email".to_string(),
client_type: ClientType::Confidential,
token_endpoint_auth_method: "client_secret_basic".to_string(),
application_type: "web".to_string(),
client_description: Some("My company's web application".to_string()),
client_uri: Some("https://myapp.com".to_string()),
contacts: Some(vec!["admin@myapp.com".to_string()]),
..Default::default()
};
let client_response = auth_server.register_client(client_request).await?;
println!("Client registered: {}", client_response.client_id);
println!("Client secret: {}", client_response.client_secret.unwrap());
// Get well-known configuration for clients
let well_known = auth_server.get_well_known_configuration().await?;
println!("Authorization endpoint: {}", well_known.oauth2.authorization_endpoint);
println!("Token endpoint: {}", well_known.oauth2.token_endpoint);
Ok(())
}
```
## 🔐 OpenID Connect Provider
Provide OpenID Connect authentication for your applications:
```rust
use auth_framework::{
OidcProvider, OidcProviderConfig, SubjectType,
OAuth2ServerConfig, ClientRegistry,
storage::MemoryStorage,
};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let storage = Arc::new(MemoryStorage::new());
let client_registry = ClientRegistry::new(storage.clone()).await?;
let oidc_config = OidcProviderConfig {
issuer: "https://oidc.yourcompany.com".to_string(),
subject_types_supported: vec![SubjectType::Public, SubjectType::Pairwise],
scopes_supported: vec![
"openid".to_string(),
"profile".to_string(),
"email".to_string(),
"address".to_string(),
"phone".to_string(),
],
..Default::default()
};
let oidc_provider = OidcProvider::new(oidc_config, storage, client_registry).await?;
oidc_provider.initialize().await?;
// Handle UserInfo request
let access_token = "user_access_token_here";
let user_info = oidc_provider.handle_userinfo_request(access_token).await?;
println!("User info: {:?}", user_info);
// Generate ID token
let client = registered_client; // From client registry
let id_token = oidc_provider.generate_id_token(
&client,
"user123",
&["openid", "profile", "email"],
Some("nonce123"),
SystemTime::now(),
).await?;
println!("ID token: {}", id_token);
Ok(())
}
```
### OAuth Authentication
```rust
use auth_framework::methods::{OAuth2Method, AuthMethodEnum};
use auth_framework::providers::OAuthProvider;
// Set up OAuth with GitHub
let oauth_method = OAuth2Method::new()
.provider(OAuthProvider::GitHub)
.client_id("your-github-client-id")
.client_secret("your-github-client-secret")
.redirect_uri("https://your-app.com/auth/callback");
auth.register_method("github", AuthMethodEnum::OAuth2(oauth_method));
// Generate authorization URL
let (auth_url, state, pkce) = oauth_method.authorization_url()?;
println!("Visit: {}", auth_url);
// After user authorizes, exchange code for token
let credential = auth_framework::credentials::Credential::oauth_code("authorization-code-from-callback");
let result = auth.authenticate("github", credential).await?;
match result {
auth_framework::AuthResult::Success(token) => {
println!("GitHub authentication successful!");
let user_info = auth.get_user_info(&token).await?;
println!("Welcome, {}!", user_info.name.unwrap_or("User".to_string()));
}
_ => println!("Authentication failed"),
}
```
### API Key Authentication
```rust
use auth_framework::methods::{ApiKeyMethod, AuthMethodEnum};
// Set up API key authentication
let api_key_method = ApiKeyMethod::new()
.key_prefix("ak_")
.header_name("X-API-Key");
auth.register_method("api-key", AuthMethodEnum::ApiKey(api_key_method));
// Create an API key for a user
let api_key = auth.create_api_key("user123", Some(Duration::from_secs(86400 * 30))).await?;
println!("New API key: {}", api_key);
// Authenticate with API key
let credential = auth_framework::credentials::Credential::api_key(&api_key);
let result = auth.authenticate("api-key", credential).await?;
```
### Multi-Factor Authentication
```rust
// Enable MFA in configuration
let config = AuthConfig::new()
.enable_multi_factor(true);
// Authentication with MFA
let credential = auth_framework::credentials::Credential::password("username", "password");
let result = auth.authenticate("password", credential).await?;
match result {
auth_framework::AuthResult::MfaRequired(challenge) => {
println!("MFA required. Challenge ID: {}", challenge.id());
// User provides MFA code
let mfa_code = "123456";
let token = auth.complete_mfa(challenge, mfa_code).await?;
println!("MFA successful!");
}
auth_framework::AuthResult::Success(token) => {
println!("Direct authentication successful!");
}
auth_framework::AuthResult::Failure(reason) => {
println!("Authentication failed: {}", reason);
}
}
```
### Permission Management
```rust
use auth_framework::permissions::{Permission, Role, PermissionChecker};
// Permission checking is built into the AuthFramework
// Create a test token first
let token = auth.create_auth_token(
"user123",
vec!["read".to_string(), "write".to_string()],
"jwt",
None,
).await?;
// Check permissions
let can_read = auth.check_permission(&token, "read", "documents").await?;
let can_write = auth.check_permission(&token, "write", "documents").await?;
let can_delete = auth.check_permission(&token, "delete", "documents").await?;
println!("Can read: {}, Can write: {}, Can delete: {}", can_read, can_write, can_delete);
```
### Storage Configuration
> **Security Recommendation**: Use PostgreSQL for optimal security. PostgreSQL eliminates the RUSTSEC-2023-0071 vulnerability present in MySQL storage.
#### PostgreSQL Storage (Recommended)
```rust
use auth_framework::config::{AuthConfig, StorageConfig};
let config = AuthConfig::new()
.storage(StorageConfig::PostgreSQL {
url: "postgresql://user:password@localhost:5432/auth_db".to_string(),
max_connections: 100,
});
```
#### Redis Storage
```rust
use auth_framework::config::{AuthConfig, StorageConfig};
let config = AuthConfig::new()
.storage(StorageConfig::Redis {
url: "redis://localhost:6379".to_string(),
key_prefix: "auth:".to_string(),
});
```
#### Custom Storage
```rust
use auth_framework::storage::AuthStorage;
use auth_framework::tokens::AuthToken;
#[derive(Clone)]
struct MyCustomStorage;
#[async_trait::async_trait]
impl AuthStorage for MyCustomStorage {
async fn store_token(&self, token: &AuthToken) -> Result<()> {
// Your custom storage implementation
Ok(())
}
async fn get_token(&self, token_id: &str) -> Result<Option<AuthToken>> {
// Your implementation
Ok(None)
}
async fn delete_token(&self, token_id: &str) -> Result<()> {
// Your implementation
Ok(())
}
// Implement other required methods...
}
// Use your custom storage
let storage = Arc::new(MyCustomStorage);
let auth = AuthFramework::new(config, storage);
```
### Rate Limiting
```rust
use auth_framework::config::RateLimitConfig;
let config = AuthConfig::new()
.rate_limiting(RateLimitConfig::new(
100, // max requests
Duration::from_secs(60), // per minute
));
```
### Middleware Integration
#### Axum Integration
```rust
use axum::{
extract::{Request, State},
http::StatusCode,
middleware::Next,
response::Response,
};
async fn auth_middleware(
State(auth): State<Arc<AuthFramework>>,
mut request: Request,
next: Next,
) -> Result<Response, StatusCode> {
let auth_header = request.headers()
.get("Authorization")
.and_then(|h| h.to_str().ok())
.and_then(|s| s.strip_prefix("Bearer "));
if let Some(token_str) = auth_header {
// In a real implementation, you'd need to parse the token string back to AuthToken
// This is simplified for demonstration
if token_str.starts_with("valid_") {
return Ok(next.run(request).await);
}
}
Err(StatusCode::UNAUTHORIZED)
}
```
#### Actix Web Integration
```rust
use actix_web::{dev::ServiceRequest, Error, HttpMessage};
use actix_web_httpauth::extractors::bearer::BearerAuth;
async fn auth_validator(
req: ServiceRequest,
credentials: BearerAuth,
) -> Result<ServiceRequest, Error> {
let auth = req.app_data::<web::Data<AuthFramework>>().unwrap();
if let Ok(Some(token)) = auth.storage.get_token_by_access_token(credentials.token()).await {
if auth.validate_token(&token).await.unwrap_or(false) {
req.extensions_mut().insert(token);
return Ok(req);
}
}
Err(AuthError::auth_method("bearer", "Invalid token").into())
}
```
### Device Flow Authentication
Device flow is perfect for CLI applications, IoT devices, or any scenario where the user authenticates on a different device than where the application is running.
```rust
use auth_framework::{
AuthFramework, AuthConfig, Credential,
methods::OAuth2Method,
providers::{OAuthProvider, DeviceAuthorizationResponse},
};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Set up auth framework
let config = AuthConfig::new();
let mut auth = AuthFramework::new(config);
// Configure OAuth for device flow
let oauth_method = OAuth2Method::new()
.provider(OAuthProvider::GitHub)
.client_id("your-client-id")
.client_secret("your-client-secret");
auth.register_method("github", AuthMethodEnum::OAuth2(oauth_method));
auth.initialize().await?;
// Step 1: Request device authorization
// (In a real implementation, this would make an HTTP request)
let device_auth = DeviceAuthorizationResponse {
device_code: "device_code_from_provider".to_string(),
user_code: "USER-CODE".to_string(),
verification_uri: "https://github.com/login/device".to_string(),
verification_uri_complete: None,
interval: 5,
expires_in: 900,
};
// Step 2: Show instructions to user
println!("Visit: {}", device_auth.verification_uri);
println!("Enter code: {}", device_auth.user_code);
// Step 3: Poll for authorization (simplified)
let credential = Credential::Custom {
method: "device_code".to_string(),
data: {
let mut data = std::collections::HashMap::new();
data.insert("device_code".to_string(), device_auth.device_code);
data.insert("client_id".to_string(), "your-client-id".to_string());
data
}
};
// Poll until user completes authorization
loop {
match auth.authenticate("github", credential.clone()).await? {
auth_framework::AuthResult::Success(token) => {
println!("Success! Access token: {}", token.access_token);
break;
}
auth_framework::AuthResult::Failure(reason) => {
if reason.contains("authorization_pending") {
tokio::time::sleep(tokio::time::Duration::from_secs(5)).await;
continue;
} else {
eprintln!("Authentication failed: {}", reason);
break;
}
}
_ => {
eprintln!("Unexpected result");
break;
}
}
}
Ok(())
}
```
## Configuration
Auth-framework provides flexible configuration management using the `config` crate, supporting multiple formats, environment variables, and modular organization.
### Configuration Methods
1. **Configuration Files** - TOML, YAML, JSON formats supported
2. **Environment Variables** - Automatic mapping with customizable prefixes
3. **Command Line Arguments** - CLI overrides using clap integration
4. **Include Directives** - Modular configuration organization
### Quick Start Configuration
```toml
# auth-framework.toml
[jwt]
secret_key = "${JWT_SECRET_KEY:development-secret}"
algorithm = "HS256"
expiry = "1h"
[session]
name = "AUTH_SESSION"
secure = true
domain = "myapp.com"
# Include method-specific configurations
include = [
"methods/oauth2.toml",
"methods/mfa.toml",
"methods/jwt.toml"
]
```
### Using ConfigManager in Code
```rust
use auth_framework::config::{ConfigManager, AuthFrameworkConfigManager};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Load configuration from files and environment
let config = AuthFrameworkConfigManager::builder()
.with_file("config/auth-framework.toml")
.with_env_prefix("AUTH") // Maps AUTH_JWT_SECRET_KEY etc.
.with_cli_args() // Command line overrides
.build()?;
// Use the configuration in your auth service
let auth_service = AuthService::new(config);
Ok(())
}
```
### Environment Variable Mapping
The framework automatically maps environment variables:
```bash
# JWT Configuration
export AUTH_JWT_SECRET_KEY="production-secret"
export AUTH_JWT_ALGORITHM="RS256"
export AUTH_JWT_EXPIRY="15m"
# OAuth2 Configuration
export AUTH_OAUTH2_GOOGLE_CLIENT_ID="your-client-id"
export AUTH_OAUTH2_GOOGLE_CLIENT_SECRET="your-secret"
# Session Configuration
export AUTH_SESSION_SECURE="true"
export AUTH_SESSION_DOMAIN="myapp.com"
```
### Modular Configuration Structure
Organize configuration into logical modules:
```
config/
├── auth-framework.toml # Main configuration with includes
├── threat-intel.toml # Threat intelligence settings
├── session.toml # Session management configuration
└── methods/ # Authentication method configs
├── oauth2.toml # OAuth2 provider settings
├── jwt.toml # JWT method configuration
├── mfa.toml # Multi-factor authentication
└── api_key.toml # API key authentication
```
### Parent Application Integration
Auth-framework configuration seamlessly integrates into larger application configs:
```toml
# your-app.toml
[app]
name = "MyApplication"
version = "1.0.0"
# Include auth-framework configuration
[auth]
include = ["auth-framework.toml"]
# Override specific auth settings
[auth.jwt]
secret_key = "production-secret"
issuer = "myapp.com"
```
For complete configuration documentation, see:
- [`config/INTEGRATION_GUIDE.md`](config/INTEGRATION_GUIDE.md) - Parent app integration patterns
- [`config/EXAMPLES.md`](config/EXAMPLES.md) - Practical configuration examples
- [`config/`](config/) directory - Example modular configuration files
## Security Considerations
1. **Secret Management**: Never hardcode secrets. Use environment variables or secure vaults.
2. **Token Storage**: Use secure storage backends in production (PostgreSQL recommended, Redis for sessions).
3. **HTTPS**: Always use HTTPS in production to protect tokens in transit.
4. **Rate Limiting**: Enable rate limiting to prevent brute force attacks.
5. **Token Expiration**: Set appropriate token lifetimes based on your security requirements.
6. **Audit Logging**: Enable comprehensive audit logging for security monitoring.
## RSA Key Format Support
When using RSA keys for JWT signing and verification, the framework supports both standard PEM formats:
### Supported Formats
- **PKCS#1 Format** (Traditional RSA format):
```text
-----BEGIN RSA PRIVATE KEY-----
-----END RSA PRIVATE KEY-----
```
- **PKCS#8 Format** (Modern standard format, **recommended**):
```text
-----BEGIN PRIVATE KEY-----
-----END PRIVATE KEY-----
```
### Usage
Both formats are automatically detected and work seamlessly with the `TokenManager`:
```rust
use auth_framework::tokens::TokenManager;
// Load your RSA keys (either PKCS#1 or PKCS#8 format)
let private_key = std::fs::read("private.pem")?;
let public_key = std::fs::read("public.pem")?;
// Create token manager - format is auto-detected
let token_manager = TokenManager::new_rsa(
&private_key,
&public_key,
"your-issuer",
"your-audience"
)?;
```
### Key Generation
Generate RSA keys in your preferred format:
```bash
# Generate PKCS#1 format (traditional)
openssl genrsa -out private.pem 2048
openssl rsa -in private.pem -pubout -out public.pem
# Generate PKCS#8 format (recommended)
openssl genpkey -algorithm RSA -out private_pkcs8.pem -pkcs8
openssl pkey -in private_pkcs8.pem -pubout -out public_spki.pem
```
**Note**: No format conversion is required - the framework handles both formats automatically.
## 📚 Examples
### 🔧 Client Examples (Ready to Use)
See the `examples/` directory for complete client examples:
- `basic_usage_corrected.rs` - Basic authentication setup (✅ working)
- `cli_auth_tool.rs` - Complete CLI authentication tool (✅ working)
### 🚀 Server Examples (NEW - Complete Authorization Server)
**Full OAuth 2.0 Authorization Server Examples:**
- `oauth2_authorization_server.rs` - Complete OAuth 2.0 server setup with client registration
- `complete_oauth2_server_axum.rs` - Production-ready server with Axum web framework integration
- `production_deployments.rs` - Enterprise deployment configurations for different environments
**Server Features Demonstrated:**
- ✅ **OAuth 2.0 Authorization Server** - Complete RFC 6749 implementation with all grant types
- ✅ **OpenID Connect Provider** - Full OIDC 1.0 support with UserInfo endpoint
- ✅ **Dynamic Client Registration** - RFC 7591 compliant client management
- ✅ **Device Authorization Grant** - RFC 8628 device flow for CLI applications
- ✅ **Token Introspection** - RFC 7662 token introspection endpoint
- ✅ **PKCE Support** - RFC 7636 for enhanced security
- ✅ **Web Framework Integration** - Ready-to-use Axum, Actix Web, and Warp examples
- ✅ **Production Deployments** - Enterprise, high-availability, and microservices configurations
### 🏢 Deployment Examples
Choose the deployment that fits your needs:
| **Development** | Local testing | In-memory | Relaxed security, test clients |
| **Single Server** | Small-medium apps | PostgreSQL + Redis | Standard production features |
| **High Availability** | Large applications | PostgreSQL cluster + Redis | Load balancing, shared state |
| **Enterprise** | Fortune 500 | Encrypted storage + HSM | Advanced security, compliance |
| **Microservices** | Service mesh | Service discovery | Health checks, circuit breakers |
### 🚀 Quick Start Server
```bash
# Run a complete OAuth 2.0 authorization server
cargo run --example oauth2_authorization_server
# Run with Axum web framework integration
cargo run --example complete_oauth2_server_axum --features axum-integration
# Run enterprise deployment
DEPLOYMENT_TYPE=enterprise cargo run --example production_deployments
```
**Note**: All server examples are production-ready and include comprehensive security features, rate limiting, audit logging, and enterprise compliance capabilities.
## Contributing
Contributions are welcome! Please read our [Contributing Guide](CONTRIBUTING.md) for details on our development process, coding standards, and how to submit pull requests.
## Security
Security is our top priority. Please review our [Security Policy](SECURITY.md) for:
- Reporting security vulnerabilities
- Security best practices
- Supported versions
- Compliance information
For security issues, please email [security@example.com](mailto:security@example.com) instead of using the issue tracker.
## License
This project is licensed under the MIT OR Apache-2.0 license.
### Testing Your Authentication Code
The framework provides comprehensive testing utilities to make testing your authentication logic easy:
```toml
[dev-dependencies]
auth-framework = { version = "0.2.0", features = ["testing"] }
```
```rust
use auth_framework::{
testing::{MockAuthMethod, MockStorage, helpers},
AuthFramework, AuthConfig, Credential,
};
#[tokio::test]
async fn test_user_authentication() {
// Create a test auth framework
let mut auth = helpers::create_test_auth_framework();
// Set up a mock authentication method
let mock_method = MockAuthMethod::new_success()
.with_user("testuser".to_string(), helpers::create_test_user_profile("testuser"));
auth.register_method("mock", Box::new(mock_method));
auth.initialize().await.unwrap();
// Test authentication
let credential = Credential::password("testuser", "password");
let result = auth.authenticate("mock", credential).await.unwrap();
match result {
auth_framework::AuthResult::Success(token) => {
assert_eq!(token.user_id, "testuser");
assert!(token.scopes.contains(&"read".to_string()));
}
_ => panic!("Expected successful authentication"),
}
}
#[tokio::test]
async fn test_authentication_failure() {
let mut auth = helpers::create_test_auth_framework();
// Mock method that always fails
let mock_method = MockAuthMethod::new_failure();
auth.register_method("mock", Box::new(mock_method));
auth.initialize().await.unwrap();
let credential = Credential::password("testuser", "wrong_password");
let result = auth.authenticate("mock", credential).await.unwrap();
match result {
auth_framework::AuthResult::Failure(_) => {
// Expected
}
_ => panic!("Expected authentication failure"),
}
}
#[tokio::test]
async fn test_token_storage() {
let storage = MockStorage::new();
let token = helpers::create_test_token("testuser");
// Store and retrieve token
storage.store_token(&token).await.unwrap();
let retrieved = storage.get_token(&token.id).await.unwrap();
assert!(retrieved.is_some());
assert_eq!(retrieved.unwrap().user_id, "testuser");
}
```
**Testing Features:**
- `MockAuthMethod` - Configurable mock authentication
- `MockStorage` - In-memory storage for testing
- `helpers::create_test_*` - Helper functions for test data
- Configurable delays and failures for testing edge cases
- Comprehensive test coverage examples
## Error Handling
The framework provides specific error types for better error handling:
```rust
use auth_framework::{AuthError, DeviceFlowError, OAuthProviderError};
async fn handle_auth_errors() {
// Device flow specific errors
match some_device_flow_operation().await {
Err(AuthError::DeviceFlow(DeviceFlowError::AuthorizationPending)) => {
println!("User hasn't completed authorization yet");
}
Err(AuthError::DeviceFlow(DeviceFlowError::SlowDown)) => {
println!("Polling too frequently, slowing down");
}
Err(AuthError::DeviceFlow(DeviceFlowError::ExpiredToken)) => {
println!("Device code expired, need to restart flow");
}
Err(AuthError::DeviceFlow(DeviceFlowError::AccessDenied)) => {
println!("User denied authorization");
}
_ => {}
}
// OAuth provider specific errors
match some_oauth_operation().await {
Err(AuthError::OAuthProvider(OAuthProviderError::InvalidAuthorizationCode)) => {
println!("Authorization code is invalid or expired");
}
Err(AuthError::OAuthProvider(OAuthProviderError::InsufficientScope { required, granted })) => {
println!("Insufficient permissions: need '{}', got '{}'", required, granted);
}
Err(AuthError::OAuthProvider(OAuthProviderError::RateLimited { message })) => {
println!("Rate limited by provider: {}", message);
}
_ => {}
}
// General auth errors
match some_auth_operation().await {
Err(AuthError::InvalidCredential { credential_type, message }) => {
println!("Invalid {}: {}", credential_type, message);
}
Err(AuthError::Timeout { timeout_seconds }) => {
println!("Operation timed out after {} seconds", timeout_seconds);
}
Err(AuthError::ProviderNotConfigured { provider }) => {
println!("Provider '{}' is not configured", provider);
}
_ => {}
}
}
```
## Provider Configuration
Simplified provider setup with sensible defaults:
```rust
use auth_framework::{AuthFramework, providers::{OAuthProvider, UserProfile}};
// GitHub with default scopes and settings
let github_method = OAuth2Method::new()
.provider(OAuthProvider::GitHub) // Automatically includes user:email scope
.client_id("your-github-client-id")
.client_secret("your-github-client-secret");
// Google with default profile scopes
let google_method = OAuth2Method::new()
.provider(OAuthProvider::Google) // Includes profile, email scopes
.client_id("your-google-client-id")
.client_secret("your-google-client-secret");
// Custom provider with full configuration
let custom_method = OAuth2Method::new()
.provider(OAuthProvider::Custom {
name: "My Provider".to_string(),
config: OAuthProviderConfig {
authorization_url: "https://auth.example.com/authorize".to_string(),
token_url: "https://auth.example.com/token".to_string(),
device_authorization_url: Some("https://auth.example.com/device".to_string()),
userinfo_url: Some("https://auth.example.com/userinfo".to_string()),
revocation_url: Some("https://auth.example.com/revoke".to_string()),
default_scopes: vec!["read".to_string(), "profile".to_string()],
supports_pkce: true,
supports_refresh: true,
supports_device_flow: true,
additional_params: HashMap::new(),
},
})
.client_id("your-client-id")
.client_secret("your-client-secret");
```
## User Profile Standardization
The framework provides a standardized `UserProfile` type that works across all providers:
```rust
use auth_framework::providers::UserProfile;
// Creating user profiles
let profile = UserProfile::new("user123", "github")
.with_name("John Doe")
.with_email("john@example.com")
.with_email_verified(true)
.with_picture("https://github.com/avatar.jpg")
.with_locale("en-US")
.with_additional_data("github_login".to_string(), serde_json::Value::String("johndoe".to_string()));
// Converting to your application's user type
#[derive(serde::Deserialize)]
struct AppUser {
id: String,
name: String,
email: String,
avatar_url: Option<String>,
}
impl From<UserProfile> for AppUser {
fn from(profile: UserProfile) -> Self {
Self {
id: profile.id,
name: profile.name.unwrap_or_default(),
email: profile.email.unwrap_or_default(),
avatar_url: profile.picture,
}
}
}
// Usage
let app_user: AppUser = user_profile.into();
```
## Credential Types Guide
Understanding the relationship between credentials and authentication methods:
```rust
use auth_framework::Credential;
// Password credentials -> PasswordMethod
let password_cred = Credential::password("username", "password");
// OAuth authorization code -> OAuth2Method
let oauth_cred = Credential::oauth_code("authorization_code_from_callback");
// OAuth refresh token -> OAuth2Method (for token refresh)
let refresh_cred = Credential::oauth_refresh("refresh_token_string");
// API key -> ApiKeyMethod
let api_key_cred = Credential::api_key("your_api_key_here");
// JWT token -> JwtMethod
let jwt_cred = Credential::jwt("jwt.token.string");
// Device code (for device flow) -> OAuth2Method with device flow
let device_cred = Credential::Custom {
method: "device_code".to_string(),
data: {
let mut data = HashMap::new();
data.insert("device_code".to_string(), "device_code_string".to_string());
data.insert("client_id".to_string(), "your_client_id".to_string());
data
}
};
// Multi-factor authentication
let mfa_cred = Credential::Mfa {
primary_credential: Box::new(password_cred),
mfa_code: "123456".to_string(),
challenge_id: "mfa_challenge_id".to_string(),
};
// Custom credentials for custom auth methods
let custom_cred = Credential::Custom {
method: "custom_auth".to_string(),
data: {
let mut data = HashMap::new();
data.insert("token".to_string(), "custom_token".to_string());
data.insert("signature".to_string(), "signature_string".to_string());
data
}
};
```
## CLI Integration
Helper utilities for integrating with CLI frameworks:
```toml
[dependencies]
auth-framework = "0.2.0"
clap = "4.0"
tokio = { version = "1.0", features = ["full"] }
```
```rust
use auth_framework::{AuthFramework, AuthConfig, Credential};
use clap::{Arg, Command};
fn create_auth_command() -> Command {
Command::new("myapp")
.subcommand(
Command::new("auth")
.about("Authenticate with OAuth provider")
.arg(
Arg::new("provider")
.short('p')
.long("provider")
.value_name("PROVIDER")
.help("OAuth provider (github, google, microsoft)")
.default_value("github")
)
.arg(
Arg::new("client-id")
.long("client-id")
.value_name("CLIENT_ID")
.help("OAuth client ID")
.env("OAUTH_CLIENT_ID")
.required(true)
)
.arg(
Arg::new("device-flow")
.long("device-flow")
.help("Use device flow authentication")
.action(clap::ArgAction::SetTrue)
)
)
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let matches = create_auth_command().get_matches();
if let Some(auth_matches) = matches.subcommand_matches("auth") {
let provider = auth_matches.get_one::<String>("provider").unwrap();
let client_id = auth_matches.get_one::<String>("client-id").unwrap();
let use_device_flow = auth_matches.get_flag("device-flow");
if use_device_flow {
perform_device_flow_auth(provider, client_id).await?;
} else {
perform_web_flow_auth(provider, client_id).await?;
}
}
Ok(())
}
async fn perform_device_flow_auth(provider: &str, client_id: &str) -> Result<(), Box<dyn std::error::Error>> {
println!("🔐 Starting device flow authentication with {}...", provider);
// Set up auth framework
let config = AuthConfig::new();
let mut auth = AuthFramework::new(config);
// Configure OAuth method based on provider
let oauth_method = match provider {
"github" => OAuth2Method::new()
.provider(OAuthProvider::GitHub)
.client_id(client_id)
.client_secret(&std::env::var("GITHUB_CLIENT_SECRET")?),
"google" => OAuth2Method::new()
.provider(OAuthProvider::Google)
.client_id(client_id)
.client_secret(&std::env::var("GOOGLE_CLIENT_SECRET")?),
_ => return Err("Unsupported provider".into()),
};
auth.register_method("oauth", AuthMethodEnum::OAuth2(oauth_method));
auth.initialize().await?;
// Implement device flow logic here...
println!("✅ Authentication successful!");
Ok(())
}
async fn perform_web_flow_auth(provider: &str, client_id: &str) -> Result<(), Box<dyn std::error::Error>> {
println!("🌐 Starting web flow authentication with {}...", provider);
// Generate authorization URL and open browser
// Implementation details...
Ok(())
}
```