Skip to content

Authentication Guide ​

System Architecture Overview ​

OpenCHS consists of two independent services with distinct authentication mechanisms:

  1. Helpline Service - PHP/MySQL REST API for case management
  2. AI Service - FastAPI/Python containerized AI pipeline

Service Details ​

ServiceTechnologyPortAuthenticationBase Path
Helpline APIPHP 8.2 + MySQL443 (HTTPS)Session-based (OTP)/helpline/api/
AI PipelineFastAPI + Celery8123Token/API Key/audio/, /whisper/, etc.

Helpline Service Authentication ​

Technology Stack ​

  • Backend: PHP 8.2 with PHP-FPM
  • Database: MySQL with unix_socket authentication
  • Web Server: Nginx with SSL/TLS
  • Session Storage: MySQL session table

Authentication Flow ​

Step 1: Request OTP ​

bash
curl -X POST https://your-domain.com/helpline/api/sendOTP \
  -H "Content-Type: application/json" \
  -d '{
    "addr_addr": "user@example.com",
    "addr_type": "email"
  }'

Response:

json
{
  "success": true,
  "message": "OTP sent to user@example.com"
}

Step 2: Verify OTP ​

bash
curl -X POST https://your-domain.com/helpline/api/verifyOTP \
  -H "Content-Type: application/json" \
  -d '{
    "addr_addr": "user@example.com",
    "otp": "123456"
  }'

Response: Sets HELPLINE_SESSION_ID cookie for subsequent requests.

json
{
  "success": true,
  "user": {
    "id": 123,
    "username": "operator_name",
    "role": "case_manager"
  }
}

Step 3: Make Authenticated Requests ​

bash
curl -X GET https://your-domain.com/helpline/api/cases \
  -H "Cookie: HELPLINE_SESSION_ID=abc123xyz..."

Step 4: Logout ​

bash
curl -X POST https://your-domain.com/helpline/api/logout \
  -H "Cookie: HELPLINE_SESSION_ID=abc123xyz..."

Database Schema ​

Sessions Table (helpline.session):

sql
CREATE TABLE session (
  session_id VARCHAR(255) PRIMARY KEY,
  user_id INT NOT NULL,
  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  last_activity TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  ip_address VARCHAR(45),
  user_agent TEXT
);

Authentication Table (helpline.auth):

sql
CREATE TABLE auth (
  id INT PRIMARY KEY AUTO_INCREMENT,
  username VARCHAR(100) UNIQUE NOT NULL,
  password_hash VARCHAR(255) NOT NULL,
  email VARCHAR(255),
  phone VARCHAR(20),
  role ENUM('admin', 'supervisor', 'case_manager', 'operator'),
  is_active BOOLEAN DEFAULT TRUE,
  last_login TIMESTAMP NULL
);

AI Service Authentication ​

Technology Stack ​

  • Backend: FastAPI 0.116+ (Python 3.11+)
  • Task Queue: Celery with Redis
  • Container: Docker with GPU support
  • Authentication: API Key / Token-based (optional)

API Endpoints (No Authentication Required by Default) ​

The AI service is designed for internal use and doesn't enforce authentication by default. It's accessed by the Helpline service backend.

Audio Processing ​

bash
# Complete pipeline processing
curl -X POST http://localhost:8123/audio/process \
  -F "audio=@recording.wav" \
  -F "language=sw" \
  -F "include_translation=true"

Individual Model Services ​

bash
# Transcription only
curl -X POST http://localhost:8123/whisper/transcribe \
  -F "audio=@recording.wav" \
  -F "language=sw"

# Translation only
curl -X POST http://localhost:8123/translate/ \
  -H "Content-Type: application/json" \
  -d '{
    "text": "Msichana mdogo ana miaka 12",
    "source_language": "sw",
    "target_language": "en"
  }'

