Overview
The VoicePact API currently operates without mandatory authentication for most endpoints, making it accessible for underserved communities. However, the system includes built-in security configurations that can be enabled for production deployments.
Current Authentication Status
The current implementation does not enforce authentication on public endpoints. This is designed for ease of use in community deployments but should be enhanced for production use.
Security Configuration
VoicePact includes several security features configured through environment variables:
Secret Keys
# JWT token signing (prepared for future use)
SECRET_KEY = your-secret-key-here
# Token expiration (default: 7 days)
ACCESS_TOKEN_EXPIRE_MINUTES = 10080
# Cryptographic signatures for contracts
SIGNATURE_PRIVATE_KEY = your-signature-key-here
# Password hashing salt
PASSWORD_SALT = your-salt-here
Webhook Security
Webhooks from external services (Africa’s Talking) can be secured:
# Webhook signature validation
WEBHOOK_SECRET = your-webhook-secret-here
# Base URL for webhook endpoints
WEBHOOK_BASE_URL = https://your-domain.com
Authentication Methods
1. No Authentication (Current Default)
Most endpoints are publicly accessible:
curl -X GET http://localhost:8000/api/v1/contracts/AG-2024-001
2. Phone Number Verification
Contract confirmations use phone number-based verification:
curl -X POST http://localhost:8000/api/v1/contracts/AG-2024-001/confirm \
-H "Content-Type: application/json" \
-d '{
"phone_number": "+254712345678"
}'
Only parties listed in the contract can confirm it using their registered phone numbers.
3. SMS-Based Authentication
Contracts are confirmed via SMS replies:
SMS: YES-AG-2024-001
From: +254712345678
The system validates:
Phone number is a contract party
SMS format is correct
Contract exists and is in pending state
Cryptographic Signatures
All contracts include cryptographic signatures for integrity:
Contract Hash
Each contract generates a unique hash using the Blake2b algorithm:
# From core/config.py
contract_hash_algorithm = "blake2b" # or "sha256"
Example contract response:
{
"contract_id" : "AG-2024-001" ,
"contract_hash" : "a8f5f167f44f4964e6c998dee827110c" ,
"status" : "pending"
}
Digital Signatures
Signatures use the Ed25519 algorithm:
# From core/config.py
contract_signature_algorithm = "ed25519" # or "rsa"
Implementing JWT Authentication (Future)
The codebase is prepared for JWT authentication. To implement:
1. Set Environment Variables
# Strong secret key for JWT signing
SECRET_KEY = $( openssl rand -hex 32 )
# Token expiration in minutes
ACCESS_TOKEN_EXPIRE_MINUTES = 60
2. Create Access Tokens
from datetime import datetime, timedelta
from jose import jwt
from app.core.config import get_settings
settings = get_settings()
def create_access_token ( data : dict ):
to_encode = data.copy()
expire = datetime.utcnow() + timedelta(
minutes = settings.access_token_expire_minutes
)
to_encode.update({ "exp" : expire})
return jwt.encode(
to_encode,
settings.get_secret_value( "secret_key" ),
algorithm = "HS256"
)
3. Protect Endpoints
from fastapi import Depends, HTTPException
from fastapi.security import HTTPBearer
security = HTTPBearer()
async def verify_token ( credentials = Depends(security)):
token = credentials.credentials
# Verify JWT token
return decoded_token
@router.get ( "/protected" )
async def protected_endpoint ( token = Depends(verify_token)):
return { "message" : "Authenticated" }
API Key Authentication (Recommended)
For third-party integrations, implement API key authentication:
Generate API Key
python -c "import secrets; print(secrets.token_urlsafe(32))"
Usage Example
curl -X POST http://localhost:8000/api/v1/contracts/create \
-H "X-API-Key: your-api-key-here" \
-H "Content-Type: application/json" \
-d '{...}'
Implement API Key Validation
from fastapi import Header, HTTPException
async def verify_api_key ( x_api_key : str = Header( ... )):
if x_api_key != settings.api_key:
raise HTTPException(
status_code = 403 ,
detail = "Invalid API key"
)
return x_api_key
@router.post ( "/secure-endpoint" )
async def secure_endpoint ( api_key = Depends(verify_api_key)):
return { "message" : "Authorized" }
Webhook Signature Verification
Verify webhooks from Africa’s Talking:
import hmac
import hashlib
def verify_webhook_signature (
payload : str ,
signature : str ,
secret : str
) -> bool :
expected = hmac.new(
secret.encode(),
payload.encode(),
hashlib.sha256
).hexdigest()
return hmac.compare_digest(expected, signature)
Usage in webhook endpoint:
@router.post ( "/webhook" )
async def payment_webhook (
request : Request,
x_signature : str = Header( None )
):
body = await request.body()
if not verify_webhook_signature(
body.decode(),
x_signature,
settings.get_secret_value( "webhook_secret" )
):
raise HTTPException( 403 , "Invalid signature" )
# Process webhook
CORS Configuration
Control which domains can access the API:
# Single origin
CORS_ORIGINS = https://app.voicepact.com
# Multiple origins (comma-separated)
CORS_ORIGINS = https://app.voicepact.com,https://admin.voicepact.com
# Allow credentials
CORS_CREDENTIALS = true
# Allowed methods
CORS_METHODS = GET,POST,PUT,DELETE,OPTIONS
# Allowed headers
CORS_HEADERS = *
Security Best Practices
Always use HTTPS to encrypt data in transit. Configure your reverse proxy (nginx, Caddy) with SSL/TLS certificates. server {
listen 443 ssl http2;
server_name api.voicepact.com;
ssl_certificate /etc/ssl/cert.pem;
ssl_certificate_key /etc/ssl/key.pem;
location / {
proxy_pass http://localhost:8000;
}
}
Regularly rotate your secret keys and update environment variables: # Generate new keys
NEW_SECRET = $( openssl rand -hex 32 )
NEW_SIGNATURE = $( openssl rand -hex 64 )
# Update environment
export SECRET_KEY = $NEW_SECRET
export SIGNATURE_PRIVATE_KEY = $NEW_SIGNATURE
# Restart application
systemctl restart voicepact
Implement rate limiting to prevent abuse: from slowapi import Limiter
from slowapi.util import get_remote_address
limiter = Limiter( key_func = get_remote_address)
@app.post ( "/api/v1/contracts/create" )
@limiter.limit ( "10/minute" )
async def create_contract ( request : Request):
# Create contract
Environment-Specific Settings
Different security levels for different environments:
Development
Testing
Production
ENVIRONMENT = development
DEBUG = true
SECRET_KEY = dev-secret-key
CORS_ORIGINS = http://localhost:3000
ENVIRONMENT = testing
DEBUG = false
SECRET_KEY = test-secret-key
CORS_ORIGINS = http://localhost:3000,http://test.local
ENVIRONMENT = production
DEBUG = false
SECRET_KEY = $( openssl rand -hex 32 )
CORS_ORIGINS = https://app.voicepact.com
# Disable interactive docs
Next Steps
Error Handling Learn how to handle API errors and exceptions
Contract Endpoints Explore contract management endpoints