# Authentication System Documentation

This document describes the authentication and authorization system implemented in the infoscreen_2025 project.

## Overview

The system provides session-based authentication with role-based access control (RBAC). It includes:

- **Backend**: Flask session-based auth with bcrypt password hashing
- **Frontend**: React context/hooks for managing authentication state
- **Permissions**: Decorators for protecting routes based on user roles
- **Roles**: Four levels (user, editor, admin, superadmin)

## Architecture

### Backend Components

#### 1. Auth Routes (`server/routes/auth.py`)

Provides authentication endpoints:

- **`POST /api/auth/login`** - Authenticate user and create session
- **`POST /api/auth/logout`** - End user session
- **`GET /api/auth/me`** - Get current user info (protected)
- **`GET /api/auth/check`** - Quick auth status check

#### 2. Permission Decorators (`server/permissions.py`)

Decorators for protecting routes:

```python
from server.permissions import require_role, admin_or_higher, editor_or_higher

# Require specific role(s)
@app.route('/admin-settings')
@require_role('admin', 'superadmin')
def admin_settings():
    return "Admin only"

# Convenience decorators
@app.route('/settings')
@admin_or_higher  # admin or superadmin
def settings():
    return "Settings"

@app.route('/events', methods=['POST'])
@editor_or_higher  # editor, admin, or superadmin
def create_event():
    return "Create event"
```

Available decorators:
- `@require_auth` - Just require authentication
- `@require_role(*roles)` - Require any of specified roles
- `@superadmin_only` - Superadmin only
- `@admin_or_higher` - Admin or superadmin
- `@editor_or_higher` - Editor, admin, or superadmin

#### 3. Session Configuration (`server/wsgi.py`)

Flask session configured with:
- Secret key from `FLASK_SECRET_KEY` environment variable
- HTTPOnly cookies (prevent XSS)
- SameSite=Lax (CSRF protection)
- Secure flag in production (HTTPS only)

### Frontend Components

#### 1. API Client (`dashboard/src/apiAuth.ts`)

TypeScript functions for auth operations:

```typescript
import { login, logout, fetchCurrentUser } from './apiAuth';

// Login
await login('username', 'password');

// Get current user
const user = await fetchCurrentUser();

// Logout
await logout();

// Check auth status (lightweight)
const { authenticated, role } = await checkAuth();
```

Helper functions:
```typescript
import { hasRole, hasAnyRole, isAdminOrHigher } from './apiAuth';

if (isAdminOrHigher(user)) {
  // Show admin UI
}
```

#### 2. Auth Context/Hooks (`dashboard/src/useAuth.tsx`)

React context for managing auth state:

```typescript
import { useAuth, useCurrentUser, useIsAuthenticated } from './useAuth';

function MyComponent() {
  // Full auth context
  const { user, login, logout, loading, error, isAuthenticated } = useAuth();
  
  // Or just what you need
  const user = useCurrentUser();
  const isAuth = useIsAuthenticated();
  
  if (loading) return <div>Loading...</div>;
  
  if (!isAuthenticated) {
    return <LoginForm onLogin={login} />;
  }
  
  return <div>Welcome {user.username}!</div>;
}
```

## User Roles

Four hierarchical roles with increasing permissions:

| Role | Value | Description | Use Case |
|------|-------|-------------|----------|
| **User** | `user` | Read-only access | View events only |
| **Editor** | `editor` | Can CRUD events/media | Content managers |
| **Admin** | `admin` | Manage settings, users (except superadmin), groups | Organization staff |
| **Superadmin** | `superadmin` | Full system access | Developers, system admins |

### Permission Matrix

| Action | User | Editor | Admin | Superadmin |
|--------|------|--------|-------|------------|
| View events | ✅ | ✅ | ✅ | ✅ |
| Create/edit events | ❌ | ✅ | ✅ | ✅ |
| Manage media | ❌ | ✅ | ✅ | ✅ |
| Manage groups/clients | ❌ | ❌ | ✅ | ✅ |
| Manage users (non-superadmin) | ❌ | ❌ | ✅ | ✅ |
| Manage settings | ❌ | ❌ | ✅ | ✅ |
| Manage superadmins | ❌ | ❌ | ❌ | ✅ |
| System configuration | ❌ | ❌ | ❌ | ✅ |

## Setup Instructions

### 1. Environment Configuration

Add to your `.env` file:

