Autenticação e Segurança
Visão Geral
O SystemClinic utiliza autenticação própria baseada em JWT (JSON Web Tokens) emitidos pela API .NET. Não há dependência de Firebase SDK no frontend — toda a autenticação é gerenciada pela API backend.
Fluxo de Autenticação
Login
1. Usuário envia e-mail e senha → POST /auth/login
2. API valida credenciais (bcrypt)
3. API gera:
- Access Token (JWT, curta duração)
- Refresh Token (longa duração, armazenado com hash no banco)
4. Tokens retornados ao frontend
5. Angular armazena tokens em memória (não no localStorage)
6. Interceptor anexa Bearer Token em toda requisição à APIRefresh Automático
O interceptor Angular detecta respostas 401 e automaticamente:
- Chama
POST /auth/refreshcom o Refresh Token - Recebe um novo par de tokens
- Repete a requisição original com o novo Access Token
Se o refresh falhar (token expirado ou revogado), o usuário é redirecionado para a tela de login.
Logout
1. Frontend chama POST /auth/logout
2. API revoga o Refresh Token no banco (marca como revogado)
3. Frontend descarta os tokens da memória
4. Usuário é redirecionado para /loginEstrutura do JWT
Claims presentes no Access Token:
| Claim | Descrição | Exemplo |
|---|---|---|
sub | ID do usuário | "uuid-do-usuario" |
org | ID da organização | "uuid-da-org" |
role | Papel do usuário | "ADMIN" |
units | IDs das unidades permitidas | ["uuid1", "uuid2"] |
email | E-mail do usuário | "user@clinica.com" |
iat | Emitido em (issued at) | Unix timestamp |
exp | Expira em (expiration) | Unix timestamp |
iss | Emissor | "systemclinic-api" |
aud | Audiência | "systemclinic-web" |
Recuperação de Senha
1. Usuário acessa /forgot-password e informa o e-mail
2. API gera um reset_token e armazena no Redis com TTL de 1 hora
3. E-mail com link de redefinição é enviado via Resend
4. Usuário clica no link, informar nova senha
5. API valida o token, atualiza o password_hash
6. Todos os refresh tokens do usuário são revogados
7. Usuário é redirecionado para loginConvite de Usuário
1. Admin acessa Usuários → Convidar Usuário
2. Informa e-mail e papel do novo usuário
3. API cria o usuário com flag must_change_password=true
4. Token de convite gerado (Redis, TTL 48h) e e-mail enviado
5. Novo usuário clica no link do convite
6. Página /accept-invite solicita definição de senha
7. API valida o token, define a senha e retorna tokens de sessãoRevogação de Tokens
Tokens são revogados automaticamente em:
- Logout manual do usuário
- Alteração de papel (role) por um Admin
- Inativação do usuário
- Redefinição de senha
Na próxima requisição com token revogado, a API retorna 401 e o frontend redireciona para login.
Endpoints de Autenticação
| Método | Endpoint | Descrição |
|---|---|---|
POST | /auth/login | Login com e-mail e senha |
POST | /auth/refresh | Renovar access token |
POST | /auth/logout | Revogar sessão |
POST | /auth/forgot-password | Solicitar redefinição de senha |
POST | /auth/reset-password | Confirmar nova senha |
POST | /auth/accept-invite | Aceitar convite de usuário |
GET | /auth/me | Retornar perfil do usuário autenticado |
Segurança de Transporte
- TLS 1.3 obrigatório em produção
- HSTS ativado com preload
- Headers de segurança:
X-Content-Type-Options,X-Frame-Options,Referrer-Policy - CORS: Apenas origens autorizadas (frontend SPA)
Rate Limiting
| Endpoint | Limite |
|---|---|
/auth/login | 10 tentativas/minuto por IP |
| API autenticada | 600 req/min por user_id |
| API pública | 60 req/min por IP |
Respostas com limite excedido retornam 429 Too Many Requests com o header Retry-After.
Firebase Storage
O armazenamento de arquivos usa o Firebase Storage com validação de tenant. Uploads são feitos via API .NET (não diretamente pelo frontend):
- Frontend envia o arquivo via multipart para
POST /files/upload - API valida o tipo MIME e tamanho (máximo 20 MB)
- API faz upload para Firebase Storage no caminho
/{orgId}/{context}/{fileName} - API retorna a path do arquivo
- Para acesso, o frontend solicita uma Signed URL temporária à API
- A URL expira em aproximadamente 1 hora
Arquivos são sempre scoped pelo
organizationId, prevenindo acesso cross-tenant.