Autenticação
Visão Geral
A API do Cidadão.AI implementa um sistema de autenticação multi-camadas baseado em padrões da indústria, fornecendo controle de acesso seguro através de tokens JWT, integração OAuth 2.0 e permissões baseadas em funções.
Métodos de Autenticação
1. Autenticação JWT (Principal)
A API usa JSON Web Tokens (JWT) como mecanismo de autenticação principal, seguindo as especificações RFC 7519.
Estrutura do Token
{
"header": {
"alg": "RS256",
"typ": "JWT",
"kid": "2024-01-key"
},
"payload": {
"sub": "550e8400-e29b-41d4-a716-446655440000",
"email": "usuario@exemplo.com",
"role": "usuario",
"permissoes": ["ler:investigacoes", "escrever:relatorios"],
"iat": 1706616000,
"exp": 1706616900,
"jti": "id-token-unico"
},
"signature": "..."
}
Ciclo de Vida do Token
2. Integração OAuth 2.0
Suporte para provedores de autenticação de terceiros:
- Google (OpenID Connect)
- GitHub (OAuth 2.0)
- Microsoft (Azure AD)
- Provedores SAML/OIDC personalizados
Fluxo OAuth
3. Autenticação por Chave de API (Legado)
Para compatibilidade regressiva e comunicação serviço-a-serviço:
X-API-Key: sk_live_50e8400-e29b-41d4-a716-446655440000
Endpoints de Autenticação
Login
POST /api/v1/auth/login
Content-Type: application/json
{
"email": "usuario@exemplo.com",
"senha": "senha-segura"
}
Resposta:
{
"token_acesso": "eyJhbGciOiJSUzI1NiIs...",
"token_renovacao": "eyJhbGciOiJSUzI1NiIs...",
"tipo_token": "Bearer",
"expira_em": 900,
"usuario": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"email": "usuario@exemplo.com",
"funcao": "usuario",
"permissoes": ["ler:investigacoes", "escrever:relatorios"]
}
}
Renovação de Token
POST /api/v1/auth/refresh
Content-Type: application/json
{
"token_renovacao": "eyJhbGciOiJSUzI1NiIs..."
}
Registro de Usuário
POST /api/v1/auth/register
Authorization: Bearer {token_admin}
Content-Type: application/json
{
"email": "novousuario@exemplo.com",
"senha": "senha-segura",
"funcao": "analista"
}
Alterar Senha
POST /api/v1/auth/change-password
Authorization: Bearer {token}
Content-Type: application/json
{
"senha_atual": "senha-antiga",
"nova_senha": "nova-senha-segura"
}
Autorização
Controle de Acesso Baseado em Funções (RBAC)
| Função | Descrição | Permissões |
|---|---|---|
admin | Administrador do sistema | Acesso total a todos os recursos |
analista | Analista de dados | Criar investigações, análises, relatórios |
visualizador | Usuário somente leitura | Ver investigações e relatórios públicos |
servico | Conta de serviço | Acesso à API para integrações |
Modelo de Permissões
class Permissao(Enum):
# Investigações
LER_INVESTIGACOES = "ler:investigacoes"
ESCREVER_INVESTIGACOES = "escrever:investigacoes"
DELETAR_INVESTIGACOES = "deletar:investigacoes"
# Análises
LER_ANALISES = "ler:analises"
ESCREVER_ANALISES = "escrever:analises"
# Relatórios
LER_RELATORIOS = "ler:relatorios"
ESCREVER_RELATORIOS = "escrever:relatorios"
# Admin
GERENCIAR_USUARIOS = "gerenciar:usuarios"
VER_LOGS_AUDITORIA = "ver:auditoria"
CONFIGURAR_SISTEMA = "configurar:sistema"
Permissões de Nível de Recurso
# Verificar propriedade
if investigacao.usuario_id != usuario_atual.id and not usuario_atual.eh_admin:
raise ErroProibido("Você não tem permissão para acessar este recurso")
# Verificar acesso da equipe
if investigacao.id_equipe not in usuario_atual.ids_equipe:
raise ErroProibido("Este recurso pertence a outra equipe")
Headers de Segurança
Headers de Requisição
Authorization: Bearer eyJhbGciOiJSUzI1NiIs...
X-Request-ID: 550e8400-e29b-41d4-a716-446655440000
X-Client-Version: 1.0.0
Headers de Resposta
X-Request-ID: 550e8400-e29b-41d4-a716-446655440000
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 999
X-Frame-Options: DENY
X-Content-Type-Options: nosniff
Gerenciamento de Tokens
Armazenamento de Tokens (Lado do Cliente)
// Recomendações de armazenamento seguro
class GerenciadorToken {
// Armazenar na memória para apps web
private tokenAcesso: string;
// Armazenar em armazenamento seguro para mobile
async armazenarTokenRenovacao(token: string) {
await SecureStore.setItemAsync('token_renovacao', token);
}
// Nunca armazenar em localStorage para apps sensíveis
// Use cookies httpOnly quando possível
}
Validação de Token
def validar_token(token: str) -> PayloadToken:
try:
# Verificar assinatura
payload = jwt.decode(
token,
CHAVE_PUBLICA,
algorithms=["RS256"],
options={"verify_exp": True}
)
# Verificar claims adicionais
if payload.get("iss") != "https://api.cidadao.ai":
raise ErroTokenInvalido("Emissor inválido")
# Verificar se token não foi revogado
if token_revogado(payload["jti"]):
raise ErroTokenInvalido("Token foi revogado")
return PayloadToken(**payload)
except jwt.ExpiredSignatureError:
raise ErroTokenExpirado("Token expirou")
except jwt.InvalidTokenError as e:
raise ErroTokenInvalido(f"Token inválido: {str(e)}")