# Authentication Flow

## Overview

The KPI Analysis Dashboard uses JWT (JSON Web Token) based authentication with support for both LDAP and fallback authentication methods.

## Authentication Flow Diagram

```
┌─────────────────────────────────────────────────────────────────┐
│                     User Access Flow                             │
└─────────────────────────────────────────────────────────────────┘

1. User visits http://localhost:8000/
   │
   ├─→ Server: GET /
   │   └─→ Response: 302 Redirect to /login
   │
2. Browser loads /login page
   │
   ├─→ JavaScript checks localStorage for 'kpi_token'
   │   │
   │   ├─→ Token exists?
   │   │   ├─→ YES: Validate with /api/auth/me
   │   │   │   ├─→ Valid: Redirect to /dashboard
   │   │   │   └─→ Invalid: Clear token, stay on login
   │   │   │
   │   │   └─→ NO: Show login form
   │
3. User enters credentials (admin/super)
   │
   ├─→ POST /api/auth/login
   │   └─→ Request: {"username": "admin", "password": "super"}
   │
4. Server validates credentials
   │
   ├─→ Try LDAP authentication (if configured)
   │   ├─→ LDAP available?
   │   │   ├─→ YES: Authenticate with LDAP
   │   │   │   ├─→ Success: Check group membership
   │   │   │   │   ├─→ In KPI group: Create token
   │   │   │   │   └─→ Not in group: Reject
   │   │   │   └─→ Failed: Try fallback
   │   │   │
   │   │   └─→ NO: Try fallback
   │   │
   ├─→ Try Fallback authentication (if enabled)
   │   ├─→ Credentials match fallback?
   │   │   ├─→ YES: Create token
   │   │   └─→ NO: Reject (401)
   │
5. Server creates JWT token
   │
   ├─→ Token contains:
   │   ├─→ user_id
   │   ├─→ username
   │   ├─→ email
   │   ├─→ role
   │   ├─→ exp (expiration)
   │   └─→ iat (issued at)
   │
6. Server responds with token
   │
   └─→ Response: {
       "success": true,
       "access_token": "eyJhbGc...",
       "token_type": "bearer",
       "user": {...}
   }
   │
7. Client stores token
   │
   ├─→ localStorage.setItem('kpi_token', token)
   ├─→ localStorage.setItem('kpi_user', user)
   │
8. Client redirects to /dashboard
   │
9. Dashboard page loads
   │
   ├─→ JavaScript checks for token
   │   ├─→ No token: Redirect to /login
   │   └─→ Has token: Continue
   │
10. Validate token with backend
    │
    ├─→ GET /api/auth/me
    │   └─→ Headers: Authorization: Bearer <token>
    │
11. Server validates token
    │
    ├─→ Decode JWT
    │   ├─→ Valid signature?
    │   ├─→ Not expired?
    │   └─→ User exists?
    │
12. Server responds
    │
    ├─→ Valid: Return user info
    │   └─→ Dashboard shows content
    │
    └─→ Invalid: Return 401
        └─→ Client redirects to /login

┌─────────────────────────────────────────────────────────────────┐
│                     Protected API Access                         │
└─────────────────────────────────────────────────────────────────┘

User makes API request
│
├─→ GET /api/files/list
│   └─→ Headers: Authorization: Bearer <token>
│
Server validates token
│
├─→ Token valid?
│   ├─→ YES: Process request
│   │   └─→ Return data
│   │
│   └─→ NO: Return 401
│       └─→ Client redirects to /login

┌─────────────────────────────────────────────────────────────────┐
│                        Logout Flow                               │
└─────────────────────────────────────────────────────────────────┘

User clicks logout
│
├─→ POST /api/auth/logout (optional)
│   └─→ Headers: Authorization: Bearer <token>
│
├─→ Clear localStorage
│   ├─→ localStorage.removeItem('kpi_token')
│   └─→ localStorage.removeItem('kpi_user')
│
└─→ Redirect to /login
```

## Authentication Methods

### 1. LDAP Authentication (Primary)

```
┌─────────────────────────────────────────────────────────────────┐
│                    LDAP Authentication                           │
└─────────────────────────────────────────────────────────────────┘

1. User provides credentials
   │
2. Connect to LDAP server
   │
   ├─→ Server: ldap://192.168.10.10:389
   │
3. Search for user
   │
   ├─→ Base DN: DC=your-company,DC=com
   ├─→ Filter: (uid={username})
   │
4. User found?
   │
   ├─→ YES: Bind as user with password
   │   │
   │   ├─→ Bind successful?
   │   │   │
   │   │   ├─→ YES: Check group membership
   │   │   │   │
   │   │   │   ├─→ Get user's memberOf attribute
   │   │   │   ├─→ Check if KPI_Users group DN is in list
   │   │   │   │
   │   │   │   ├─→ In group: AUTHENTICATED ✅
   │   │   │   └─→ Not in group: REJECTED ❌
   │   │   │
   │   │   └─→ NO: REJECTED ❌
   │   │
   └─→ NO: REJECTED ❌
```

### 2. Fallback Authentication (Development)