# Named Entity Recognition
curl -X POST http://localhost:8123/ner/extract \
  -H "Content-Type: application/json" \
  -d '{
    "text": "Maria lives in Nairobi and works at City Hospital"
  }'

Health Checks ​

bash
# Detailed system status
curl http://localhost:8123/health/detailed

# Model loading status
curl http://localhost:8123/health/models

# Worker status
curl http://localhost:8123/audio/workers/status

Adding Authentication to AI Service (Optional) ​

For production deployments where AI service needs external access:

Option 1: API Key Authentication

python
# app/middleware/auth.py
from fastapi import Header, HTTPException

async def verify_api_key(x_api_key: str = Header(...)):
    if x_api_key != os.getenv("AI_SERVICE_API_KEY"):
        raise HTTPException(status_code=401, detail="Invalid API key")
    return x_api_key

# Usage in endpoint
@app.post("/audio/process")
async def process_audio(
    audio: UploadFile,
    api_key: str = Depends(verify_api_key)
):
    # Process audio
    pass

Option 2: JWT Token Authentication

python
# app/middleware/jwt_auth.py
from jose import JWTError, jwt
from fastapi import Depends, HTTPException
from fastapi.security import HTTPBearer

security = HTTPBearer()

async def verify_token(token: str = Depends(security)):
    try:
        payload = jwt.decode(
            token.credentials,
            os.getenv("JWT_SECRET_KEY"),
            algorithms=["HS256"]
        )
        return payload
    except JWTError:
        raise HTTPException(status_code=401, detail="Invalid token")

Development Environment Setup ​

Helpline Service Setup ​

1. Database Setup ​

bash
# Create MySQL user with unix_socket authentication
sudo mysql -e "CREATE USER 'nginx'@'localhost' IDENTIFIED VIA unix_socket;"

# Create database
sudo mysql -e "CREATE DATABASE helpline;"

# Import schema
sudo mysql helpline < /usr/src/OpenChs/rest_api/uchl.sql

# Grant permissions
sudo mysql -e "
GRANT SELECT, INSERT ON helpline.* TO 'nginx'@'localhost';
GRANT UPDATE ON helpline.auth TO 'nginx'@'localhost';
GRANT UPDATE ON helpline.contact TO 'nginx'@'localhost';
GRANT UPDATE ON helpline.kase TO 'nginx'@'localhost';
GRANT DELETE ON helpline.session TO 'nginx'@'localhost';
FLUSH PRIVILEGES;"

2. PHP-FPM Configuration ​

bash
# Install PHP and extensions
sudo apt-get install php8.2 php8.2-fpm php8.2-mysql

# Configure PHP-FPM
sudo nano /etc/php/8.2/fpm/pool.d/www.conf

Key settings in www.conf:

ini
user = nginx
group = nginx
listen = /run/php/php8.2-fpm.sock
listen.owner = nginx
listen.group = nginx

3. Nginx Configuration ​

bash
# Install Nginx
sudo apt-get install nginx

# Copy SSL certificates
sudo mkdir -p /etc/pki/openchs/private
sudo cp openchs.crt /etc/pki/openchs/
sudo cp openchs.key /etc/pki/openchs/private/

Nginx server block:

nginx
server {
    listen 443 ssl;
    server_name your-domain.com;
    root /var/www/html;

    ssl_certificate "/etc/pki/openchs/openchs.crt";
    ssl_certificate_key "/etc/pki/openchs/private/openchs.key";
    ssl_protocols TLSv1.2 TLSv1.3;

    location /helpline/ {
        index index.php index.html;
        try_files $uri $uri/ /helpline/api/index.php?$args;
    }

    location ~ \.php$ {
        fastcgi_pass unix:/run/php/php8.2-fpm.sock;
        fastcgi_index index.php;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    }
}

4. Deploy Application ​

