- 
                Notifications
    You must be signed in to change notification settings 
- Fork 0
Version 0.2.0 #467
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Version 0.2.0 #467
Conversation
Add comprehensive OAuth2/OIDC authentication support using oauth2-proxy and GitLab as identity provider, alongside existing bearer token auth. Core Changes: - Implement hybrid authentication system supporting dev/oauth/bearer modes - Add OAuth2-proxy integration with Traefik reverse proxy setup - Update frontend to detect and adapt to different authentication modes - Extend API middleware to handle OAuth headers and session management New Features: - Development mode: No authentication for local development - OAuth mode: GitLab OIDC via oauth2-proxy with cookie-based sessions - Bearer mode: Traditional API token authentication (existing behavior) - Complete Docker Compose development environment with profiles - Frontend auth mode detection with appropriate UI changes Configuration: - Add AuthMode enum with dev/oauth/bearer variants in scotty-core - Extend ApiServer settings with OAuth redirect URL and dev user config - Update CurrentUser struct to include email, name, and optional access token - Add oauth2-proxy configuration with GitLab OIDC integration Development Setup: - Docker Compose profiles for different authentication modes - Helper scripts for easy local development and testing - Complete OAuth development example in examples/oauth2-proxy/ - 1Password integration for secure secret management Documentation: - Comprehensive CLAUDE.md with architecture and development guidance - OAuth testing documentation in LOCAL_OAUTH_TESTING.md - Configuration examples for all authentication modes Testing: - Full OAuth flow validation with Playwright browser testing - Traefik service discovery and routing verification - End-to-end authentication testing across all modes This implementation provides a production-ready OAuth authentication system while maintaining backward compatibility with existing bearer token authentication.
BREAKING CHANGE: API endpoints restructured with protected resources moved to /api/v1/authenticated/* namespace Enable secure GitLab OIDC authentication for Scotty's SPA interface while maintaining CLI bearer token support. This production-ready implementation replaces manual token entry with seamless OAuth flow using oauth2-proxy v7.6.0 and Traefik ForwardAuth middleware. Key improvements: - Hybrid authentication modes: dev, oauth, and bearer for different use cases - GitLab OIDC integration supporting both gitlab.com and self-hosted instances - Redis-backed session storage eliminating 4KB cookie size limitations - Clean API separation: public endpoints at /api/v1/ and authenticated at /api/v1/authenticated/* - Reusable ForwardAuth middleware for protecting additional Docker applications - Production-ready Docker Compose setup with Traefik reverse proxy Technical implementation: - ForwardAuth pattern validates sessions and injects user headers into backend requests - Breaking change: moved protected API endpoints to dedicated authenticated namespace - Frontend auto-detects authentication mode and handles OAuth redirects seamlessly - CLI tools updated to use new authenticated API namespace - Comprehensive example setups for both development and production OAuth scenarios This enables self-service user authentication without manual token management while preserving existing CLI workflows and adding enterprise-grade session management.
- Add #[derive(Default)] to AuthMode enum as suggested by clippy - Add #[allow(dead_code)] to access_token field for future OAuth implementations - Format all code with cargo fmt All tests passing and clippy warnings resolved.
- Replace 'any' type with proper LoginResponse interface in auth flow - Add proper type annotations for API response handling - Format code to match project style guidelines
The monitorTask function was calling getTask() which only checked the local store instead of actually fetching task status from the API. Changed to use requestTaskDetails() to properly fetch task status updates, enabling the loading spinner animation when running/stopping apps.
- Remove automatic OAuth redirects from login page, require user button click - Add auth_mode to /api/v1/info endpoint for cleaner auth mode detection - Use validate-token endpoint for proper authentication checking - Remove Traefik auto-redirect middlewares that bypass login page - Consolidate OAuth/bearer redirect handling to both use /login route Improves user experience by showing login page with explicit OAuth button instead of automatic redirects that users might miss.
- Add comprehensive OAuth authentication guide with oauth2-proxy and Traefik - Remove outdated LOCAL_OAUTH_TESTING.md file - Update configuration.md with new auth_mode options and environment variables - Add oauth-authentication.md to docs navigation The new documentation covers the current OAuth implementation including: - Three authentication modes (dev, oauth, bearer) - Route-based protection (/api/v1/authenticated/*) - Working examples in examples/oauth2-proxy-oauth/ - Complete setup instructions and troubleshooting
- Reduce healthcheck interval from 30s to 10s for faster feedback - Add 15s start period to prevent failures during startup - Reduce timeout from 3s to 2s (health endpoint responds in ~20ms) - Add explicit retries=3 for clarity This improves Docker Compose startup time and provides more responsive health status feedback during development and deployment.
…tion - Implement hybrid OAuth approach (Option C) with temporary session exchange - Add OAuth session storage with 5-minute expiry for security - Create `/oauth/exchange` API endpoint for frontend token retrieval - Update OAuth callback to redirect to frontend with session ID - Separate API and frontend OAuth callback paths to prevent conflicts - Modify frontend to handle session exchange flow instead of direct tokens - Add comprehensive OAuth state management and validation - Ensure no sensitive tokens appear in URLs or browser history - Support configurable frontend callback URLs via redirect_uri parameter This approach provides secure OAuth authentication while maintaining flexibility for different deployment configurations and prevents common security issues like token exposure in URLs.
…Gravatar support This comprehensive refactoring transforms the OAuth implementation from GitLab-specific to fully OIDC-compliant and provider-agnostic, while adding modern UI enhancements. **OIDC Standards Compliance:** - Replace GitLab-specific `gitlab_url` with generic `oidc_issuer_url` configuration - Update `GitLabUser` to `OidcUser` with OIDC standard fields (`sub`, `preferred_username`) - Use OIDC `/oauth/userinfo` endpoint instead of provider-specific endpoints - Support optional OIDC claims with intelligent fallbacks **Provider Interchangeability:** - Support GitLab, Auth0, Keycloak, Google, and other OIDC providers - Provider-agnostic configuration and documentation - Remove all GitLab-specific references from codebase **Enhanced Authentication UX:** - Add reactive user store for immediate UI updates after OAuth login - Implement session exchange flow to avoid exposing tokens in URLs - Fix user info display appearing only after page reload - Add proper error handling and debugging for OAuth flows **Modern Avatar System:** - Add Gravatar support with MD5 hashing for user avatars - Implement smart fallback system: Gravatar → initials → generic avatar - Create reusable UserAvatar component with multiple sizes and shapes - Enhanced user dropdown with professional styling and logout icon **Updated Documentation:** - Comprehensive OIDC authentication guide with provider examples - Updated CLI documentation with new command structure - Provider setup instructions for GitLab, Auth0, Keycloak, and Google - Migration guide from oauth2-proxy to native OIDC implementation **Frontend Improvements:** - Reactive authentication state management with Svelte stores - DaisyUI integration for consistent avatar styling - Enhanced user interface with Gravatar images and rich user dropdowns - Improved error handling and user feedback **Backend Enhancements:** - Better OIDC user field handling with meaningful fallbacks - Improved session management and token validation - Enhanced OAuth error handling and debugging capabilities The system now works seamlessly with any OIDC-compliant provider while providing a modern, professional user experience with Gravatar support and reactive UI updates.
Complete end-to-end OAuth device flow implementation enabling CLI authentication with OIDC providers like GitLab. This adds native device flow support alongside the existing web-based OAuth flow. Key improvements: - Implement full device flow token polling and exchange in Scotty server - Add proper OIDC provider integration with device authorization grant - Fix server info endpoint to use OIDC-compliant field names - Resolve server URL mismatch between localhost and 127.0.0.1 in token storage - Update scottyctl to handle device flow authentication properly - Add comprehensive error handling for OAuth flow states Technical changes: - Server: Add exchange_device_code_for_token() method for GitLab token polling - Server: Store device flow session interval for proper polling cadence - Server: Update info handler to return oidc_issuer_url instead of gitlab_url - scottyctl: Fix token storage to use user-provided server URL - scottyctl: Remove placeholder user info and use actual token response data - scottyctl: Update OAuth structures to be fully OIDC-compliant The device flow now supports the complete OAuth 2.0 Device Authorization Grant flow (RFC 8628) with proper error handling for authorization_pending, access_denied, and expired_token scenarios. Tested with GitLab OIDC provider - full authentication and API access working.
- Remove unused variables in frontend components - Remove imageLoaded variable from user-avatar component - Remove oauthRedirectUrl variable from login page - Apply Prettier formatting across all frontend files - Fix arrow function formatting in stores and components - Improve code readability with consistent indentation These changes resolve ESLint warnings and ensure consistent code style across the frontend codebase.
# Conflicts: # Cargo.lock
Update all documentation to use correct CLI command syntax: - Change apps subcommand to app:subcommand format - Change blueprints list to blueprint:list - Change notifications add/remove to notify:add/notify:remove This aligns documentation with actual CLI implementation.
Implement complete test suite for bearer token and OAuth authentication flows: **Bearer Authentication Tests (14 tests)** - Valid/invalid/missing token authentication scenarios - Malformed headers and public endpoint access validation - Configuration-dependent behavior testing - Cross-authentication mode validation **OAuth Authentication Tests (8 tests)** - Complete OAuth device flow: authorization → token → protected endpoint access - OAuth web flow: authorization URL generation, callback handling, session exchange - Mock OAuth provider integration with exact API format matching - OAuth provider error handling and authorization pending states **Key Technical Achievements** - Tests actual Scotty application router with complete middleware stack - Uses AppState access for OAuth session store manipulation to test complete flows - Mock OAuth provider with wiremock exactly matches implementation request formats - Validates end-to-end authentication: auth flow → token → protected API access - All 22 tests validate real implementation behavior, not isolated components The AppState approach solves OAuth web flow testing complexity by directly populating session stores, enabling complete flow validation without complex callback coordination between HTTP requests. Dependencies: Add axum-test, tokio-test, wiremock for testing infrastructure.
Removed assert!(true) statements that would be optimized out by the compiler, as flagged by clippy's assertions_on_constants lint. These assertions provided no actual test value and were replaced with comments explaining the test flow.
- Add preflight version check using semver to ensure major/minor compatibility - Create shared ServerInfo and OAuthConfig types in scotty_core for consistency - Add --bypass-version-check flag for emergency situations - Update AuthMode enum to support serialization with proper defaults - Version check runs before commands requiring server connection - Show clear error messages when versions are incompatible - Skip version check for auth commands (login/logout) and completion This prevents backwards compatibility issues by ensuring scottyctl and scotty server versions are compatible before executing operations.
- Replace direct println! calls with app_context.ui() methods - Use proper success/failed status methods for better terminal integration - Reduce excessive emoji usage for cleaner, more professional output - Maintain colored text for important information (URLs, usernames, servers) - Ensure consistent UI behavior with status line management
This commit centralizes shared functionality in scotty-core and significantly improves OAuth error handling with type-safe enums. ## New shared modules in scotty-core: - Add HTTP client with retry logic and exponential backoff - Add unified OAuth types with type-safe error enums - Add version management utilities with compatibility checking - Move retry logic from scottyctl to shared location ## OAuth improvements: - Replace string literals with OAuthErrorCode enum for type safety - Add built-in error descriptions to OAuth error codes - Update all OAuth handlers to use type-safe error responses - Maintain backward compatibility with legacy error formats ## HTTP client consolidation: - Create shared HttpClient with builder pattern and timeout support - Replace scattered reqwest::Client usage with shared implementation - Add proper error handling and retry policies across the workspace - Update OAuth flows to use shared HTTP client ## Version management: - Add comprehensive version comparison and compatibility utilities - Update preflight checker to use shared version management - Add user-friendly version formatting and update recommendations - Include extensive test coverage for version handling ## Code cleanup: - Remove unused dependencies (utoipa-axum) - Fix clippy warnings and improve code consistency - Update imports to use shared types across workspace - Maintain full backward compatibility All tests pass, ensuring no regressions were introduced.
This commit consolidates the OAuth error handling across the Scotty project by: - Unifying OAuthError and OAuthErrorCode into a single comprehensive error type in scotty-core - Implementing smart IntoResponse for AppError that returns OAuth-compliant ErrorResponse format for OAuth errors - Adding proper HTTP status code mappings for all OAuth error types (400, 401, 403, 404, 429) - Fixing device flow "Server error" issue by improving scottyctl error handling to process all OAuth status codes - Adding SlowDown variant for handling OAuth2 "slow_down" error during device flow polling - Maintaining OAuth2 RFC 6749 compliance while simplifying the error architecture - Updating all components (scotty, scottyctl, scotty-core) to use the unified system with proper error conversions The device flow now properly handles polling rate limiting and provides specific error messages instead of generic "Server error" responses.
Add role-based access control (RBAC) system using Casbin for granular permission management across apps and groups. Key features: - Group-based app organization (development, staging, production, default) - Role-based permissions (viewer, operator, developer, admin) - Per-app permission checks (view, manage, shell, logs, create, destroy) - Universal default group access for all users via wildcard assignment - Authorization middleware for API endpoints - Groups list endpoint (/api/v1/authenticated/groups/list) - Seamless fallback when authorization config unavailable This enables secure multi-tenant app management while maintaining backward compatibility.
- Fix token bounds checking in basic_auth.rs to prevent panics with short tokens - Implement proper get_user_permissions method in authorization service - Update authorization middleware to extract app names from API v1 paths - Fix middleware ordering by using State extractor instead of request extensions - Update router to use from_fn_with_state for require_permission middleware These changes resolve authentication failures and "App state not found" errors in the RBAC authorization system.
- Remove references to legacy api.access_token fallback - Add migration instructions for existing bearer token installations - Update PRD to reflect completed Phase 4 enforcement - Document middleware architecture improvements - Add warnings about breaking changes for bearer token authentication The authorization system now requires explicit RBAC assignments for all bearer tokens, removing the legacy fallback behavior.
Updates scottyctl to check server auth mode before using stored OAuth tokens. When server is in bearer mode, prioritizes --access-token parameter and SCOTTY_ACCESS_TOKEN environment variable over stored OAuth credentials. Resolves authentication failures where scottyctl would attempt to use invalid OAuth tokens against servers configured for bearer authentication.
- Remove fallback authorization service - RBAC is now required - Update tests to use actual RBAC configuration instead of fallback - Add test bearer token to policy configuration - Remove obsolete test for no-token configuration - Improve log format with timestamp, level, target, and message - Clean up telemetry configuration and reduce verbose span output
…-token-comparison fix(security): use constant-time comparison for bearer token validation
…se URL The OAuth callback handler used a hardcoded localhost URL for redirecting users back to the frontend after authentication. This prevented OAuth from working in production environments accessed via different hostnames. Changes: - Added 'frontend_base_url' field to OAuthSettings configuration - Defaults to 'http://localhost:21342' for backward compatibility - Updated OAuth callback handler to use configured URL instead of hardcoded value - Maintains support for per-flow frontend_callback_url override The frontend_base_url can now be configured in the settings file: [api.oauth] frontend_base_url = "https://scotty.example.com" Fixes: #517 Relates to: scotty-36
| Code Review - PR #467 (v0.2.0)Thank you for this comprehensive PR introducing authentication and authorization to Scotty! This is a significant enhancement that adds OAuth 2.0, bearer token auth, and RBAC via Casbin. The implementation shows solid engineering practices, but there are critical security issues that must be addressed before merging. 🔴 Critical Issues (Must Fix)1. Plaintext Secrets in Version ControlFiles:  Bearer tokens and OAuth client secrets are stored as plaintext in configuration files: bearer_tokens:
    admin: "gFW5k1fdvYw8iB2xCxw5qZXj5pkP9dga"
    client-a: "j3Xq973L67JVAsQpU4PfZAMKdMsfdXsu"Risk: Anyone with repository access can see these secrets. Recommendation: 
 2. No Token Expiration MechanismFiles: Throughout auth implementation Bearer tokens have no expiration - once issued, they're valid indefinitely. Risk: Stolen tokens can be used perpetually. Recommendation: 
 3. Insecure Authorization FallbackFile:  If Casbin config fails to load, the system falls back to a permissive default: Err(e) => {
    warn!("Failed to load authorization config...");
    FallbackService::create_fallback_service(settings.api.access_token.clone()).await
}Risk: Configuration errors could grant unintended access. Recommendation: Fail closed - refuse to start if authorization can't be loaded. 4. Container Running as RootFile:  User switching is commented out: # RUN chown -R $APP_USER:$APP_USER ${APP}
# USER $APP_USERRisk: Container breakout vulnerabilities. Recommendation: Uncomment and fix permission issues properly, never run as root. 🟡 High Priority Issues (Should Fix)5. Missing Input Validation on Admin EndpointsFiles:  Limited validation on user IDs, role names, scope names could allow injection attacks or invalid data. Recommendation: Add comprehensive input validation: fn validate_identifier(s: &str) -> Result<(), &'static str> {
    if s.is_empty() || s.len() > 128 {
        return Err("Invalid length");
    }
    if !s.chars().all(|c| c.is_alphanumeric() || c == '-' || c == '_') {
        return Err("Invalid characters");
    }
    Ok(())
}6. In-Memory Session Storage Without CleanupFile:  OAuth sessions stored in  Risk: Memory leak over time. Recommendation: 
 7. Limited Security Test CoverageFiles: Test files throughout Found basic tests but missing critical security scenarios: 
 Recommendation: Add comprehensive security test suite. 8. Missing Security Scanning in CIFile:  CI runs tests, fmt, clippy but no security scans. Recommendation: Add: - name: Security audit
  run: cargo audit
- name: Dependency checks
  run: cargo deny check🟢 Positive ObservationsExcellent work on several security aspects: 
 📊 Additional RecommendationsMedium Priority:
 Low Priority:
 🎯 Overall AssessmentRisk Level: HIGH This PR implements valuable functionality with generally good code quality, but critical security issues prevent merging in current state. The secrets management and token expiration issues are particularly concerning for production use. Recommendation: Address all critical issues before merge. The authentication system should be secure by default, with production-ready secret management. 📝 Testing RecommendationsBefore merging, ensure: 
 Overall: Great foundation! The architecture is solid and the OAuth implementation is well-structured. Once the security issues are addressed, this will be a strong addition to Scotty. Let me know if you'd like me to elaborate on any of these points or provide code examples for the fixes. | 
Replaces standard string equality with constant-time comparison using the subtle crate to prevent timing attacks that could reveal valid bearer tokens through response time measurements. The vulnerable code used simple == comparison which short-circuits on the first character mismatch, allowing attackers to determine correct characters through timing analysis. This fix ensures all token comparisons take the same amount of time regardless of match position. Fixes: #520 Relates to: scotty-39
The login handler was still using standard == comparison for bearer tokens, vulnerable to the same timing attack fixed in auth_core.rs. This completes the timing attack mitigation across all token comparison points in the authentication system. Addresses PR #524 review feedback
Add documentation for the new frontend_base_url configuration option that allows OAuth to work with production domains instead of being hardcoded to localhost. Changes: - Add frontend_base_url to OAuth configuration examples - Add SCOTTY__API__OAUTH__FRONTEND_BASE_URL environment variable - Add "Understanding OAuth URLs" section explaining the difference between redirect_url (backend callback) and frontend_base_url (frontend application base) - Include production configuration example - Update environment variables reference table This documents the fix for scotty-36 where OAuth callback URLs were hardcoded to localhost, preventing OAuth from working in production environments.
| Code Review: Version 0.2.0This is a major release introducing OAuth authentication, RBAC authorization, unified output system, and observability. This is a comprehensive review with specific findings. 🎯 Executive SummaryOverall Assessment: ✅ APPROVE with Important Recommendations This is a well-architected and substantial release that significantly enhances Scotty's security and operational capabilities. The implementation demonstrates solid engineering practices, good separation of concerns, and comprehensive testing (777 test occurrences across 57 files). However, there are critical security concerns that should be addressed before production deployment. Changed: 245 files, +30,318 additions, -2,253 deletions 🔒 Critical Security Issues1. 🔴 CRITICAL: Hardcoded Bearer Tokens in Version ControlLocation:  bearer_tokens:
    admin: "gFW5k1fdvYw8iB2xCxw5qZXj5pkP9dga"
    client-a: "j3Xq973L67JVAsQpU4PfZAMKdMsfdXsu"
    client-b: "mPFMijuZeEAaus94hWApEHzD8JMhrcRk"
    hello-world: "mv7UuZddtVpAM5c6tWCFejCp1vizuSlX"
    test-bearer-token-123: "9oWZsLsUzFvC01nPqB6nzZpDK6Zlv3KR"Issue: While these appear to be example tokens, committing ANY tokens to version control is a critical security vulnerability. These could be accidentally deployed to production or leaked via forks. Recommendation: 
 Impact: HIGH - If these are real tokens or get reused, they provide unauthorized access 2. 🟡 MEDIUM: Wildcard User AuthorizationLocation:  '*':
  - role: viewer
    scopes:
    - defaultIssue: The wildcard  Recommendation: 
 Impact: MEDIUM - Potential unauthorized read access if auth is misconfigured 3. 🟡 MEDIUM: Token Storage in sessionStorageLocation:  Positive: Unlike previous reviews suggested, this implementation uses sessionStorage (not localStorage), which is significantly more secure: 
 Remaining Concerns: 
 Recommendations: 
 Impact: MEDIUM - Acceptable for many use cases, but requires XSS prevention 🐛 Code Quality Issues4. 🟡 MEDIUM: Panic-Prone Code with Multiple  | 
The login handler was still using standard == comparison for bearer tokens, vulnerable to the same timing attack fixed in auth_core.rs. This completes the timing attack mitigation across all token comparison points in the authentication system. Addresses PR #524 review feedback
…se URL The OAuth callback handler used a hardcoded localhost URL for redirecting users back to the frontend after authentication. This prevented OAuth from working in production environments accessed via different hostnames. Changes: - Added 'frontend_base_url' field to OAuthSettings configuration - Defaults to 'http://localhost:21342' for backward compatibility - Updated OAuth callback handler to use configured URL instead of hardcoded value - Maintains support for per-flow frontend_callback_url override The frontend_base_url can now be configured in the settings file: [api.oauth] frontend_base_url = "https://scotty.example.com" Fixes: #517 Relates to: scotty-36
…k-url fix(oauth): replace hardcoded localhost with configurable frontend base URL
| Code Review: PR #467 - Version 0.2.0OverviewThis is a substantial release introducing major new features across authentication, authorization, observability, and frontend improvements. The PR includes: 
 Overall AssessmentStatus: ✅ APPROVE WITH RECOMMENDATIONS This PR demonstrates high-quality engineering with well-architected systems. The authorization implementation is particularly impressive, and the observability stack is production-ready. However, there are critical security issues that should be addressed before production deployment. 🎯 Major Features Review1. Authorization System (Casbin RBAC)Strengths: 
 Code Quality: 
 2. OAuth/OIDC AuthenticationStrengths: 
 
 3. Observability StackStrengths: 
 Metrics Coverage: 
 This is production-ready and well-documented. 4. Frontend ImprovementsStrengths: 
 Code Quality: 
 
 🔒 Security AnalysisCritical Issues (Must Fix Before Production)
 High Priority
 Medium Priority
 Positive Security Findings ✅
 📊 Code Quality AssessmentRust BackendStrengths: 
 Minor Issues: 
 Frontend (TypeScript/Svelte)Strengths: 
 Suggestions: 
 🧪 Testing & QualityObservations: 
 Recommendations: 
 📝 DocumentationStrengths: 
 Suggestions: 
 🚀 Performance ConsiderationsPositive: 
 Potential Concerns: 
 Recommendations: 
 🔄 Breaking Changes
 These are well-documented in the migration sections. 📋 Recommendations SummaryBefore Merging
 Before Production Deployment
 Next Release (0.2.1)
 🎉 HighlightsWhat's Really Well Done: 
 Final RecommendationAPPROVE with conditions: This is high-quality work that significantly enhances Scotty's capabilities. The authorization system is well-architected, and the observability stack is production-ready. However, the OAuth/OIDC implementation has critical security gaps that must be addressed. Recommendation: 
 Confidence Level: High - The foundations are solid, but security hardening is essential. Detailed Issue TrackerWould you like me to create separate GitHub issues for each security concern? I can draft them with: 
 Great work on this release! The overall direction is excellent. 🚀 Review generated by Claude Code based on PR diff, documentation, and codebase analysis. | 
Add automated session cleanup to prevent memory leaks and implement full observability for OAuth authentication flows. Session Cleanup (scotty-37): - Add periodic cleanup task running every 5 minutes via clokwerk scheduler - Create generic ExpirableSession trait for all session types - Clean DeviceFlowStore, WebFlowStore, and OAuthSessionStore - Prevent unbounded memory growth and DoS attacks - Include comprehensive unit tests for cleanup functionality Metrics Implementation (scotty-41): - Add 10 new OAuth metrics to instruments.rs: * Session gauges: device_flow, web_flow, oauth sessions (sampled every 30s) * Flow counters: device flows, web flows, flow failures * Token validation: total, duration histogram, failures * Cleanup counter: expired sessions cleaned - Create dedicated oauth/metrics.rs module with clean API - Instrument device_flow.rs and handlers.rs with minimal code changes - Record token validation timing and success/failure rates Grafana Dashboard: - Add "OAuth Authentication" section with 9 panels - Session monitoring: 4 gauge panels for active sessions - Flow rates: device/web flow rates with failure tracking - Performance: token validation duration (p50/p95/p99) - Error rates: validation and flow error percentages - Color-coded thresholds and stacked time series Benefits: - Fixes memory leak vulnerability (sessions never expired) - Prevents DoS attacks via session exhaustion - Full observability for authentication health and performance - Enables proactive monitoring and alerting - Minimal impact on business logic (single-line instrumentation) Relates to: scotty-37, scotty-41
…and-metrics feat(oauth): implement session cleanup and comprehensive monitoring
| PR Review: Version 0.2.0OverviewThis is a substantial release adding three major features: OAuth authentication, RBAC authorization with Casbin, and observability with OpenTelemetry. The PR includes 31,475 additions across 100+ files. Overall Assessment: The implementation is well-structured with good separation of concerns. However, the PR size makes thorough review challenging. Future releases should consider breaking features into smaller, reviewable chunks. 🎯 Positive HighlightsArchitecture & Design
 Security
 Code Quality
 
 | 
Wrap sensitive cryptographic material in MaskedSecret to prevent exposure in memory dumps, debug logs, and crash reports. Secrets are now zeroized on drop and require explicit .expose_secret() calls for access. Changes: - Update WebFlowSession to use MaskedSecret for csrf_token and pkce_verifier - Update handlers.rs to wrap/unwrap secrets during storage and retrieval - Update all test code to use MaskedSecret - Maintain full serialization/deserialization support Security improvements: - PKCE verifier protected from memory exposure - CSRF token protected from memory exposure - Automatic zeroization on drop - Masked output in debug logs All OAuth tests passing (21/21). Closes scotty-38
Remove base64 encoding/decoding of PKCE verifier as it provides no benefit. The PKCE verifier (RFC 7636) is already URL-safe and contains only ASCII alphanumeric characters and safe symbols (-._~). Changes: - Store PKCE verifier directly as string without base64 encoding - Simplify retrieval logic (no decode/UTF-8 conversion needed) - Remove unused base64 import - Update struct comment to remove encoding reference - Add test to verify debug output masks secrets Benefits: - Simpler code (removed 25 lines of error handling) - No unnecessary encode/decode overhead - Fewer potential failure points - Easier debugging (see actual verifier format) All 22 OAuth tests passing including new masking test.
…rotection fix(oauth): protect PKCE verifier and CSRF token with MaskedSecret
| PR #467 - Version 0.2.0 Code ReviewOverviewThis is a major release with 31,497 additions across 103 files, introducing comprehensive authentication, authorization, and observability systems. Overall assessment: Strong foundation with some critical issues requiring attention before merge. 🎯 Summary Rating
 🔒 Security Analysis✅ Strengths
 🚨 Critical Issues1. Secrets as Plain  | 
Implemented tiered rate limiting for all vulnerable API endpoints to prevent brute force attacks, DoS, and abuse. Uses token bucket algorithm via tower-governor with three distinct tiers: - Public auth endpoints (login) - IP-based rate limiting - OAuth endpoints - IP-based rate limiting - Authenticated API endpoints - Token-based rate limiting Rate limiting is disabled by default and can be configured per-tier with requests_per_minute and burst_size settings. Global switch allows enabling/disabling all rate limiting. Key changes: - Added tower_governor 0.8 and governor 0.10 dependencies - Created rate limiting module with tier-specific limiters - Added custom bearer token extractor for authenticated tier - Split router into separate login, OAuth, and authenticated routers - Added conditional layer application based on configuration - Added rate limiting settings to api_server config All 117 existing tests pass. Addresses scotty-40.
Add comprehensive metrics instrumentation for rate limiting: - Total rate limit hits counter - Rate limit hits by tier (authenticated, public_auth, oauth) - Middleware to automatically record 429 responses Add Grafana dashboard panels: - Total rate limit hits stat - Rate limit hit rate over time - Stacked chart showing hits by tier Add integration tests: - Test rate limiting disabled - Test authenticated per-token rate limiting - Test independent tier limits
Document rate limiting configuration, tiers, and monitoring: - Configuration options and examples - Three-tier rate limiting system (public_auth, oauth, authenticated) - Recommended limits per tier - Monitoring metrics and dashboard - Behavior when limits are exceeded
The rate limiting integration tests were failing because they use IP-based rate limiting via SmartIpKeyExtractor, but axum_test::TestServer doesn't provide real IP addresses. Added X-Forwarded-For headers to all test requests to allow proper IP extraction and rate limit validation. Also fixed login endpoint JSON format to use only 'password' field as required by the FormData struct. Tests now properly verify: - Public auth rate limiting (IP-based) - OAuth rate limiting (IP-based) - Rate limit response format - Independent limits across endpoint tiers
- Replace token truncation with SHA256 hashing to prevent collision attacks - Fix rate calculation precision loss by using per_nanosecond instead of per_second - Add configuration validation for TierConfig with comprehensive tests - Validate rate limiting config on application startup This addresses the 3 MUST FIX items from PR #529 review: 1. Token truncation created collision risk for DoS attacks 2. Integer division precision loss could double rate limits (30 req/min → 1 req/sec) 3. No validation for invalid config (burst_size=0, burst exceeds rate) All rate limiting tests still pass with these security improvements.
- Document multi-instance deployment limitations and solutions - Document IPv6 support and considerations - Verify and document rate limit response headers (Retry-After, X-RateLimit-After) - Add test assertions for rate limit headers - Document missing RFC 6585 headers as future enhancement - Remove emojis from documentation per user preference This addresses the SHOULD FIX items from PR #529 review: - IPv6 handling documented with prefix-based attack mitigation strategies - Multi-instance limitations clearly documented with recommended solutions - Rate limit headers verified (Retry-After provided by tower-governor) - Missing headers (X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset) documented as future enhancement
Add detailed observability for rate limiting:
- rate_limit_requests_total{tier, status} - tracks allowed/denied requests
- rate_limit_extractor_errors - tracks bearer token extraction failures
Changes:
- Updated ScottyMetrics to include new rate limiting counters
- Modified middleware to record both allowed and denied requests
- Added extraction error tracking in BearerTokenExtractor
- Added unit test for metrics recording functions
All tests passing (126 total).
    feat(security): implement comprehensive API rate limiting
| Comprehensive Code Review - Version 0.2.0This is a major release introducing authentication, authorization, unified output system, and observability. I've conducted a thorough review across all major components. Executive SummaryOverall Assessment: APPROVE WITH CRITICAL FIXES REQUIRED ✅ This is an excellent architectural upgrade with strong security foundations. However, several critical issues must be addressed before production deployment: 
 Major Features Review1. OAuth Authentication & Authorization SystemStrengths ✅
 Critical Issues 🔴1. Mutex Unwrap Pattern (Panic-Prone) 
 // VULNERABLE CODE
let mut sessions = oauth_state.web_flow_store.lock().unwrap();Issue: Using  Recommendation: let mut sessions = oauth_state.web_flow_store.lock()
    .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?;2. In-Memory Session Storage (No Persistence) 
 pub type DeviceFlowStore = Arc<Mutex<HashMap<String, DeviceFlowSession>>>;
pub type WebFlowStore = Arc<Mutex<HashMap<String, WebFlowSession>>>;Issues: 
 Impact: Unreliable OAuth flows, load balancer incompatibility Recommendation: Implement Redis or database-backed session storage before production 3. Hardcoded Bearer Tokens 
 bearer_tokens:
    admin: "admin-bearer-token"
    client-a: "client-a-bearer-token"
    client-b: "client-b-bearet-token"  # TYPO: "bearet"Issues: 
 Recommendation: 
 4. OIDC Tokens Returned as Bearer Tokens 
 // TODO: Generate a Scotty JWT token instead
Ok(Json(TokenResponse {
    access_token: oidc_token,  // OIDC token returned directlyImpact: 
 Recommendation: Implement Scotty JWT generation (TODO at line 556) 5. Casbin Policy Sync Not Atomic 
 let _ = enforcer.clear_policy().await;  // Errors silently ignored\!
// Then add new policies...Issues: 
 Recommendation: Use load-swap pattern or implement atomicity 2. Frontend Authentication SecurityStrengths ✅
 Critical Issues 🔴1. Token Logging to Console 
 console.log(
    'Authenticating WebSocket with token (first 8 chars):',
    token.substring(0, 8) + '...'
);Risk: Token prefixes visible in browser console (accessible to XSS attacks, developer tools) Recommendation: Remove ALL token logging entirely 2. Missing CSRF Protection 
 Issue: No CSRF tokens on state-changing POST requests Recommendation: Implement CSRF tokens or enforce SameSite cookies 3. Dev Mode Bypass Risk 
 if (authMode === 'dev') {
    isAuthenticated = true; // Always authenticated in dev mode
}Risk: If  Recommendation: Ensure dev mode is compile-time only, not runtime configurable 4. No Token Expiration Tracking 
 Recommendation: Implement token metadata tracking and refresh 5. WebSocket Auto-Connect Before Auth 
 if (browser) {
    initialize(); // Connects immediately on module load
}Issue: WebSocket connection attempted before authentication complete Recommendation: Only connect after successful authentication 3. Unified Output SystemStrengths ✅
 Issues Found 🟡1. Broadcast Channel Overflow 
 let (sender, _) = broadcast::channel(1000); // 1000 message capacityIssue: High-frequency log streams can overflow, causing lagged clients to lose messages Recommendation: Reduce capacity or implement backpressure 2. O(n) Output Line Eviction 
 while self.lines.len() > self.limits.max_lines {
    self.lines.remove(0);  // Shifts 9,999 lines on each eviction\!
}Issue:  Recommendation: Replace with  3. Double Task Output Polling 
 Calls  Recommendation: Cache Arc from first call 4. Docker Timestamp Parsing Heuristic 
 if content.starts_with('2') { /* assume timestamp */ }Risk: Can fail on log lines starting with "2" that aren't timestamps Recommendation: Use regex or strict format validation 4. Configuration SecurityIssues Found 🔴1. Registry Credentials in Default Config 
 registries:
    factorial_legacy:
        username: "deploybot"
        password: "deploybot"  # Override with env varIssue: While comment mentions env vars, having example credentials in committed config is risky Recommendation: Use  2. Wildcard User Assignment 
 assignments:
  '*':  # All users get viewer role
  - role: viewer
    scopes:
    - defaultRisk: Every authenticated user gets viewer access to default scope Recommendation: Add comment explaining behavior, ensure this is intentional 3. Test Credentials in Default Policy 
 Multiple test identifiers (admin, hello-world, test-bearer-token-123) in default config Recommendation: Separate example configs from production defaults 5. Observability StackStrengths ✅
 No significant issues found - excellent implementation! Test Coverage AssessmentGood Coverage ✅
 Gaps to Address 📝
 Performance ConsiderationsOptimizations Needed 🟡
 Breaking ChangesUser Impact  | 
No description provided.