# 🔐 ROA2WEB Shared Authentication System Sistem de autentificare JWT partajat între toate aplicațiile din ecosistemul ROA2WEB, integrat cu Oracle Database și optimizat pentru aplicații FastAPI. ## 📋 Table of Contents - [Features](#features) - [Architecture](#architecture) - [Quick Start](#quick-start) - [Components](#components) - [Integration Guide](#integration-guide) - [Security Features](#security-features) - [API Reference](#api-reference) - [Testing](#testing) - [Deployment](#deployment) - [Troubleshooting](#troubleshooting) ## ✨ Features ### Core Features - **JWT Authentication**: Secure token-based authentication cu access și refresh tokens - **Oracle Database Integration**: Folosește `pack_drepturi.verificautilizator` pentru autentificare - **Multi-Company Support**: Acces controlat la multiple firme/schemas Oracle - **Permission System**: Sistem granular de permisiuni (read, write, admin, reports) - **FastAPI Integration**: Dependencies și middleware native pentru FastAPI - **Rate Limiting**: Protecție împotriva brute force attacks - **Caching**: Cache inteligent pentru performanță optimă ### Security Features - **Token Expiration**: Configurabil pentru access și refresh tokens - **SQL Injection Protection**: Parametri legați în toate query-urile - **Rate Limiting**: Configurabil per IP și endpoint - **CORS Protection**: Configurare flexibilă pentru origins - **Header Security**: Security headers automate - **Token Blacklisting**: Suport pentru invalidarea token-urilor (în dezvoltare) ## 🏗️ Architecture ``` ROA2WEB Authentication Flow: ┌─────────────┐ ┌──────────────┐ ┌─────────────┐ ┌──────────────┐ │ Client │───▶│ FastAPI │───▶│ JWT │───▶│ Oracle │ │ (Frontend) │ │ Application │ │ Handler │ │ Database │ └─────────────┘ └──────────────┘ └─────────────┘ └──────────────┘ │ │ │ ▼ ▼ ▼ ┌──────────────┐ ┌─────────────┐ ┌──────────────┐ │ Auth Service │ │ Middleware │ │ User Cache │ └──────────────┘ └─────────────┘ └──────────────┘ ``` ### Components Overview ``` shared/auth/ ├── jwt_handler.py # JWT token creation și validation ├── auth_service.py # Oracle database integration ├── models.py # Pydantic models pentru data validation ├── middleware.py # FastAPI middleware pentru auto-authentication ├── dependencies.py # FastAPI dependencies pentru protected routes ├── routes.py # Pre-built authentication routes ├── test_auth.py # Comprehensive test suite ├── demo_app.py # Demo application cu examples └── README.md # Această documentație ``` ## 🚀 Quick Start ### 1. Environment Setup ```bash # Copy și configurează environment variables cp .env.example .env # Edit .env cu configurările tale JWT_SECRET_KEY=your-super-secret-jwt-key-change-in-production ORACLE_USER=your_oracle_username ORACLE_PASSWORD=your_oracle_password ORACLE_DSN=your_oracle_connection_string ``` ### 2. Basic Integration ```python from fastapi import FastAPI, Depends from roa2web.shared.auth import ( AuthenticationMiddleware, create_auth_router, get_current_user, CurrentUser ) from roa2web.shared.database import oracle_pool app = FastAPI(title="My ROA2WEB App") # Add authentication middleware app.add_middleware( AuthenticationMiddleware, excluded_paths=["/", "/docs", "/health", "/auth/login"] ) # Include authentication routes auth_router = create_auth_router() app.include_router(auth_router) @app.on_event("startup") async def startup(): await oracle_pool.initialize() @app.get("/protected") async def protected_endpoint( current_user: CurrentUser = Depends(get_current_user) ): return {"message": f"Hello {current_user.username}!"} ``` ### 3. Test Authentication ```bash # Start demo application cd roa2web/shared/auth python demo_app.py # Open browser open http://localhost:8000/docs # Login prin Swagger UI cu credențialele Oracle ``` ## 🧩 Components ### JWT Handler (`jwt_handler.py`) Gestionează crearea, validarea și refresh-ul token-urilor JWT. ```python from roa2web.shared.auth import jwt_handler # Create access token token = jwt_handler.create_access_token( username="admin", companies=["COMP1", "COMP2"], permissions=["read", "write", "reports"] ) # Verify token token_data = jwt_handler.verify_token(token) if token_data: print(f"Valid token for user: {token_data.username}") ``` ### Auth Service (`auth_service.py`) Integrează cu Oracle Database pentru autentificare și management utilizatori. ```python from roa2web.shared.auth import auth_service # Authenticate user success, token_response, error = await auth_service.authenticate_and_create_tokens( "username", "password" ) if success: print(f"Access token: {token_response.access_token}") else: print(f"Authentication failed: {error}") ``` ### FastAPI Dependencies (`dependencies.py`) Oferă dependencies pentru protejarea endpoint-urilor. ```python from fastapi import Depends from roa2web.shared.auth import ( get_current_user, require_company_access, require_permissions, PermissionType ) @app.get("/admin-only") async def admin_endpoint( user: CurrentUser = Depends(require_permissions([PermissionType.ADMIN])) ): return {"message": "Admin access granted"} @app.get("/company/{company_code}/data") async def company_data( company_code: str, user: CurrentUser = Depends(require_company_access(company_code)) ): return {"company": company_code, "data": "..."} ``` ### Authentication Routes (`routes.py`) Pre-built routes pentru operații de autentificare. ```python from roa2web.shared.auth import create_auth_router # Basic auth router auth_router = create_auth_router() app.include_router(auth_router) # Auth router cu admin routes auth_router_admin = create_auth_router(include_admin_routes=True) app.include_router(auth_router_admin) ``` Available routes: - `POST /auth/login` - User authentication - `POST /auth/refresh` - Token refresh - `POST /auth/logout` - User logout - `GET /auth/me` - Current user info - `GET /auth/companies` - User companies - `GET /auth/status` - Authentication status ## 🔧 Integration Guide ### Full FastAPI Application ```python from fastapi import FastAPI, Depends, HTTPException from fastapi.middleware.cors import CORSMiddleware from contextlib import asynccontextmanager from roa2web.shared.auth import ( AuthenticationMiddleware, create_auth_router, get_current_user, require_company_access, CurrentUser, PermissionType ) from roa2web.shared.database import oracle_pool @asynccontextmanager async def lifespan(app: FastAPI): # Startup await oracle_pool.initialize() yield # Shutdown await oracle_pool.close_pool() app = FastAPI( title="ROA2WEB Application", lifespan=lifespan ) # CORS app.add_middleware( CORSMiddleware, allow_origins=["http://localhost:3000"], allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) # Authentication app.add_middleware( AuthenticationMiddleware, excluded_paths=["/", "/docs", "/health"], rate_limit_paths=["/auth/login"] ) # Routes auth_router = create_auth_router() app.include_router(auth_router) # Protected endpoints @app.get("/") async def public_endpoint(): return {"message": "Public endpoint"} @app.get("/me") async def my_info(current_user: CurrentUser = Depends(get_current_user)): return current_user @app.get("/company/{company_code}/invoices") async def get_invoices( company_code: str, current_user: CurrentUser = Depends(require_company_access(company_code)) ): # Business logic here return {"company": company_code, "invoices": []} ``` ### Custom Permissions ```python from roa2web.shared.auth import require_permissions, PermissionType # Define custom permissions class CustomPermissionType(str, Enum): INVOICE_READ = "invoice_read" INVOICE_WRITE = "invoice_write" REPORT_EXPORT = "report_export" # Use in endpoints @app.get("/invoices") async def get_invoices( user: CurrentUser = Depends(require_permissions([CustomPermissionType.INVOICE_READ])) ): return {"invoices": []} ``` ### Company-Specific Endpoints ```python from fastapi import Header from roa2web.shared.auth import get_current_company_from_header @app.get("/current-company-data") async def get_current_company_data( company_code: str = Depends(get_current_company_from_header), current_user: CurrentUser = Depends(get_current_user) ): # company_code is automatically extracted from X-Company-Code header # and validated against user's accessible companies return {"company": company_code, "data": "..."} ``` ## 🔒 Security Features ### JWT Configuration ```python # Environment variables JWT_SECRET_KEY=your-super-secret-jwt-key-change-in-production JWT_ALGORITHM=HS256 ACCESS_TOKEN_EXPIRE_MINUTES=30 REFRESH_TOKEN_EXPIRE_DAYS=7 ``` ### Rate Limiting ```python from roa2web.shared.auth import RateLimiter, AuthenticationMiddleware # Custom rate limiter custom_rate_limiter = RateLimiter( max_requests=10, # 10 requests time_window=60 # per minute ) app.add_middleware( AuthenticationMiddleware, rate_limit_paths=["/auth/login", "/auth/register"], rate_limiter=custom_rate_limiter ) ``` ### Security Headers Middleware-ul adaugă automat header-e de securitate: ``` X-Content-Type-Options: nosniff X-Frame-Options: DENY X-XSS-Protection: 1; mode=block ``` ## 📚 API Reference ### JWT Handler Methods ```python class JWTHandler: def create_access_token(username, companies, user_id=None, permissions=None) -> str def create_refresh_token(username, user_id=None) -> str def verify_token(token) -> Optional[TokenData] def refresh_access_token(refresh_token, companies, permissions=None) -> Optional[str] def create_token_response(username, companies, ...) -> TokenResponse ``` ### Auth Service Methods ```python class UserAuthService: async def verify_user_credentials(username, password) -> bool async def get_user_companies(username) -> List[str] async def get_user_permissions(username, company) -> List[str] async def authenticate_and_create_tokens(username, password) -> Tuple[bool, TokenResponse, str] async def validate_user_company_access(username, company) -> bool ``` ### FastAPI Dependencies ```python # User dependencies get_current_user() -> CurrentUser get_optional_user() -> Optional[CurrentUser] # Permission dependencies require_permissions(permissions: List[PermissionType]) require_company_access(company_code: str) require_company_and_permissions(company_code: str, permissions: List[PermissionType]) # Utility dependencies get_current_company_from_header() -> str ``` ## 🧪 Testing ### Running Tests ```bash # Install test dependencies pip install pytest pytest-asyncio httpx # Run all tests cd roa2web/shared/auth python -m pytest test_auth.py -v # Run specific test categories python -m pytest test_auth.py::TestJWTHandler -v python -m pytest test_auth.py::TestUserAuthService -v python -m pytest test_auth.py::TestSecurityFeatures -v # Run with coverage python -m pytest test_auth.py --cov=. --cov-report=html ``` ### Test Categories - **Unit Tests**: JWT operations, auth service methods - **Integration Tests**: Database integration, full auth flow - **Security Tests**: Token tampering, SQL injection, rate limiting - **Performance Tests**: Token creation/verification speed ### Demo Application ```bash # Start demo app for manual testing cd roa2web/shared/auth python demo_app.py # Available demo endpoints: # http://localhost:8000/ - Home page cu documentație # http://localhost:8000/docs - Swagger UI pentru testare # http://localhost:8000/demo/* - Various demo endpoints ``` ## 🚀 Deployment ### Production Configuration ```bash # Strong JWT secret key JWT_SECRET_KEY=$(python -c "import secrets; print(secrets.token_urlsafe(32))") # Shorter token expiration ACCESS_TOKEN_EXPIRE_MINUTES=15 REFRESH_TOKEN_EXPIRE_DAYS=1 # Strict rate limiting RATE_LIMIT_MAX_REQUESTS=3 RATE_LIMIT_TIME_WINDOW=300 # Secure headers SECURE_SSL_REDIRECT=true SESSION_COOKIE_SECURE=true ``` ### Docker Integration ```dockerfile # În Dockerfile-ul aplicației FROM python:3.11-slim WORKDIR /app COPY requirements.txt . RUN pip install -r requirements.txt COPY . . # Environment pentru container ENV JWT_SECRET_KEY=${JWT_SECRET_KEY} ENV ORACLE_USER=${ORACLE_USER} ENV ORACLE_PASSWORD=${ORACLE_PASSWORD} ENV ORACLE_DSN=${ORACLE_DSN} CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"] ``` ### Health Checks ```python @app.get("/health") async def health_check(): # Test database connection try: async with oracle_pool.get_connection() as conn: with conn.cursor() as cursor: cursor.execute("SELECT 1 FROM DUAL") db_status = "healthy" except Exception as e: db_status = f"error: {str(e)}" return { "status": "healthy" if db_status == "healthy" else "degraded", "database": db_status, "jwt": "functional", "timestamp": datetime.now().isoformat() } ``` ## 🔧 Troubleshooting ### Common Issues #### 1. "Invalid token" errors ```python # Check JWT secret key consistency print(f"JWT Secret: {os.getenv('JWT_SECRET_KEY')}") # Verify token creation and validation token = jwt_handler.create_access_token("test", ["COMP1"]) token_data = jwt_handler.verify_token(token) print(f"Token valid: {token_data is not None}") ``` #### 2. Database connection errors ```python # Test Oracle connection try: async with oracle_pool.get_connection() as conn: with conn.cursor() as cursor: cursor.execute("SELECT 1 FROM DUAL") result = cursor.fetchone() print("Database connection: OK") except Exception as e: print(f"Database error: {e}") ``` #### 3. Rate limiting issues ```python # Check rate limiter stats from roa2web.shared.auth import default_rate_limiter client_ip = "192.168.1.1" allowed = default_rate_limiter.is_allowed(client_ip) reset_time = default_rate_limiter.get_reset_time(client_ip) print(f"IP {client_ip} allowed: {allowed}, resets at: {reset_time}") ``` #### 4. Permission denied errors ```python # Check user companies and permissions companies = await auth_service.get_user_companies("username") permissions = await auth_service.get_user_permissions("username", "COMP1") print(f"User companies: {companies}") print(f"User permissions: {permissions}") ``` ### Debug Mode ```python import logging # Enable debug logging logging.basicConfig(level=logging.DEBUG) # Specific loggers logging.getLogger("roa2web.shared.auth").setLevel(logging.DEBUG) ``` ### Environment Validation ```python from roa2web.shared.utils.config import shared_config # Validate configuration print(f"Oracle User: {shared_config.oracle_user}") print(f"JWT Secret set: {'***' if shared_config.jwt_secret_key else 'NOT SET'}") print(f"Token expiry: {shared_config.access_token_expire_minutes} minutes") ``` ## 📈 Performance Optimization ### Caching ```python # Cache configuration AUTH_CACHE_TTL_MINUTES=15 # User data cache TTL # Monitor cache performance stats = auth_service.get_cache_stats() print(f"Cache hit ratio: {stats['cache_hit_ratio']:.2%}") ``` ### Connection Pooling ```python # Oracle pool configuration DB_MIN_CONNECTIONS=2 DB_MAX_CONNECTIONS=10 DB_CONNECTION_INCREMENT=1 ``` ### Token Optimization ```python # Optimize token size by limiting payload token = jwt_handler.create_access_token( username="user", companies=["COMP1"], # Limit companies in token permissions=["read"] # Essential permissions only ) ``` ## 🤝 Contributing Pentru contribuții la sistemul de autentificare: 1. **Fork repository-ul** și creează o ramură pentru feature 2. **Implementează schimbările** cu tests comprehensive 3. **Rulează toate testele** pentru a verifica compatibilitatea 4. **Actualizează documentația** dacă este necesar 5. **Creează Pull Request** cu descriere detaliată ### Development Setup ```bash # Clone repository git clone [repository-url] cd roa-flask # Setup environment python -m venv venv source venv/bin/activate # Linux/Mac # or venv\Scripts\activate # Windows pip install -r requirements.txt # Run tests cd roa2web/shared/auth python -m pytest test_auth.py -v ``` ## 📜 License Acest sistem de autentificare face parte din proiectul ROA2WEB și este disponibil sub aceleași condiții de licențiere ca și proiectul principal. --- **ROA2WEB Authentication System v1.0.0** *Secure, scalable, Oracle-integrated authentication pentru aplicații moderne*