```bash
# Flask session secret key (REQUIRED)
# Generate with: python -c 'import secrets; print(secrets.token_hex(32))'
FLASK_SECRET_KEY=your_secret_key_here

# Superadmin account (REQUIRED for initial setup)
DEFAULT_SUPERADMIN_USERNAME=superadmin
DEFAULT_SUPERADMIN_PASSWORD=your_secure_password
```

### 2. Database Initialization

The superadmin user is created automatically when containers start. See `SUPERADMIN_SETUP.md` for details.

### 3. Frontend Integration

Wrap your app with `AuthProvider` in `main.tsx` or `App.tsx`:

```typescript
import { AuthProvider } from './useAuth';

function App() {
  return (
    <AuthProvider>
      {/* Your app components */}
    </AuthProvider>
  );
}
```

## Usage Examples

### Backend: Protecting Routes

```python
from flask import Blueprint
from server.permissions import require_role, admin_or_higher

users_bp = Blueprint("users", __name__, url_prefix="/api/users")

@users_bp.route("", methods=["GET"])
@admin_or_higher
def list_users():
    """List all users - admin+ only"""
    # Implementation
    pass

@users_bp.route("", methods=["POST"])
@require_role('superadmin')
def create_superadmin():
    """Create superadmin - superadmin only"""
    # Implementation
    pass
```

### Frontend: Conditional Rendering

```typescript
import { useAuth } from './useAuth';
import { isAdminOrHigher, isEditorOrHigher } from './apiAuth';

function NavigationMenu() {
  const { user } = useAuth();
  
  return (
    <nav>
      <a href="/dashboard">Dashboard</a>
      <a href="/events">Events</a>
      
      {isEditorOrHigher(user) && (
        <a href="/events/new">Create Event</a>
      )}
      
      {isAdminOrHigher(user) && (
        <>
          <a href="/settings">Settings</a>
          <a href="/users">Manage Users</a>
          <a href="/groups">Manage Groups</a>
        </>
      )}
    </nav>
  );
}
```

### Frontend: Login Form Example

```typescript
import { useState } from 'react';
import { useAuth } from './useAuth';

function LoginPage() {
  const [username, setUsername] = useState('');
  const [password, setPassword] = useState('');
  const { login, loading, error } = useAuth();
  
  const handleSubmit = async (e: React.FormEvent) => {
    e.preventDefault();
    try {
      await login(username, password);
      // Redirect on success
      window.location.href = '/dashboard';
    } catch (err) {
      // Error is already in auth context
      console.error('Login failed:', err);
    }
  };
  
  return (
    <form onSubmit={handleSubmit}>
      <h1>Login</h1>
      {error && <div className="error">{error}</div>}
      
      <input
        type="text"
        placeholder="Username"
        value={username}
        onChange={(e) => setUsername(e.target.value)}
        disabled={loading}
      />
      
      <input
        type="password"
        placeholder="Password"
        value={password}
        onChange={(e) => setPassword(e.target.value)}
        disabled={loading}
      />
      
      <button type="submit" disabled={loading}>
        {loading ? 'Logging in...' : 'Login'}
      </button>
    </form>
  );
}
```

## Security Considerations

### Backend Security

1. **Password Hashing**: All passwords hashed with bcrypt (salt rounds default)
2. **Session Security**:
   - HTTPOnly cookies (prevent XSS access)
   - SameSite=Lax (CSRF protection)
   - Secure flag in production (HTTPS only)
3. **Secret Key**: Must be set via environment variable, not hardcoded
4. **Role Checking**: Server-side validation on every protected route

### Frontend Security

1. **Credentials**: Always use `credentials: 'include'` in fetch calls
2. **No Password Storage**: Never store passwords in localStorage/sessionStorage
3. **Role Gating**: UI gating is convenience, not security (always validate server-side)
4. **HTTPS**: Always use HTTPS in production

### Production Checklist

- [ ] Generate strong `FLASK_SECRET_KEY` (32+ bytes)
- [ ] Set `SESSION_COOKIE_SECURE=True` (handled automatically by ENV=production)
- [ ] Use HTTPS with valid TLS certificate
- [ ] Change default superadmin password after first login
- [ ] Review and audit user roles regularly
- [ ] Enable audit logging (future enhancement)

## API Reference

### Authentication Endpoints

#### POST /api/auth/login

Authenticate user and create session.

**Request:**
```json
{
  "username": "string",
  "password": "string"
}
```

**Response (200):**
```json
{
  "message": "Login successful",
  "user": {
    "id": 1,
    "username": "admin",
    "role": "admin"
  }
}
```

