diff options
Diffstat (limited to 'REFACTORING_PLAN.md')
| -rw-r--r-- | REFACTORING_PLAN.md | 289 |
1 files changed, 289 insertions, 0 deletions
diff --git a/REFACTORING_PLAN.md b/REFACTORING_PLAN.md new file mode 100644 index 0000000..ec24449 --- /dev/null +++ b/REFACTORING_PLAN.md @@ -0,0 +1,289 @@ +# OAuth2 STS SOLID Refactoring Plan + +## Overview +This document outlines refactoring opportunities to better align with SOLID principles. + +## 1. Extract Grant Type Handlers (SRP + OCP) + +### Current Issue +`OAuthServer::handle_token()` contains all grant type logic in one method. + +### Proposed Solution +```rust +trait GrantHandler { + fn can_handle(&self, grant_type: &str) -> bool; + fn handle_grant( + &self, + params: &HashMap<String, String>, + auth_header: Option<&str>, + ip_address: Option<String>, + ) -> Result<String, String>; +} + +struct AuthorizationCodeGrantHandler { + client_authenticator: Arc<dyn ClientAuthenticator>, + token_generator: Arc<dyn TokenGenerator>, + code_repository: Arc<dyn AuthCodeRepository>, + token_repository: Arc<dyn TokenRepository>, + audit_logger: Arc<dyn AuditLogger>, +} + +struct RefreshTokenGrantHandler { + // Similar dependencies +} + +struct GrantHandlerRegistry { + handlers: Vec<Arc<dyn GrantHandler>>, +} +``` + +### Benefits +- ✅ Easy to add new grant types (Client Credentials, Device Code, etc.) +- ✅ Each handler has single responsibility +- ✅ Testable in isolation + +## 2. Create Repository Abstractions (DIP + SRP) + +### Current Issue +Monolithic `Database` struct violates SRP and makes testing difficult. + +### Proposed Solution +```rust +trait ClientRepository { + fn get_client(&self, client_id: &str) -> Result<Option<OAuthClient>>; + fn authenticate_client(&self, client_id: &str, secret: &str) -> Result<bool>; + fn is_redirect_uri_valid(&self, client_id: &str, uri: &str) -> bool; +} + +trait TokenRepository { + fn create_access_token(&self, token: &DbAccessToken) -> Result<()>; + fn get_access_token(&self, token_hash: &str) -> Result<Option<DbAccessToken>>; + fn revoke_access_token(&self, token_hash: &str) -> Result<()>; +} + +trait AuthCodeRepository { + fn create_auth_code(&self, code: &DbAuthCode) -> Result<()>; + fn get_auth_code(&self, code: &str) -> Result<Option<DbAuthCode>>; + fn mark_auth_code_used(&self, code: &str) -> Result<()>; +} + +// SQLite implementations +struct SqliteClientRepository { + database: Arc<Mutex<Database>>, +} + +struct SqliteTokenRepository { + database: Arc<Mutex<Database>>, +} +``` + +### Benefits +- ✅ Easy to swap database backends (PostgreSQL, Redis, etc.) +- ✅ Better testability with mock repositories +- ✅ Clear separation of concerns + +## 3. Extract Authentication Strategy (OCP + SRP) + +### Current Issue +Client authentication logic scattered throughout token handlers. + +### Proposed Solution +```rust +trait ClientAuthenticator { + fn authenticate( + &self, + params: &HashMap<String, String>, + auth_header: Option<&str>, + ) -> Result<(String, String), String>; // Returns (client_id, client_secret) +} + +struct BasicAuthenticator { + client_repository: Arc<dyn ClientRepository>, +} + +struct PostAuthenticator { + client_repository: Arc<dyn ClientRepository>, +} + +struct CompositeAuthenticator { + authenticators: Vec<Arc<dyn ClientAuthenticator>>, +} +``` + +### Benefits +- ✅ Easy to add new authentication methods (JWT, mTLS, etc.) +- ✅ Clear separation of authentication concerns +- ✅ Configurable authentication strategies + +## 4. Extract Token Generation (SRP + OCP) + +### Current Issue +Token generation logic embedded in `OAuthServer`. + +### Proposed Solution +```rust +trait TokenGenerator { + fn generate_access_token( + &self, + user_id: &str, + client_id: &str, + scope: &Option<String>, + token_id: &str, + ) -> Result<String>; + + fn generate_refresh_token( + &self, + client_id: &str, + user_id: &str, + scope: &Option<String>, + ) -> Result<String>; +} + +struct JwtTokenGenerator { + key_manager: Arc<Mutex<KeyManager>>, + config: Config, +} + +struct OpaqueTokenGenerator { + // For opaque token implementation +} +``` + +### Benefits +- ✅ Easy to switch token formats (JWT vs opaque) +- ✅ Configurable token generation strategies +- ✅ Better testability + +## 5. Extract Cross-Cutting Concerns + +### Rate Limiting +```rust +trait RateLimiter { + fn check_rate_limit(&self, identifier: &str, endpoint: &str) -> Result<()>; +} + +struct DatabaseRateLimiter { + rate_repository: Arc<dyn RateRepository>, + config: Config, +} + +struct RedisRateLimiter { + redis_client: redis::Client, + config: Config, +} +``` + +### Audit Logging +```rust +trait AuditLogger { + fn log_event(&self, event: AuditEvent) -> Result<()>; +} + +struct DatabaseAuditLogger { + audit_repository: Arc<dyn AuditRepository>, +} + +struct JsonFileAuditLogger { + file_path: PathBuf, +} +``` + +## 6. Refactor HTTP Layer (SRP) + +### Current Issue +`Server` mixes HTTP protocol with OAuth business logic. + +### Proposed Solution +```rust +struct HttpServer { + router: Router, + config: Config, +} + +struct Router { + oauth_handler: Arc<OAuthHandler>, + static_handler: Arc<StaticHandler>, +} + +struct OAuthHandler { + oauth_service: Arc<OAuthService>, // Renamed from OAuthServer +} + +// Clean separation between HTTP concerns and OAuth business logic +``` + +## 7. Dependency Injection Container + +### Proposed Solution +```rust +struct ServiceContainer { + // Repositories + client_repository: Arc<dyn ClientRepository>, + token_repository: Arc<dyn TokenRepository>, + auth_code_repository: Arc<dyn AuthCodeRepository>, + + // Services + client_authenticator: Arc<dyn ClientAuthenticator>, + token_generator: Arc<dyn TokenGenerator>, + rate_limiter: Arc<dyn RateLimiter>, + audit_logger: Arc<dyn AuditLogger>, + + // Grant handlers + grant_registry: Arc<GrantHandlerRegistry>, +} + +impl ServiceContainer { + fn new(config: &Config) -> Result<Self> { + // Wire up all dependencies + } +} +``` + +## Implementation Strategy + +### Phase 1: Repository Extraction +1. Create repository traits +2. Move database methods to specific repositories +3. Update `OAuthServer` to use repositories + +### Phase 2: Grant Handler Extraction +1. Create `GrantHandler` trait +2. Extract authorization code handler +3. Extract refresh token handler +4. Create registry + +### Phase 3: Cross-Cutting Concerns +1. Extract rate limiting +2. Extract audit logging +3. Extract authentication + +### Phase 4: HTTP Layer Cleanup +1. Separate HTTP protocol from business logic +2. Create clean request/response handlers + +### Phase 5: Dependency Injection +1. Create service container +2. Wire up all dependencies +3. Update main.rs to use container + +## Benefits of This Refactoring + +### Maintainability +- ✅ Easier to understand and modify individual components +- ✅ Clear separation of concerns +- ✅ Reduced coupling between components + +### Extensibility +- ✅ Easy to add new grant types +- ✅ Easy to swap implementations (database, token format, etc.) +- ✅ Configurable strategies for cross-cutting concerns + +### Testability +- ✅ Each component can be tested in isolation +- ✅ Easy to create mock implementations +- ✅ Better unit test coverage + +### Production Readiness +- ✅ Easy to scale different components independently +- ✅ Better observability and monitoring capabilities +- ✅ More flexible deployment options
\ No newline at end of file |
