TL;DR
A conformidade HIPAA para APIs exige controles de segurança rígidos para Informações de Saúde Protegidas (PHI): criptografia em trânsito/repouso, registro de auditoria, controle de acesso e acordos de associados de negócios. Este guia mostra padrões de arquitetura de API, autenticação, trilhas de auditoria e verificação de conformidade para apps de saúde que manipulam PHI.
Introdução
Violações de dados de saúde custam, em média, US$ 10,93 milhões por incidente. Para desenvolvedores de apps de saúde, segurança de API não é opcional—é exigida pela lei HIPAA (Health Insurance Portability and Accountability Act).
79% das violações de dados de saúde envolvem acesso não autorizado via APIs e falhas de aplicativos. Uma arquitetura de API compatível com HIPAA, bem projetada, previne violações, permite trilhas de auditoria e protege a privacidade do paciente.
Este guia detalha o processo de conformidade de API HIPAA. Aqui você aprende como tratar PHI, padrões de criptografia, controle de acesso, registro de auditoria e documentação de conformidade. Ao final, você terá uma arquitetura de API HIPAA pronta para produção.
💡 Projete endpoints seguros, valide criptografia, audite acessos e documente controles de conformidade em um só workspace com o Apidog. Compartilhe especificações de API com o time de compliance e mantenha documentação pronta para auditoria.
O Que É HIPAA e Por Que É Importante para APIs?
HIPAA é uma lei federal que define padrões nacionais para proteger dados sensíveis de saúde. A Regra de Segurança do HIPAA trata especificamente de ePHI transmitida por APIs.
Quem Deve Cumprir
| Tipo de Entidade | Exemplos | Implicações da API |
|---|---|---|
| Entidades Abrangidas | Provedores de saúde, planos de saúde, câmaras de compensação | Responsabilidade direta pelo HIPAA |
| Associados de Negócios | Provedores de API, cloud, fornecedores de software | BAA exigido, responsabilidade direta |
| Subcontratados | Subprocessadores, serviços de API downstream | BAA exigido |
Principais Regras HIPAA para APIs
Regra de Privacidade: uso e divulgação de PHI
- Padrão mínimo necessário
- Direitos de acesso do paciente
- Requisitos de autorização
Regra de Segurança: salvaguardas técnicas para ePHI
- Controles de acesso
- Controles de auditoria
- Controles de integridade
- Segurança da transmissão
Regra de Notificação de Violação:
- Prazo de notificação de 60 dias
- Documentação de avaliação de risco
- Procedimentos de mitigação
Visão Geral da Arquitetura da API
Uma arquitetura compatível com HIPAA inclui:
┌─────────────────────────────────────────────────────────────────┐
│ PILHA DE API COMPATÍVEL COM HIPAA │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ CLIENTE │───▶│ GATEWAY │───▶│ BANCO DE │ │
│ │ (Aplicativo)│ │ DA API │ │ DADOS │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ OAuth 2.0 │ │ WAF + │ │ Registro │ │
│ │ + MFA │ │ Limite de │ │ de │ │
│ │ │ │ Taxa │ │ Auditoria │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
│ │
│ Todos os dados criptografados: TLS 1.3+ em trânsito, AES-256 em repouso │
│ │
└─────────────────────────────────────────────────────────────────┘
Primeiros Passos: Fundação da Conformidade
Passo 1: Executar Acordos de Associado de Negócios (BAA)
Antes de manipular PHI:
- Identifique todos os fornecedores com acesso a PHI
- Execute BAA com cada fornecedor
- Documente subprocessadores em seus BAAs
- Revise anualmente e atualize conforme necessário
Fornecedores críticos que exigem BAA:
- Cloud (AWS, GCP, Azure)
- Provedores de banco de dados
- Serviços de logging
- Provedores de backup
- Gateways de API
- Ferramentas de monitoramento
NÃO use sem BAA:
- Google Analytics padrão
- Cloud free tier
- Contas de e-mail pessoais
- Canais do Slack não relacionados à saúde
Passo 2: Classificação de Dados
Classifique todos os dados que sua API manipula:
| Tipo de Dados | Classificação | Nível de Proteção |
|---|---|---|
| Nome do paciente + Data de Nascimento | PHI | Controles HIPAA completos |
| Número de registro médico | PHI | Controles HIPAA completos |
| Códigos de diagnóstico (CID-10) | PHI | Controles HIPAA completos |
| Notas de tratamento | PHI | Controles HIPAA completos |
| Horários de consulta (sem ID) | Não PHI | Controles padrão |
| Dados agregados, desidentificados | Não PHI | Controles padrão |
Passo 3: Padrão Mínimo Necessário
Expose apenas dados mínimos necessários:
// RUIM: Retorna todos os dados do paciente
app.get('/api/patients/:id', async (req, res) => {
const patient = await db.patients.findById(req.params.id);
res.json(patient); // Retorna tudo
});
// BOM: Filtragem em nível de campo
app.get('/api/patients/:id', async (req, res) => {
const fields = req.query.fields?.split(',') || ['id', 'name'];
const allowedFields = ['id', 'name', 'dateOfBirth'];
const patient = await db.patients.findById(req.params.id);
const filtered = Object.fromEntries(
Object.entries(patient).filter(([key]) => allowedFields.includes(key))
);
res.json(filtered);
});
Implementação de Salvaguardas Técnicas
Controle de Acesso: Autenticação
Implemente autenticação forte:
const crypto = require('crypto');
const jwt = require('jsonwebtoken');
const bcrypt = require('bcrypt');
// Autenticação multifator necessária
class HIPAAAuthService {
async authenticate(username, password, mfaCode) {
const user = await this.getUserByUsername(username);
if (!user) throw new Error('Invalid credentials');
const validPassword = await bcrypt.compare(password, user.passwordHash);
if (!validPassword) throw new Error('Invalid credentials');
// Verificar MFA (TOTP)
const validMFA = this.verifyTOTP(user.mfaSecret, mfaCode);
if (!validMFA) throw new Error('Invalid MFA code');
// Gerar JWT curto (15 min)
const token = jwt.sign(
{
sub: user.id,
role: user.role,
mfa_verified: true
},
process.env.JWT_SECRET,
{ expiresIn: '15m' }
);
// Registrar tentativa de autenticação
await this.auditLog('AUTH_SUCCESS', { userId: user.id, ip: req.ip });
return { token, expiresIn: 900 };
}
verifyTOTP(secret, token) {
const period = 30;
const digits = 6;
const now = Math.floor(Date.now() / 1000);
const counter = Math.floor(now / period);
const buffer = Buffer.alloc(8);
buffer.writeUInt32BE(0, 0);
buffer.writeUInt32BE(counter, 4);
const hmac = crypto.createHmac('sha1', secret).update(buffer).digest();
const offset = hmac[hmac.length - 1] & 0xf;
const code = (
((hmac[offset] & 0x7f) << 24) |
((hmac[offset + 1] & 0xff) << 16) |
((hmac[offset + 2] & 0xff) << 8) |
(hmac[offset + 3] & 0xff)
) % Math.pow(10, digits);
return code.toString().padStart(digits, '0') === token;
}
}
Controle de Acesso: Autorização
Implemente RBAC:
const ROLES = {
ADMIN: 'admin',
PROVIDER: 'provider',
NURSE: 'nurse',
BILLING: 'billing',
PATIENT: 'patient'
};
const PERMISSIONS = {
[ROLES.ADMIN]: ['read:all', 'write:all', 'delete:all'],
[ROLES.PROVIDER]: ['read:patients', 'write:patients', 'read:labs', 'write:orders'],
[ROLES.NURSE]: ['read:patients', 'write:vitals', 'read:labs'],
[ROLES.BILLING]: ['read:billing', 'read:patients:limited'],
[ROLES.PATIENT]: ['read:self', 'write:self']
};
const authorize = (...requiredPermissions) => {
return async (req, res, next) => {
const user = req.user;
const userPermissions = PERMISSIONS[user.role] || [];
const hasPermission = requiredPermissions.every(
perm => userPermissions.includes(perm)
);
if (!hasPermission) {
await auditLog('AUTHZ_DENIED', {
userId: user.id,
action: req.method,
path: req.path,
required: requiredPermissions
});
return res.status(403).json({ error: 'Insufficient permissions' });
}
next();
};
};
// Uso
app.get('/api/patients/:id/records',
authenticate,
authorize('read:patients'),
getPatientRecords
);
Criptografia em Trânsito
Force TLS 1.3 em todas as comunicações:
const https = require('https');
const fs = require('fs');
const options = {
key: fs.readFileSync('server-key.pem'),
cert: fs.readFileSync('server-cert.pem'),
ca: fs.readFileSync('ca-cert.pem'),
minVersion: 'TLSv1.3',
ciphers: [
'TLS_AES_256_GCM_SHA384',
'TLS_CHACHA20_POLY1305_SHA256',
'TLS_AES_128_GCM_SHA256'
].join(':'),
honorCipherOrder: true
};
const server = https.createServer(options, app);
// Redirecionamento HTTPS
app.use((req, res, next) => {
if (!req.secure) {
return res.redirect(`https://${req.headers.host}${req.url}`);
}
next();
});
// Cabeçalho HSTS
app.use((req, res, next) => {
res.setHeader(
'Strict-Transport-Security',
'max-age=31536000; includeSubDomains; preload'
);
next();
});
Criptografia em Repouso
Criptografe PHI armazenada:
const crypto = require('crypto');
class EncryptionService {
constructor(key) {
// Use AWS KMS, GCP KMS ou Azure Key Vault para chaves
this.key = crypto.scryptSync(key, 'salt', 32);
this.algorithm = 'aes-256-gcm';
}
encrypt(plaintext) {
const iv = crypto.randomBytes(16);
const cipher = crypto.createCipheriv(this.algorithm, this.key, iv);
let encrypted = cipher.update(plaintext, 'utf8', 'hex');
encrypted += cipher.final('hex');
const authTag = cipher.getAuthTag().toString('hex');
return {
encryptedData: encrypted,
iv: iv.toString('hex'),
authTag: authTag
};
}
decrypt(encryptedData, iv, authTag) {
const decipher = crypto.createDecipheriv(
this.algorithm,
this.key,
Buffer.from(iv, 'hex')
);
decipher.setAuthTag(Buffer.from(authTag, 'hex'));
let decrypted = decipher.update(encryptedData, 'hex', 'utf8');
decrypted += decipher.final('utf8');
return decrypted;
}
}
// Modelo com criptografia
class PatientRecord {
constructor(db, encryptionService) {
this.db = db;
this.encryption = encryptionService;
}
async create(data) {
const encryptedData = {
...data,
ssn: this.encryption.encrypt(data.ssn),
diagnosis: this.encryption.encrypt(data.diagnosis),
treatmentNotes: this.encryption.encrypt(data.treatmentNotes)
};
await this.db.patients.insert(encryptedData);
await auditLog('PHI_CREATED', { recordType: 'patient' });
}
async findById(id) {
const record = await this.db.patients.findById(id);
return {
...record,
ssn: this.encryption.decrypt(record.ssn.encryptedData, record.ssn.iv, record.ssn.authTag),
diagnosis: this.encryption.decrypt(record.diagnosis.encryptedData, record.diagnosis.iv, record.diagnosis.authTag),
treatmentNotes: this.encryption.decrypt(record.treatmentNotes.encryptedData, record.treatmentNotes.iv, record.treatmentNotes.authTag)
};
}
}
Implementação de Controles de Auditoria
Registro de Auditoria Abrangente
Registre todo acesso a PHI:
const winston = require('winston');
const auditLogger = winston.createLogger({
level: 'info',
format: winston.format.combine(
winston.format.timestamp(),
winston.format.json()
),
transports: [
new winston.transports.File({
filename: '/var/log/hipaa-audit/audit.log',
maxsize: 52428800,
maxFiles: 365
}),
new winston.transports.Http({
host: 'siem.internal',
path: '/api/logs',
ssl: true
})
]
});
const auditLog = async (event, details) => {
const logEntry = {
timestamp: new Date().toISOString(),
event: event,
actor: details.userId,
action: details.action,
resource: details.resource,
outcome: details.outcome || 'SUCCESS',
ipAddress: details.ip,
userAgent: details.userAgent,
details: details.metadata
};
auditLogger.info(logEntry);
await db.auditLogs.insert(logEntry);
};
app.use((req, res, next) => {
const start = Date.now();
res.on('finish', async () => {
const duration = Date.now() - start;
if (req.path.includes('/patients') || req.path.includes('/records')) {
await auditLog('API_ACCESS', {
userId: req.user?.id || 'anonymous',
action: req.method,
resource: req.path,
outcome: res.statusCode < 400 ? 'SUCCESS' : 'FAILURE',
ip: req.ip,
userAgent: req.headers['user-agent'],
metadata: {
duration: duration,
statusCode: res.statusCode,
queryParams: Object.keys(req.query)
}
});
}
});
next();
});
Eventos de Auditoria Obrigatórios
| Tipo de Evento | O que Registrar | Retenção |
|---|---|---|
| Autenticação | Sucesso/falha, status MFA, IP | 6 anos |
| Autorização | Tentativas de acesso negadas | 6 anos |
| Acesso a PHI | Quem acessou o quê, quando | 6 anos |
| Modificação de PHI | Valores antes/depois | 6 anos |
| Exclusão de PHI | O que foi excluído, por quem | 6 anos |
| Alterações no Sistema | Alterações de config, novos usuários | 6 anos |
| Eventos de Segurança | Falhas, limites de taxa | 6 anos |
Geração de Relatórios de Auditoria
Exporte relatórios de conformidade:
const generateAuditReport = async (startDate, endDate, options = {}) => {
const query = {
timestamp: {
$gte: new Date(startDate),
$lte: new Date(endDate)
}
};
if (options.userId) query.actor = options.userId;
if (options.eventType) query.event = options.eventType;
const logs = await db.auditLogs.find(query).sort({ timestamp: 1 });
return {
reportPeriod: { start: startDate, end: endDate },
generatedAt: new Date().toISOString(),
summary: {
totalEvents: logs.length,
uniqueUsers: new Set(logs.map(l => l.actor)).size,
failures: logs.filter(l => l.outcome === 'FAILURE').length,
phiAccess: logs.filter(l => l.event === 'PHI_ACCESS').length
},
events: logs
};
};
// Relatórios semanais agendados
cron.schedule('0 0 * * 1', async () => {
const end = new Date();
const start = new Date(end.getTime() - 7 * 24 * 60 * 60 * 1000);
const report = await generateAuditReport(start, end);
await sendToComplianceTeam(report);
});
Melhores Práticas de Segurança de API
Validação de Entrada
Previna injeção:
const { body, param, query, validationResult } = require('express-validator');
// Validação rigorosa para todas as entradas
const validatePatientRequest = [
body('firstName')
.trim()
.notEmpty()
.matches(/^[a-zA-Z\s'-]+$/)
.withMessage('Invalid first name format')
.isLength({ max: 50 }),
body('dateOfBirth')
.isISO8601()
.withMessage('Invalid date format')
.custom(value => new Date(value) < new Date())
.withMessage('Date of birth must be in the past'),
body('ssn')
.optional()
.matches(/^\d{3}-\d{2}-\d{4}$/)
.withMessage('Invalid SSN format'),
body('email')
.optional()
.isEmail()
.normalizeEmail(),
param('id')
.isUUID()
.withMessage('Invalid patient ID format'),
(req, res, next) => {
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(400).json({
error: 'Validation failed',
details: errors.array()
});
}
next();
}
];
Limitação de Taxa (Rate Limiting)
Previna abuso e força bruta:
const rateLimit = require('express-rate-limit');
// Limite para autenticação
const authLimiter = rateLimit({
windowMs: 15 * 60 * 1000,
max: 5,
message: { error: 'Too many authentication attempts' },
standardHeaders: true,
legacyHeaders: false,
handler: async (req, res) => {
await auditLog('RATE_LIMIT_EXCEEDED', {
userId: req.body.username,
ip: req.ip,
endpoint: 'auth'
});
res.status(429).json({ error: 'Too many attempts' });
}
});
// Limite geral de API
const apiLimiter = rateLimit({
windowMs: 60 * 1000,
max: 100,
message: { error: 'Rate limit exceeded' }
});
app.use('/api/auth', authLimiter);
app.use('/api', apiLimiter);
Tratamento de Erros
Evite vazamento de informações:
// Respostas genéricas
app.use((err, req, res, next) => {
// Log interno detalhado
console.error('Error:', {
message: err.message,
stack: err.stack,
path: req.path,
user: req.user?.id
});
res.status(err.status || 500).json({
error: 'An error occurred processing your request',
requestId: req.id
});
});
// Nunca exponha:
// - Stack traces
// - Esquema do banco
// - IPs internos
// - Contagem de usuários
// - PHI em mensagens de erro
Violações Comuns da API HIPAA e Como Evitá-las
Violação: Controles de Acesso Inadequados
Cenário: API permite acesso irrestrito a registros de pacientes.
Correção: Implemente checagem de autorização:
// RUIM: Sem verificação
app.get('/api/patients/:id', async (req, res) => {
const patient = await db.patients.findById(req.params.id);
res.json(patient);
});
// BOM: Cheque relacionamento
app.get('/api/patients/:id', async (req, res) => {
const patient = await db.patients.findById(req.params.id);
// Se o usuário é o paciente
if (req.user.id === patient.userId) {
return res.json(patient);
}
// Se o usuário é o provedor atribuído
const assignment = await db.providerAssignments.findOne({
providerId: req.user.id,
patientId: patient.id
});
if (assignment) {
return res.json(patient);
}
await auditLog('UNAUTHORIZED_ACCESS_ATTEMPT', {
userId: req.user.id,
patientId: patient.id
});
res.status(403).json({ error: 'Access denied' });
});
Violação: Registros de Auditoria Ausentes
Cenário: Não há registro de quem acessou dados do paciente.
Correção: Registre todo acesso a PHI conforme acima.
Violação: Transmissão de Dados Não Criptografados
Cenário: API aceita conexões HTTP.
Correção: Force HTTPS + HSTS:
app.use((req, res, next) => {
if (!req.secure && process.env.NODE_ENV === 'production') {
return res.status(403).json({
error: 'HTTPS required. Connect via https://' + req.headers.host
});
}
res.setHeader('Strict-Transport-Security', 'max-age=31536000; includeSubDomains');
next();
});
Violação: Exposição Excessiva de Dados
Cenário: API retorna todos os dados do paciente quando só o nome é necessário.
Correção: Filtragem em nível de campo:
app.get('/api/patients/:id', async (req, res) => {
const fields = req.query.fields?.split(',') || ['id', 'name'];
const projection = Object.fromEntries(fields.map(f => [f, 1]));
const patient = await db.patients.findById(req.params.id, projection);
res.json(patient);
});
Lista de Verificação de Implantação em Produção
Antes de lidar com PHI ao vivo:
- [ ] Execute BAA com todos os fornecedores
- [ ] Implemente MFA para todos os usuários
- [ ] Habilite TLS 1.3 para todos os endpoints
- [ ] Criptografe PHI em repouso (AES-256)
- [ ] Implemente registro de auditoria abrangente
- [ ] Configure retenção de logs (6+ anos)
- [ ] Configure RBAC
- [ ] Implemente rate limiting
- [ ] Tenha plano de resposta a incidentes
- [ ] Documente todos controles de segurança
- [ ] Realize avaliação de risco de segurança
- [ ] Treine equipe sobre HIPAA
- [ ] Agende auditorias regulares
Modelo de Avaliação de Risco de Segurança
## Avaliação de Risco de Segurança HIPAA
### Visão Geral do Sistema
- Nome do Sistema: [Nome da API]
- Tipos de PHI Manipulados: [Lista]
- Fluxo de Dados: [Diagrama]
### Avaliação de Ameaças
| Ameaça | Probabilidade | Impacto | Mitigação |
|----------------------|--------------|---------|-------------|
| Acesso não autorizado| Médio | Alto | MFA, RBAC |
| Violação de dados | Baixo | Crítico | Criptografia|
| Ameaça interna | Médio | Alto | Logs auditoria|
### Teste de Controle
- [ ] Teste de bypass de autenticação
- [ ] Teste de bypass de autorização
- [ ] Teste de injeção SQL
- [ ] Teste XSS
- [ ] Verificação de criptografia
### Assinatura
Oficial de Segurança: _______________ Data: _______
CTO: _______________ Data: _______
Casos de Uso do Mundo Real
API de Plataforma de Telemedicina
Startup de telessaúde: consultas por vídeo compatíveis HIPAA.
- Desafio: Transmissão segura de vídeo entre paciente e provedor
- Solução: WebRTC E2E criptografado e sinalização via API HIPAA
- Resultado: SOC 2 Tipo II, 500k+ consultas sem violação
Implementação:
- Autenticação JWT + MFA
- Tokens de sala efêmeros (expiram após consulta)
- Sem PHI em logs
- BAA com Twilio para vídeo
API do Portal do Paciente
Sistema hospitalar moderniza acesso do paciente.
- Desafio: 20+ sistemas legados, segurança inconsistente
- Solução: Gateway de API unificado, autenticação e auditoria centralizadas
- Resultado: Fonte única de verdade, compliance simplificada
Implementação:
- OAuth 2.0 com SMART on FHIR
- Auditoria centralizada
- Controle de acesso por campo
- Detecção de violações automatizada
Plataforma de Integração de Dados de Saúde
Empresa agrega dados de múltiplos EHRs.
- Desafio: Diferentes modelos de segurança nos fornecedores
- Solução: Camada de abstração com controles HIPAA uniformes
- Resultado: 100+ integrações hospitalares, zero não-conformidades
Implementação:
- Normalização e criptografia de dados consistente
- Trilhas de auditoria por locatário
- Rastreamento automatizado de BAA
- Painéis de conformidade em tempo real
Conclusão
A conformidade HIPAA para APIs exige decisões de arquitetura deliberadas em autenticação, criptografia, controle de acesso e auditoria. Pilares para desenvolvedores:
- Execute BAAs com todos os fornecedores antes de manipular PHI
- Implemente MFA e RBAC
- Criptografe dados em trânsito (TLS 1.3) e repouso (AES-256)
- Registre todo acesso a PHI com retenção de 6 anos
- Aplique padrão mínimo necessário em todos endpoints
- O Apidog agiliza documentação e compliance de API.
Seção de Perguntas Frequentes
O que torna uma API compatível com HIPAA?
Uma API é compatível ao implementar salvaguardas técnicas (criptografia, controle de acesso, logs de auditoria), administrativas (políticas, treinamento, BAAs) e físicas exigidas pela Regra de Segurança do HIPAA para proteger ePHI.
Preciso de um BAA para minha API?
Sim, se sua API manipula, processa ou armazena PHI em nome de uma entidade abrangida, você é um Associado de Negócios e deve assinar um BAA. Isso inclui clouds, APIs e subprocessadores.
Que criptografia é exigida pelo HIPAA?
HIPAA exige criptografia "em trânsito" e "em repouso". Use TLS 1.3 para APIs e AES-256 para dados armazenados. Mesmo sendo "endereçável", é exigida para conformidade.
Por quanto tempo os logs HIPAA devem ser retidos?
6 anos a partir da criação ou última efetividade do registro, o que for posterior.
Posso usar JWT para autenticação compatível com HIPAA?
Sim, se implementado corretamente: expiração curta (máx. 15 min para PHI), armazenamento seguro, rotação de refresh tokens. Sempre combine com MFA.
O que é o padrão mínimo necessário?
APIs só devem expor a PHI mínima necessária ao propósito. Implemente filtragem por campo e controle de acesso por finalidade.
Logs de auditoria precisam ser criptografados?
Sim, logs com PHI devem ser criptografados em repouso e armazenados em storage somente anexado.
Como lidar com notificação de violação?
Se houver acesso não autorizado a PHI: 1) Contenha, 2) Avalie risco (4 fatores), 3) Notifique afetados em até 60 dias, 4) Notifique HHS (>500 pessoas: imediato), 5) Documente tudo.
Posso usar cloud para workloads HIPAA?
Sim, se o provedor assinar BAA. AWS, GCP e Azure têm serviços elegíveis. Configure conforme o guia HIPAA do provedor.
Que penalidades existem para violações HIPAA?
Civis: US$ 100 a US$ 50.000/violação, até US$ 1,5 milhão/ano por categoria. Criminais: até US$ 250.000 e 10 anos de prisão.
Top comments (0)