Healthcare applications handling Protected Health Information (PHI) must comply with HIPAA regulations. Django provides the foundation for secure, compliant applications. At ZIRA Software, we've built HIPAA-compliant platforms for healthcare providers.
HIPAA Requirements Overview
HIPAA Safeguards
├── Administrative
│ ├── Security policies
│ ├── Access management
│ └── Training
├── Physical
│ ├── Facility access
│ └── Workstation security
└── Technical
├── Access controls
├── Audit controls
├── Integrity controls
└── Transmission security
Encryption at Rest
# settings.py
from cryptography.fernet import Fernet
# Generate and store securely (use secrets manager in production)
ENCRYPTION_KEY = os.environ.get('ENCRYPTION_KEY')
# Custom encrypted field
# app/fields.py
from django.db import models
from cryptography.fernet import Fernet
from django.conf import settings
class EncryptedCharField(models.CharField):
def __init__(self, *args, **kwargs):
kwargs['max_length'] = kwargs.get('max_length', 255) * 2
super().__init__(*args, **kwargs)
self.fernet = Fernet(settings.ENCRYPTION_KEY)
def from_db_value(self, value, expression, connection):
if value is None:
return value
return self.fernet.decrypt(value.encode()).decode()
def get_prep_value(self, value):
if value is None:
return value
return self.fernet.encrypt(value.encode()).decode()
# Usage in models
class Patient(models.Model):
name = models.CharField(max_length=100)
ssn = EncryptedCharField(max_length=11)
medical_record_number = EncryptedCharField(max_length=20)
date_of_birth = models.DateField()
Comprehensive Audit Logging
# app/middleware.py
import json
import logging
from django.utils import timezone
audit_logger = logging.getLogger('hipaa_audit')
class HIPAAAuditMiddleware:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
response = self.get_response(request)
# Log PHI access
if self.is_phi_endpoint(request.path):
self.log_access(request, response)
return response
def is_phi_endpoint(self, path):
phi_patterns = ['/patients/', '/records/', '/prescriptions/']
return any(pattern in path for pattern in phi_patterns)
def log_access(self, request, response):
audit_logger.info(json.dumps({
'timestamp': timezone.now().isoformat(),
'user_id': getattr(request.user, 'id', None),
'user_email': getattr(request.user, 'email', 'anonymous'),
'action': request.method,
'resource': request.path,
'ip_address': self.get_client_ip(request),
'user_agent': request.META.get('HTTP_USER_AGENT', ''),
'status_code': response.status_code,
'session_id': request.session.session_key,
}))
def get_client_ip(self, request):
x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR')
if x_forwarded_for:
return x_forwarded_for.split(',')[0]
return request.META.get('REMOTE_ADDR')
# models.py - Audit trail for model changes
from django.db import models
from django.contrib.auth import get_user_model
class AuditLog(models.Model):
ACTION_CHOICES = [
('CREATE', 'Create'),
('READ', 'Read'),
('UPDATE', 'Update'),
('DELETE', 'Delete'),
]
user = models.ForeignKey(get_user_model(), on_delete=models.SET_NULL, null=True)
action = models.CharField(max_length=10, choices=ACTION_CHOICES)
model_name = models.CharField(max_length=100)
object_id = models.CharField(max_length=100)
changes = models.JSONField(null=True)
ip_address = models.GenericIPAddressField()
timestamp = models.DateTimeField(auto_now_add=True)
class Meta:
indexes = [
models.Index(fields=['user', 'timestamp']),
models.Index(fields=['model_name', 'object_id']),
]
Role-Based Access Control
# app/permissions.py
from django.contrib.auth.models import Permission
from django.contrib.contenttypes.models import ContentType
class HIPAAPermissions:
VIEW_PHI = 'view_phi'
EDIT_PHI = 'edit_phi'
EXPORT_PHI = 'export_phi'
ADMIN_PHI = 'admin_phi'
# Create permissions in migration
def create_hipaa_permissions(apps, schema_editor):
Permission.objects.create(
codename='view_phi',
name='Can view Protected Health Information',
content_type=ContentType.objects.get_for_model(Patient),
)
# views.py
from django.contrib.auth.decorators import permission_required
@permission_required('app.view_phi', raise_exception=True)
def patient_detail(request, patient_id):
patient = get_object_or_404(Patient, id=patient_id)
# Log PHI access
AuditLog.objects.create(
user=request.user,
action='READ',
model_name='Patient',
object_id=patient_id,
ip_address=get_client_ip(request),
)
return render(request, 'patients/detail.html', {'patient': patient})
Session Security
# settings.py
SESSION_COOKIE_SECURE = True
SESSION_COOKIE_HTTPONLY = True
SESSION_COOKIE_SAMESITE = 'Strict'
SESSION_EXPIRE_AT_BROWSER_CLOSE = True
SESSION_COOKIE_AGE = 900 # 15 minutes
CSRF_COOKIE_SECURE = True
CSRF_COOKIE_HTTPONLY = True
# Auto-logout after inactivity
SESSION_SAVE_EVERY_REQUEST = True
# middleware.py
class SessionTimeoutMiddleware:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
if request.user.is_authenticated:
last_activity = request.session.get('last_activity')
if last_activity:
elapsed = timezone.now() - datetime.fromisoformat(last_activity)
if elapsed.seconds > settings.SESSION_COOKIE_AGE:
from django.contrib.auth import logout
logout(request)
return redirect('login')
request.session['last_activity'] = timezone.now().isoformat()
return self.get_response(request)
Transmission Security (TLS)
# settings.py
SECURE_SSL_REDIRECT = True
SECURE_HSTS_SECONDS = 31536000
SECURE_HSTS_INCLUDE_SUBDOMAINS = True
SECURE_HSTS_PRELOAD = True
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
# Force HTTPS for all API calls
REST_FRAMEWORK = {
'DEFAULT_RENDERER_CLASSES': [
'rest_framework.renderers.JSONRenderer',
],
}
Backup and Recovery
# management/commands/backup_phi.py
from django.core.management.base import BaseCommand
import subprocess
from datetime import datetime
class Command(BaseCommand):
help = 'Create encrypted backup of PHI data'
def handle(self, *args, **options):
timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
backup_file = f'/secure/backups/phi_backup_{timestamp}.sql'
# Create backup
subprocess.run([
'pg_dump',
'--table=patients',
'--table=medical_records',
'-f', backup_file,
os.environ['DATABASE_URL'],
], check=True)
# Encrypt backup
subprocess.run([
'gpg', '--encrypt',
'--recipient', os.environ['BACKUP_GPG_KEY'],
backup_file,
], check=True)
# Remove unencrypted file
os.remove(backup_file)
self.stdout.write(
self.style.SUCCESS(f'Backup created: {backup_file}.gpg')
)
Security Checklist
## HIPAA Technical Safeguards Checklist
### Access Controls
- [ ] Unique user identification
- [ ] Emergency access procedure
- [ ] Automatic logoff (15 min)
- [ ] Encryption/decryption
### Audit Controls
- [ ] Hardware audit trails
- [ ] Software audit trails
- [ ] Procedural audit trails
### Integrity Controls
- [ ] Data authentication
- [ ] Error correcting memory
- [ ] Magnetic disk storage
### Transmission Security
- [ ] Integrity controls
- [ ] Encryption (TLS 1.3)
Conclusion
HIPAA compliance requires comprehensive security controls across Django applications. Proper encryption, audit logging, and access controls protect PHI and ensure regulatory compliance.
Building healthcare applications? Contact ZIRA Software for HIPAA-compliant development.