- Add complete dark mode system with theme context and toggle - Implement dark mode toggle component in navigation menu - Add client-side routing with SSR-safe signal handling - Fix language selector styling for better dark mode compatibility - Add documentation system with mdBook integration - Improve navigation menu with proper external/internal link handling - Add comprehensive project documentation and configuration - Enhance theme system with localStorage persistence - Fix arena panic issues during server-side rendering - Add proper TypeScript configuration and build optimizations 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
13 KiB
13 KiB
Authentication & Authorization System
A comprehensive authentication and authorization system built with Rust, featuring JWT tokens, OAuth2 integration, role-based access control (RBAC), and secure session management.
🚀 Features
Core Authentication
- JWT Token Authentication - Secure token-based authentication with access and refresh tokens
- Password-based Authentication - Secure password hashing using Argon2
- Session Management - Secure session handling with HTTP-only cookies
- Password Reset - Secure password reset flow with time-limited tokens
OAuth2 Integration
- Google OAuth - Sign in with Google accounts
- GitHub OAuth - Sign in with GitHub accounts
- Discord OAuth - Sign in with Discord accounts
- Microsoft OAuth - Sign in with Microsoft accounts
- Extensible - Easy to add custom OAuth providers
Authorization (RBAC)
- Role-Based Access Control - Flexible role system with built-in roles
- Fine-grained Permissions - Permission-based access control
- Custom Roles - Support for custom role definitions
- Middleware Protection - Route-level authorization middleware
Security Features
- CSRF Protection - Built-in CSRF token validation
- Rate Limiting - Configurable rate limiting for auth endpoints
- Security Headers - Comprehensive security headers
- Password Strength - Configurable password complexity requirements
- Token Blacklisting - Ability to invalidate tokens
- Audit Logging - Complete audit trail for user actions
📋 Architecture
Backend Components
auth/service.rs- Main authentication serviceauth/jwt.rs- JWT token managementauth/oauth.rs- OAuth2 provider integrationauth/password.rs- Password hashing and validationauth/repository.rs- Database operationsauth/middleware.rs- Authentication middlewareauth/routes.rs- HTTP API endpoints
Frontend Components
auth/context.rs- React-style auth contextauth/login.rs- Login form component- Auth Guards - Route protection components
Database Schema
users- User accounts and profilesuser_roles- Role assignmentsoauth_accounts- OAuth provider linkssessions- Session managementtokens- Security tokenspermissions- System permissionsrole_permissions- Role-permission mappingsuser_audit_log- Audit trail
🔧 Installation & Setup
1. Database Setup
# Create PostgreSQL database
createdb rustelo_dev
# Run migrations
psql rustelo_dev < migrations/001_create_auth_tables.sql
2. Environment Configuration
Create a .env file with the following variables:
# Database
DATABASE_URL=postgres://username:password@localhost:5432/rustelo_dev
# JWT Configuration
JWT_SECRET=your-super-secret-jwt-key-change-this-in-production
JWT_ISSUER=rustelo-auth
JWT_ACCESS_TOKEN_EXPIRES_IN=15 # minutes
JWT_REFRESH_TOKEN_EXPIRES_IN=7 # days
# Password Security
# Argon2 uses secure defaults, no configuration needed
# OAuth Configuration (optional)
OAUTH_REDIRECT_BASE_URL=http://localhost:3030/api/auth/oauth/callback
# Google OAuth
GOOGLE_CLIENT_ID=your-google-client-id
GOOGLE_CLIENT_SECRET=your-google-client-secret
# GitHub OAuth
GITHUB_CLIENT_ID=your-github-client-id
GITHUB_CLIENT_SECRET=your-github-client-secret
# Discord OAuth
DISCORD_CLIENT_ID=your-discord-client-id
DISCORD_CLIENT_SECRET=your-discord-client-secret
# Microsoft OAuth
MICROSOFT_CLIENT_ID=your-microsoft-client-id
MICROSOFT_CLIENT_SECRET=your-microsoft-client-secret
MICROSOFT_TENANT_ID=common
3. Dependencies
The system automatically includes all necessary dependencies. Key dependencies include:
jsonwebtoken- JWT token handlingargon2- Password hashingoauth2- OAuth2 client implementationsqlx- Database operationstower-cookies- Cookie managementreqwest- HTTP client for OAuth
🔐 Usage
Backend Usage
Basic Authentication Service
use auth::{AuthService, AuthRepository, JwtService, OAuthService, PasswordService};
use std::sync::Arc;
// Initialize services
let auth_repo = Arc::new(AuthRepository::new(pool));
let jwt_service = Arc::new(JwtService::new()?);
let oauth_service = Arc::new(OAuthService::new()?);
let password_service = Arc::new(PasswordService::new());
let auth_service = Arc::new(AuthService::new(
jwt_service,
oauth_service,
password_service,
auth_repo,
));
Protecting Routes
use auth::middleware::{require_auth, require_admin, require_permission};
use shared::auth::Permission;
// Require authentication
app.route("/protected", get(handler))
.layer(axum::middleware::from_fn(require_auth));
// Require admin role
app.route("/admin", get(admin_handler))
.layer(axum::middleware::from_fn(require_admin));
// Require specific permission
app.route("/users", get(users_handler))
.layer(axum::middleware::from_fn(require_permission(Permission::ReadUsers)));
Custom Authorization
use auth::middleware::{AuthContext, extract_user_from_request};
async fn protected_handler(request: Request) -> Result<Response, Error> {
let user = extract_user_from_request(&request)?;
if !user.has_permission(&Permission::WriteContent) {
return Err(AuthError::InsufficientPermissions.into());
}
// Handler logic here
Ok(Response::new("Success"))
}
Frontend Usage
Authentication Context
use leptos::prelude::*;
use auth::{AuthProvider, use_auth};
#[component]
fn App() -> impl IntoView {
view! {
<AuthProvider>
<Router>
<Routes>
<Route path="/login" view=LoginPage />
<Route path="/dashboard" view=ProtectedPage />
</Routes>
</Router>
</AuthProvider>
}
}
Using Authentication
#[component]
fn LoginPage() -> impl IntoView {
let auth = use_auth();
let login = move |email: String, password: String| {
(auth.0.actions.login)(email, password, false);
};
view! {
<div>
<Show when=move || auth.0.is_authenticated()>
<p>"Welcome, " {move || auth.0.user().map(|u| u.display_name_or_username().to_string()).unwrap_or_default()}</p>
</Show>
<LoginForm />
</div>
}
}
Route Protection
#[component]
fn ProtectedPage() -> impl IntoView {
let auth = use_auth();
view! {
<Show
when=move || auth.0.is_authenticated()
fallback=move || view! { <Redirect path="/login" /> }
>
<div>"Protected content"</div>
</Show>
}
}
🛡️ Security Features
Password Security
- Argon2 Hashing - State-of-the-art password hashing algorithm
- Secure Defaults - Uses recommended Argon2id variant with secure parameters
- Strength Validation - Enforced password complexity
- Common Password Detection - Prevents weak passwords
Token Security
- JWT with HS256 - Secure token signing
- Short-lived Access Tokens - Default 15-minute expiration
- Refresh Token Rotation - Secure token refresh
- Token Blacklisting - Ability to invalidate tokens
Session Security
- HTTP-Only Cookies - Prevents XSS attacks
- Secure Cookies - HTTPS-only transmission
- SameSite Protection - CSRF prevention
- Session Expiration - Automatic cleanup
OAuth Security
- PKCE Support - Proof Key for Code Exchange
- State Parameter - CSRF protection
- Secure Redirects - Validated redirect URLs
- Token Validation - Proper token verification
🔄 API Endpoints
Authentication Endpoints
| Method | Endpoint | Description | Auth Required |
|---|---|---|---|
| POST | /api/auth/register |
Register new user | No |
| POST | /api/auth/login |
Login with credentials | No |
| POST | /api/auth/logout |
Logout current user | Yes |
| POST | /api/auth/refresh |
Refresh access token | No |
| GET | /api/auth/profile |
Get user profile | Yes |
| PUT | /api/auth/profile |
Update user profile | Yes |
| POST | /api/auth/change-password |
Change password | Yes |
OAuth Endpoints
| Method | Endpoint | Description | Auth Required |
|---|---|---|---|
| GET | /api/auth/oauth/providers |
List OAuth providers | No |
| GET | /api/auth/oauth/:provider/authorize |
Get OAuth URL | No |
| GET | /api/auth/oauth/:provider/callback |
Handle OAuth callback | No |
Password Reset Endpoints
| Method | Endpoint | Description | Auth Required |
|---|---|---|---|
| POST | /api/auth/password-reset/request |
Request password reset | No |
| POST | /api/auth/password-reset/confirm |
Confirm password reset | No |
Admin Endpoints
| Method | Endpoint | Description | Auth Required |
|---|---|---|---|
| GET | /api/auth/admin/users/:id |
Get user by ID | Admin |
| POST | /api/auth/admin/users/:id/verify-email |
Verify user email | Admin |
| POST | /api/auth/admin/cleanup |
Clean expired data | Admin |
🎯 Role-Based Access Control
Default Roles
- Admin - Full system access
- Moderator - Content management
- User - Standard user access
- Guest - Read-only access
Default Permissions
- ReadUsers - View user information
- WriteUsers - Create/update users
- DeleteUsers - Delete users
- ReadContent - View content
- WriteContent - Create/update content
- DeleteContent - Delete content
- ManageRoles - Manage user roles
- ManageSystem - System administration
Custom Roles
// Add custom role
auth_service.repository.assign_role(user_id, Role::Custom("editor".to_string())).await?;
// Check custom role
if user.has_role(&Role::Custom("editor".to_string())) {
// Allow editor actions
}
📊 Audit Logging
All authentication events are logged:
- User registration
- Login/logout events
- Password changes
- Profile updates
- Role changes
- OAuth authentications
Access logs via:
SELECT * FROM user_audit_log WHERE user_id = $1 ORDER BY created_at DESC;
🔧 Maintenance
Cleanup Expired Data
// Manual cleanup
auth_service.cleanup_expired().await?;
// Or via SQL function
SELECT cleanup_expired_auth_data();
Database Maintenance
-- Vacuum tables periodically
VACUUM ANALYZE users;
VACUUM ANALYZE sessions;
VACUUM ANALYZE tokens;
VACUUM ANALYZE user_audit_log;
🚨 Common Issues
JWT Token Issues
- Invalid Token - Check JWT_SECRET consistency
- Token Expired - Implement refresh token logic
- Clock Skew - Ensure server time synchronization
OAuth Issues
- Callback Errors - Verify redirect URLs match exactly
- Provider Errors - Check client ID/secret configuration
- PKCE Failures - Ensure PKCE verifier storage
Database Issues
- Connection Errors - Verify DATABASE_URL
- Migration Failures - Check PostgreSQL version compatibility
- Performance Issues - Ensure proper indexing
📈 Performance Considerations
Database Optimization
- Indexes - All critical queries are indexed
- Connection Pooling - SQLx connection pool
- Query Optimization - Efficient join queries
Caching
- JWT Verification - Cache public keys
- User Data - Consider Redis for session storage
- Rate Limiting - In-memory or Redis-based
Monitoring
- Metrics - Track authentication success/failure rates
- Logging - Comprehensive audit logging
- Health Checks - Database connection monitoring
🔮 Future Enhancements
Planned Features
- WebAuthn Support - Passwordless authentication
- Multi-Factor Authentication - TOTP/SMS support
- Social Login - Additional OAuth providers
- Advanced RBAC - Hierarchical roles
- API Keys - Service-to-service authentication
Integration Options
- Email Service - Password reset emails
- SMS Service - Two-factor authentication
- Monitoring - Prometheus metrics
- Analytics - User behavior tracking
🤝 Contributing
- Fork the repository
- Create a feature branch
- Add comprehensive tests
- Update documentation
- Submit a pull request
📄 License
This authentication system is part of the Rustelo template and follows the same licensing terms.
🆘 Support
For questions and support:
- Check the ENV_CONFIG.md for configuration details
- Review the migration files for database schema
- Examine the test files for usage examples
- Open an issue for bugs or feature requests
Security Notice: This system implements industry-standard security practices, but always review and customize security settings for your specific use case. Change default passwords and secrets before production deployment.