```
┌─────────────────────────────────────────────────────────────────┐
│                  Fallback Authentication                         │
└─────────────────────────────────────────────────────────────────┘

1. User provides credentials
   │
2. Check if fallback enabled
   │
   ├─→ ENABLE_FALLBACK_AUTH=true?
   │   │
   │   ├─→ YES: Continue
   │   └─→ NO: REJECTED ❌
   │
3. Compare credentials
   │
   ├─→ username == FALLBACK_ADMIN_USERNAME?
   ├─→ password == FALLBACK_ADMIN_PASSWORD?
   │
   ├─→ Both match: AUTHENTICATED ✅
   └─→ No match: REJECTED ❌
```

## Token Structure

### JWT Token Payload
```json
{
  "user_id": "admin",
  "username": "admin",
  "email": "admin@kpi-system.local",
  "role": "admin",
  "exp": 1764057689,  // Expiration timestamp
  "iat": 1764054089,  // Issued at timestamp
  "sub": "admin"      // Subject (username)
}
```

### Token Validation
```
1. Extract token from Authorization header
   │
2. Decode JWT
   │
   ├─→ Verify signature with SECRET_KEY
   │   ├─→ Valid: Continue
   │   └─→ Invalid: REJECT ❌
   │
3. Check expiration
   │
   ├─→ exp > current_time?
   │   ├─→ YES: Continue
   │   └─→ NO: REJECT ❌ (Token expired)
   │
4. Extract user info
   │
   └─→ Return user data ✅
```

## Security Features

### 1. Token Expiration
- Tokens expire after 1 hour (configurable)
- Expired tokens are automatically rejected
- Users must login again after expiration

### 2. Secure Storage
- Tokens stored in browser localStorage
- Cleared on logout
- Not accessible to other domains

### 3. HTTPS (Production)
- All communication encrypted
- Tokens protected in transit
- Prevents man-in-the-middle attacks

### 4. Group-Based Access (LDAP)
- Only users in KPI_Users group can access
- Group membership verified on each login
- Centralized access control

### 5. Role-Based Authorization
- User roles stored in token
- Can be used for feature access control
- Admin vs regular user permissions

## Configuration

### Environment Variables

```bash
# Fallback Authentication
ENABLE_FALLBACK_AUTH=true
FALLBACK_ADMIN_USERNAME=admin
FALLBACK_ADMIN_PASSWORD=super
FALLBACK_ADMIN_ROLE=admin
FALLBACK_ADMIN_EMAIL=admin@kpi-system.local

# LDAP Configuration
LDAP_SERVER=192.168.10.10
LDAP_PORT=389
LDAP_USE_SSL=false
LDAP_BASE_DN=DC=your-company,DC=com
LDAP_BIND_DN=CN=service-account,OU=Service Accounts,DC=your-company,DC=com
LDAP_BIND_PASSWORD=your-ldap-password

# LDAP Group Configuration
LDAP_KPI_GROUP_DN=CN=KPI_Users,OU=Groups,DC=your-company,DC=com
LDAP_GROUP_MEMBER_ATTRIBUTE=member
LDAP_USER_MEMBER_ATTRIBUTE=memberOf

# Security
SECRET_KEY=your-secret-key-here-change-in-production
SESSION_TIMEOUT_MINUTES=60
```

## Testing

### Test Authentication
```bash
python test_auth.py
```

### Test API Endpoints
```bash
# Login
curl -X POST http://localhost:8000/api/auth/login \
  -H "Content-Type: application/json" \
  -d '{"username":"admin","password":"super"}'

# Get user info
curl http://localhost:8000/api/auth/me \
  -H "Authorization: Bearer <token>"

# Logout
curl -X POST http://localhost:8000/api/auth/logout \
  -H "Authorization: Bearer <token>"
```

## Troubleshooting

### Issue: Can't login
**Solution:**
1. Check fallback auth is enabled: `ENABLE_FALLBACK_AUTH=true`
2. Verify credentials: `admin` / `super`
3. Check browser console for errors
4. Clear localStorage and try again

### Issue: Token expired
**Solution:**
1. Login again to get new token
2. Adjust `SESSION_TIMEOUT_MINUTES` if needed

### Issue: LDAP not working
**Solution:**
1. Install ldap3: `pip install ldap3`
2. Check LDAP server is accessible
3. Verify LDAP credentials
4. Test with: `GET /api/auth/test`

### Issue: Dashboard redirects to login
**Solution:**
This is correct behavior if:
- No token in localStorage
- Token is expired
- Token is invalid

Login again to get a new token.

## Best Practices

### Development
- ✅ Use fallback authentication
- ✅ Enable debug mode
- ✅ Use HTTP for local testing
- ✅ Short token expiration for testing

### Production
- ✅ Disable fallback authentication
- ✅ Use LDAP/Active Directory
- ✅ Enable HTTPS
- ✅ Change SECRET_KEY to random value
- ✅ Set appropriate token expiration
- ✅ Enable rate limiting
- ✅ Add CSRF protection
- ✅ Use secure session storage
- ✅ Enable audit logging
- ✅ Regular security updates
