Pular para conteúdo

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

GET /api/me/
Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...

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

GET /api/patients/
Authorization: Bearer {token}
X-Clinic-ID: 1

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:

GET /api/me/
Authorization: Bearer {token}

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

  1. Nunca exponha o refresh token no localStorage em produção
  2. Use HTTPS em produção
  3. Configure CORS corretamente
  4. Rotacione SECRET_KEY periodicamente

Configurações Django

# settings.py
SIMPLE_JWT = {
    'ACCESS_TOKEN_LIFETIME': timedelta(minutes=60),
    'REFRESH_TOKEN_LIFETIME': timedelta(days=7),
    'ROTATE_REFRESH_TOKENS': True,
}

# CORS apenas para origens específicas em produção
CORS_ALLOWED_ORIGINS = [
    "https://app.suaclinica.com.br",
]