| Crates.io | auth-framework |
| lib.rs | auth-framework |
| version | 0.4.2 |
| created_at | 2025-07-09 02:35:50.406163+00 |
| updated_at | 2025-08-24 16:41:33.519446+00 |
| description | A comprehensive, production-ready authentication and authorization framework for Rust applications |
| homepage | |
| repository | https://github.com/ciresnave/auth-framework |
| max_upload_size | |
| id | 1744004 |
| size | 7,237,058 |

Production-ready โข Enterprise-grade โข Security-first โข Bulletproof
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.
๐ Security Notice: This framework requires a JWT secret to be configured before use. See
SECURITY_GUIDE.mdfor 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.mdfor details.
v0.4.2 introduces significant reliability and quality improvements:
Previous Major Features (v0.3.0):
config crate for multi-format configuration supportConfiguration Highlights:
oauth-device-flows integrationThe new token-to-profile conversion utilities make it easier to work with OAuth providers and user profiles:
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());
Version 0.3.0 adds more convenient constructors for device flow credentials:
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"]
);
Add this to your Cargo.toml:
[dependencies]
auth-framework = "0.2.0"
tokio = { version = "1.0", features = ["full"] }
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>> {
// Set environment for development/testing (allows memory storage)
std::env::set_var("ENVIRONMENT", "development");
// Configure the auth framework with required JWT secret
let jwt_secret = std::env::var("JWT_SECRET")
.unwrap_or_else(|_| "your-secure-jwt-secret-at-least-32-characters-long".to_string());
let config = AuthConfig::new()
.token_lifetime(Duration::from_secs(3600))
.refresh_token_lifetime(Duration::from_secs(86400 * 7))
.secret(jwt_secret);
// 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-secure-jwt-secret-at-least-32-characters-long")
.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(())
}
Build your own OAuth 2.0 authorization server in minutes:
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(())
}
Provide OpenID Connect authentication for your applications:
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(())
}
Note: OAuth authentication is currently implemented through provider configurations and server components. For complete OAuth client flows, see the server examples in
examples/oauth2_authorization_server.rsandexamples/complete_oauth2_server_axum.rs.```rust use auth_framework::providers::OAuthProvider;
// OAuth providers are available for server implementations let github_provider = OAuthProvider::GitHub; let google_provider = OAuthProvider::Google;
// Build authorization URLs for OAuth flows let auth_url = github_provider.build_authorization_url( "your-client-id", "https://your-app.com/callback", "random-state", Some(&["user:email".to_string()]), None )?;
println!("Authorization URL: {}", auth_url);
// Exchange code for tokens (server-side) let token_response = github_provider.exchange_code( "your-client-id", "your-client-secret", "authorization-code-from-callback", "https://your-app.com/callback", None ).await?;
println!("Access token: {}", token_response.access_token);
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?;
// 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);
}
}
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);
Security Recommendation: Use PostgreSQL for optimal security. PostgreSQL eliminates the RUSTSEC-2023-0071 vulnerability present in MySQL storage.
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,
});
use auth_framework::config::{AuthConfig, StorageConfig};
let config = AuthConfig::new()
.storage(StorageConfig::Redis {
url: "redis://localhost:6379".to_string(),
key_prefix: "auth:".to_string(),
});
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);
use auth_framework::config::RateLimitConfig;
let config = AuthConfig::new()
.rate_limiting(RateLimitConfig::new(
100, // max requests
Duration::from_secs(60), // per minute
));
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)
}
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 is supported through the provider implementations. See the OAuth server examples for complete device flow implementations:
use auth_framework::providers::OAuthProvider;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Device flow is available through provider implementations
// For complete examples, see:
// - examples/oauth2_authorization_server.rs
// - examples/complete_oauth2_server_axum.rs
let provider = OAuthProvider::GitHub;
// Device flow methods are available on providers:
// provider.start_device_authorization()
// provider.poll_device_token()
// See server examples for complete implementation
println!("Check server examples for complete device flow implementation");
Ok(())
}
Auth-framework provides flexible configuration management using the config crate, supporting multiple formats, environment variables, and modular organization.
# 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"
]
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(())
}
The framework automatically maps environment variables:
# 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"
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
Auth-framework configuration seamlessly integrates into larger application configs:
# 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 - Parent app integration patternsconfig/EXAMPLES.md - Practical configuration examplesconfig/ directory - Example modular configuration filesWhen using RSA keys for JWT signing and verification, the framework supports both standard PEM formats:
PKCS#1 Format (Traditional RSA format):
-----BEGIN RSA PRIVATE KEY-----
-----END RSA PRIVATE KEY-----
PKCS#8 Format (Modern standard format, recommended):
-----BEGIN PRIVATE KEY-----
-----END PRIVATE KEY-----
Both formats are automatically detected and work seamlessly with the TokenManager:
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"
)?;
Generate RSA keys in your preferred format:
# 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.
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)Full OAuth 2.0 Authorization Server Examples:
oauth2_authorization_server.rs - Complete OAuth 2.0 server setup with client registrationcomplete_oauth2_server_axum.rs - Production-ready server with Axum web framework integrationproduction_deployments.rs - Enterprise deployment configurations for different environmentsServer Features Demonstrated:
Choose the deployment that fits your needs:
| Deployment Type | Use Case | Storage | Features |
|---|---|---|---|
| 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 |
# 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.
Contributions are welcome! Please read our Contributing Guide for details on our development process, coding standards, and how to submit pull requests.
Security is our top priority. Please review our Security Policy for:
For security issues, please email security@example.com instead of using the issue tracker.
This project is licensed under the MIT OR Apache-2.0 license.
The framework provides comprehensive testing utilities to make testing your authentication logic easy:
[dev-dependencies]
auth-framework = { version = "0.2.0", features = ["testing"] }
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 authenticationMockStorage - In-memory storage for testinghelpers::create_test_* - Helper functions for test dataThe framework provides specific error types for better error handling:
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);
}
_ => {}
}
}
OAuth providers are available for server-side implementations. See the server examples for complete provider usage:
use auth_framework::providers::{OAuthProvider, OAuthProviderConfig, UserProfile};
use std::collections::HashMap;
// Available providers for OAuth server implementations
let github_provider = OAuthProvider::GitHub;
let google_provider = OAuthProvider::Google;
let microsoft_provider = OAuthProvider::Microsoft;
// Custom provider configuration
let custom_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(),
},
};
// For complete OAuth server implementation examples, see:
// - examples/oauth2_authorization_server.rs
// - examples/complete_oauth2_server_axum.rs
The framework provides a standardized UserProfile type that works across all providers:
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();
Understanding the relationship between credentials and authentication methods:
use auth_framework::Credential;
// Password credentials -> PasswordMethod
let password_cred = Credential::password("username", "password");
// 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");
// OAuth flows are handled by the OAuth server implementation
// See server examples for complete OAuth credential handling
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
}
};
Helper utilities for integrating with CLI frameworks:
[dependencies]
auth-framework = "0.2.0"
clap = "4.0"
tokio = { version = "1.0", features = ["full"] }
use auth_framework::{AuthFramework, AuthConfig, Credential};
use auth_framework::providers::OAuthProvider;
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);
// OAuth providers are available for server-side implementations
let oauth_provider = match provider {
"github" => OAuthProvider::GitHub,
"google" => OAuthProvider::Google,
"microsoft" => OAuthProvider::Microsoft,
_ => return Err("Unsupported provider".into()),
};
println!("Selected provider: {:?}", oauth_provider);
// For complete OAuth server implementation, see:
// - examples/oauth2_authorization_server.rs
// - examples/complete_oauth2_server_axum.rs
println!("โ
Provider configuration complete!");
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(())
}