# 🔐 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*