Monalisa

Autenticação

Como a sessão chega à API (cookie host-only ou Bearer) e o que ainda está em reconstrução.

O login ainda está em reconstrução: nenhuma rota emite sessão hoje e toda rota protegida responde 401. Esta página descreve o que já está no código (NOVA-118), não o desenho do login.

Estado atual

  • Os endpoints antigos de login, sessão e refresh foram removidos.
  • Toda rota protegida passa por AuthenticateSession, que pede a um SessionResolver para transformar o token da sessão em sessão. Em produção, o resolver ligado não resolve nada, então toda rota protegida responde 401.
  • Rotas públicas continuam funcionando: /health, /ready, /docs e /openapi.json.
  • Cabeçalhos como x-tenant-id, x-user-id e x-system nunca estabelecem identidade nem autoridade.
  • Os testes da API autenticam com um resolver falso (FakeSessionResolver), que apresenta o token como Bearer ou como cookie.

De onde vem o token da sessão

A API aceita o token de duas fontes. O contrato OpenAPI declara os dois esquemas, Bearer e SessionCookie, como alternativas em toda rota protegida.

FontePara quem
Cookie __Host-monalisa_sessionO navegador: o cookie é HttpOnly, então o site nunca guarda o token
Authorization: Bearer <token>Os demais clientes

O Bearer vence. Regras de leitura:

  • O esquema Bearer é reconhecido sem diferenciar maiúsculas; token vazio ou com mais de uma parte recebe 401 antes de qualquer consulta.
  • Um Authorization com outro esquema (por exemplo, Basic acrescentado por um proxy) não é fonte de sessão: é ignorado, e o cookie continua autenticando.
  • Se a requisição manda Bearer e cookie com tokens diferentes, recebe 401: os dois nomeiam sessões diferentes.
  • Uma credencial grande demais recebe 401. Tokens nunca aparecem em mensagens de erro, detalhes ou logs.

Por padrão o cookie é host-only: __Host-monalisa_session, com HttpOnly; Secure; SameSite=Lax; Path=/ e sem Domain. O prefixo __Host- faz o navegador recusar qualquer cópia com Domain ou com Path mais estreito, então um subdomínio vizinho não consegue plantar um cookie que esconda o verdadeiro. O site e a API ficam sob o mesmo site registrável, então o fetch com credenciais do site já leva o cookie host-only da API.

  • Duplicatas. Um cabeçalho Cookie que traz o nome do cookie de sessão mais de uma vez recebe 401, porque uma cópia plantada venceria em silêncio.
  • SESSION_COOKIE_DOMAIN (opcional). Só para um consumidor do lado do servidor confirmado num host vizinho (como SSR que repassa o cookie). O cookie passa a se chamar __Secure-monalisa_session, com esse Domain, e chega a todos os subdomínios. O valor precisa ser um host simples, em minúsculas, com pelo menos dois rótulos e que não seja um sufixo público conhecido; senão a API não sobe.
  • A definição do cookie (nome e atributos) existe num lugar só, e o esquema SessionCookie do OpenAPI tira o nome dela.

Um POST, PUT, PATCH ou DELETE autenticado pelo cookie precisa trazer um Origin (ou, sem ele, um Referer) cuja origem esteja exatamente listada em CORS_ORIGINS. Sem isso, recebe 403 antes de a sessão ser resolvida.

  • Requisições com Bearer e requisições GET, HEAD e OPTIONS não passam por essa checagem. Uma página estranha não consegue mandar Authorization, porque o preflight de CORS dela não recebe Access-Control-Allow-Origin.
  • Com CORS_ORIGINS vazio (o padrão), toda escrita autenticada por cookie recebe 403. Uma implantação em que o site e a API dividem o mesmo host também precisa listar a própria origem.
  • O site não deve contar com Referrer-Policy: no-referrer para clientes que omitem Origin.

CORS

Ambientes que usam o cookie definem CORS_CREDENTIALS=true e listam as origens exatas do site em CORS_ORIGINS; a mesma lista alimenta o CORS e a checagem de origem. A API não sobe com CORS_CREDENTIALS=true e CORS_ORIGINS vazio, e recusa * ou qualquer origem que não seja exata, em qualquer ambiente. Staging ainda usa CORS_CREDENTIALS=false até o login emitir cookies.

O que já existe no banco

O schema de identidade continua no baseline: users, user_logins (por tenant), platform_logins (operador de plataforma, sem tenant), user_credentials, sessions, refresh_tokens, session_memberships, session_membership_brokers e session_contexts. Nenhuma rota grava sessões hoje. O primeiro operador de plataforma é criado pelo bootstrap, mas ainda não tem como fazer login.

Ver Identity para as tabelas.

Nesta página