**Errors:**
- `400` - Missing username or password
- `401` - Invalid credentials or account disabled

#### POST /api/auth/logout

End current session.

**Response (200):**
```json
{
  "message": "Logout successful"
}
```

#### GET /api/auth/me

Get current user information (requires authentication).

**Response (200):**
```json
{
  "id": 1,
  "username": "admin",
  "role": "admin",
  "is_active": true
}
```

**Errors:**
- `401` - Not authenticated or account disabled

#### GET /api/auth/check

Quick authentication status check.

**Response (200):**
```json
{
  "authenticated": true,
  "role": "admin"
}
```

Or if not authenticated:
```json
{
  "authenticated": false
}
```

## Testing

### Manual Testing

1. **Create test users** (via database or future user management UI):
   ```sql
   INSERT INTO users (username, password_hash, role, is_active)
   VALUES ('testuser', '<bcrypt_hash>', 'user', 1);
   ```

2. **Test login**:
   ```bash
   curl -X POST http://localhost:8000/api/auth/login \
     -H "Content-Type: application/json" \
     -d '{"username":"superadmin","password":"your_password"}' \
     -c cookies.txt
   ```

3. **Test /me endpoint**:
   ```bash
   curl http://localhost:8000/api/auth/me -b cookies.txt
   ```

4. **Test protected route**:
   ```bash
   # Should fail without auth
   curl http://localhost:8000/api/protected
   
   # Should work with cookie
   curl http://localhost:8000/api/protected -b cookies.txt
   ```

### Automated Testing

Example test cases (to be implemented):

```python
def test_login_success():
    response = client.post('/api/auth/login', json={
        'username': 'testuser',
        'password': 'testpass'
    })
    assert response.status_code == 200
    assert 'user' in response.json

def test_login_invalid_credentials():
    response = client.post('/api/auth/login', json={
        'username': 'testuser',
        'password': 'wrongpass'
    })
    assert response.status_code == 401

def test_me_authenticated():
    # Login first
    client.post('/api/auth/login', json={'username': 'testuser', 'password': 'testpass'})
    response = client.get('/api/auth/me')
    assert response.status_code == 200
    assert response.json['username'] == 'testuser'

def test_me_not_authenticated():
    response = client.get('/api/auth/me')
    assert response.status_code == 401
```

## Troubleshooting

### Login Not Working

**Symptoms**: Login endpoint returns 401 even with correct credentials

**Solutions**:
1. Verify user exists in database: `SELECT * FROM users WHERE username='...'`
2. Check password hash is valid bcrypt format
3. Verify user `is_active=1`
4. Check server logs for bcrypt errors

### Session Not Persisting

**Symptoms**: `/api/auth/me` returns 401 after successful login

**Solutions**:
1. Verify `FLASK_SECRET_KEY` is set
2. Check frontend is sending `credentials: 'include'` in fetch
3. Verify cookies are being set (check browser DevTools)
4. Check CORS settings if frontend/backend on different domains

### Permission Denied on Protected Route

**Symptoms**: 403 error on decorated routes

**Solutions**:
1. Verify user is logged in (`/api/auth/me`)
2. Check user role matches required role
3. Verify decorator is applied correctly
4. Check session hasn't expired

### TypeScript Errors in Frontend

**Symptoms**: Type errors when using auth hooks

**Solutions**:
1. Ensure `AuthProvider` is wrapping your app
2. Import types correctly: `import type { User } from './apiAuth'`
3. Check TypeScript config for `verbatimModuleSyntax`

## Next Steps

See `userrole-management.md` for the complete implementation roadmap:

1. ✅ **Extend User Model** - Done
2. ✅ **Seed Superadmin** - Done (`init_defaults.py`)
3. ✅ **Expose Current User Role** - Done (this document)
4. ⏳ **Implement Minimal Role Enforcement** - Apply decorators to existing routes
5. ⏳ **Test the Flow** - Verify permissions work correctly
6. ⏳ **Frontend Role Gating** - Update UI components
7. ⏳ **User Management UI** - Build admin interface

## References

- User model: `models/models.py`
- Auth routes: `server/routes/auth.py`
- Permissions: `server/permissions.py`
- API client: `dashboard/src/apiAuth.ts`
- Auth context: `dashboard/src/useAuth.tsx`
- Flask sessions: https://flask.palletsprojects.com/en/latest/api/#sessions
- Bcrypt: https://pypi.org/project/bcrypt/