bash
# Copy application files
sudo cp -r /path/to/helpline/files/* /var/www/html/helpline/

# Set permissions
sudo chown -R nginx:nginx /var/www/html/helpline/
sudo chmod -R 755 /var/www/html/helpline/

# Restart services
sudo systemctl restart php8.2-fpm
sudo systemctl restart nginx

AI Service Setup ​

1. Clone and Configure ​

bash
git clone <ai-service-repo>
cd ai-service

# Copy environment file
cp .env.example .env

# Edit configuration
nano .env

Key environment variables:

bash
# Core settings
DEBUG=false
LOG_LEVEL=INFO
MAX_CONCURRENT_GPU_REQUESTS=1
REQUEST_TIMEOUT=300

# Redis configuration
REDIS_URL=redis://localhost:6379/0
REDIS_TASK_DB=1

# Optional authentication
AI_SERVICE_API_KEY=your-secure-api-key

2. Start with Docker ​

bash
# Start all services
docker-compose up -d

# Check status
docker-compose ps

# View logs
docker-compose logs -f ai-pipeline

3. Verify Installation ​

bash
# Check API health
curl http://localhost:8123/health/detailed

# Check GPU availability
curl http://localhost:8123/health/models

# Test transcription
curl -X POST http://localhost:8123/whisper/transcribe \
  -F "audio=@test_audio.wav" \
  -F "language=en"

Cross-Service Integration ​

Helpline Calling AI Service ​

The Helpline backend (PHP) calls the AI service for audio processing:

php
<?php
// helpline/api/services/AIServiceClient.php

class AIServiceClient {
    private $baseUrl;
    private $apiKey;
    
    public function __construct() {
        $this->baseUrl = getenv('AI_SERVICE_URL') ?: 'http://localhost:8123';
        $this->apiKey = getenv('AI_SERVICE_API_KEY');
    }
    
    public function transcribeAudio($audioPath, $language = 'sw') {
        $ch = curl_init();
        
        $postFields = [
            'audio' => new CURLFile($audioPath),
            'language' => $language,
            'include_translation' => 'true'
        ];
        
        $headers = [];
        if ($this->apiKey) {
            $headers[] = "X-API-Key: {$this->apiKey}";
        }
        
        curl_setopt_array($ch, [
            CURLOPT_URL => "{$this->baseUrl}/audio/process",
            CURLOPT_POST => true,
            CURLOPT_POSTFIELDS => $postFields,
            CURLOPT_HTTPHEADER => $headers,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_TIMEOUT => 300
        ]);
        
        $response = curl_exec($ch);
        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        curl_close($ch);
        
        if ($httpCode !== 200) {
            throw new Exception("AI Service error: HTTP $httpCode");
        }
        
        return json_decode($response, true);
    }
    
    public function getTaskStatus($taskId) {
        $ch = curl_init();
        
        curl_setopt_array($ch, [
            CURLOPT_URL => "{$this->baseUrl}/audio/task/{$taskId}",
            CURLOPT_RETURNTRANSFER => true
        ]);
        
        $response = curl_exec($ch);
        curl_close($ch);
        
        return json_decode($response, true);
    }
}
?>

Usage in case processing:

php
<?php
// Example: Process audio when case is created
$aiClient = new AIServiceClient();

try {
    // Transcribe and analyze audio
    $result = $aiClient->transcribeAudio(
        $_FILES['audio']['tmp_name'],
        'sw'  // Swahili
    );
    
    // Store results in case
    $caseData = [
        'transcript' => $result['transcript'],
        'translation' => $result['translation'],
        'entities' => json_encode($result['entities']),
        'classification' => $result['classification']['main_category'],
        'priority' => $result['classification']['priority']
    ];
    
    // Save to database
    saveCaseData($caseData);
    
} catch (Exception $e) {
    error_log("AI processing failed: " . $e->getMessage());
    // Handle error - case can still be created without AI analysis
}
?>

Testing Authentication ​

Helpline Service Tests ​

bash
# Test OTP flow
curl -X POST https://localhost/helpline/api/sendOTP \
  -k \  # Skip SSL verification for local testing
  -H "Content-Type: application/json" \
  -d '{"addr_addr": "test@example.com", "addr_type": "email"}'

# Check session creation
sudo mysql -e "SELECT * FROM helpline.session ORDER BY created_at DESC LIMIT 5;"

AI Service Tests ​

bash
# Test health endpoint
curl http://localhost:8123/health/detailed | jq

# Test audio processing
curl -X POST http://localhost:8123/whisper/transcribe \
  -F "audio=@sample.wav" \
  -F "language=en" | jq

# Test worker status
curl http://localhost:8123/audio/workers/status | jq

Security Considerations ​

Helpline Service Security ​

SSL/TLS Configuration:

  • Use strong ciphers (already configured in nginx)
  • TLS 1.2 and 1.3 only
  • HSTS headers recommended

Session Security:

php
// session_config.php
ini_set('session.cookie_httponly', 1);
ini_set('session.cookie_secure', 1);  // HTTPS only
ini_set('session.cookie_samesite', 'Lax');
ini_set('session.gc_maxlifetime', 86400);  // 24 hours

Database Security:

  • Unix socket authentication (no passwords over network)
  • Minimal permissions per user
  • Regular session cleanup

AI Service Security ​

Network Isolation:

yaml
# docker-compose.yml
services:
  ai-pipeline:
    networks:
      - internal
    # Only expose to Helpline service, not public internet

API Key Protection:

bash
# .env
AI_SERVICE_API_KEY=$(openssl rand -hex 32)

# Rotate keys periodically
# Store in secure secret management system

Troubleshooting ​

Helpline Service Issues ​

1. "Session not found" errors

bash
# Check session table
sudo mysql -e "SELECT COUNT(*) FROM helpline.session;"

# Check PHP session configuration
php -i | grep session

# View PHP-FPM logs
sudo tail -f /var/log/php8.2-fpm.log

2. "Database connection failed"

bash
# Verify unix socket authentication
sudo mysql -e "SELECT user, host, plugin FROM mysql.user WHERE user='nginx';"

# Check PHP-FPM user
ps aux | grep php-fpm

# Test connection
sudo -u nginx mysql -e "SELECT 1;"

3. "OTP not sending"

bash
# Check PHP mail configuration
php -i | grep mail

# View nginx error logs
sudo tail -f /var/log/nginx/error.log

AI Service Issues ​

1. "Model loading failed"

bash
# Check model files
docker-compose exec ai-pipeline ls -la /app/models/

# Check GPU availability
docker-compose exec ai-pipeline nvidia-smi

# View detailed logs
docker-compose logs ai-pipeline | grep -i "model"

2. "Worker not responding"

bash
# Check Celery worker status
docker-compose exec celery-worker celery -A app.celery_app inspect active

# Restart workers
docker-compose restart celery-worker

# Check Redis connectivity
docker-compose exec ai-pipeline redis-cli ping

3. "Out of memory errors"

bash
# Check GPU memory
docker stats

# Adjust concurrent requests
# Edit .env: MAX_CONCURRENT_GPU_REQUESTS=1

# Restart services
docker-compose restart

Production Deployment Checklist ​

Helpline Service ​

  • [ ] SSL certificates properly installed
  • [ ] Database backups configured
  • [ ] Session cleanup cron job setup
  • [ ] PHP-FPM tuned for production load
  • [ ] Nginx configured with security headers
  • [ ] Firewall rules limiting access
  • [ ] Monitoring and logging enabled

AI Service ​

  • [ ] GPU drivers and CUDA installed
  • [ ] Docker volumes for model persistence
  • [ ] Redis persistence enabled
  • [ ] Resource limits configured
  • [ ] Health check monitoring setup
  • [ ] Log aggregation configured
  • [ ] Backup AI service instance ready

This authentication guide provides complete setup and integration instructions for both the Helpline PHP/MySQL service and the AI FastAPI/Docker service in the OpenCHS system.