Autenticação e Autorização
Visão Geral
O sistema usa JWT (JSON Web Tokens) para autenticação stateless.
sequenceDiagram
participant C as Cliente
participant A as API
participant DB as Banco
C->>A: POST /api/auth/login/ {email, password}
A->>DB: Valida credenciais
DB-->>A: Usuário válido
A-->>C: {access, refresh}
Note over C: Armazena tokens
C->>A: GET /api/patients/<br/>Authorization: Bearer {access}
A->>A: Valida JWT
A->>DB: Busca dados
DB-->>A: Pacientes
A-->>C: Lista de pacientes
Tokens JWT
Access Token
- Validade: 60 minutos
- Uso: Autenticar requisições à API
- Header:
Authorization: Bearer {token}
Refresh Token
- Validade: 7 dias
- Uso: Obter novo access token sem re-login
- Endpoint:
POST /api/auth/refresh/
Fluxo de Login
1. Autenticar
POST /api/auth/login/
Content-Type: application/json
{
"email": "admin@clinic.com",
"password": "admin123"
}
2. Resposta
{
"access": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...",
"refresh": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9..."
}
3. Usar Access Token
4. Renovar Token (quando expirar)
POST /api/auth/refresh/
Content-Type: application/json
{
"refresh": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9..."
}
Multi-Tenancy
Cada usuário pertence a uma ou mais clínicas. O sistema filtra dados automaticamente.
Header X-Clinic-ID
Importante
Sem o header X-Clinic-ID, a API usa a clínica principal do usuário.
Middleware de Tenant
# O middleware extrai a clínica do header
class TenantMiddleware:
def process_request(self, request):
clinic_id = request.headers.get('X-Clinic-ID')
if clinic_id:
request.tenant = Clinic.objects.get(id=clinic_id)
else:
request.tenant = request.user.clinic
Filtragem Automática
Todos os ViewSets filtram por clínica:
class PatientViewSet(viewsets.ModelViewSet):
def get_queryset(self):
return Patient.objects.filter(clinic=self.request.tenant)
Papéis de Usuário
| Papel | Código | Permissões |
|---|---|---|
| Administrador | admin |
Acesso total à clínica |
| Profissional | professional |
Atendimentos, prontuários |
| Recepcionista | receptionist |
Agendamentos, pacientes |
Verificar Papel
# No backend
if request.user.role == 'admin':
# Permite ação administrativa
# No frontend
if (user.role === 'professional') {
// Mostra opção de atendimento
}
Endpoint /api/me/
Retorna dados do usuário autenticado:
Resposta:
{
"id": 1,
"email": "admin@clinic.com",
"name": "Administrador",
"role": "admin",
"clinic": {
"id": 1,
"name": "Clínica Saúde"
},
"additional_clinics": [
{"id": 2, "name": "Clínica Vida"}
]
}
Segurança
Boas Práticas
- Nunca exponha o refresh token no localStorage em produção
- Use HTTPS em produção
- Configure CORS corretamente
- Rotacione SECRET_KEY periodicamente