Autenticação
A sessão é um cookie
Entrar define sb_admin_session: HttpOnly, Path=/admin, SameSite=Strict.
O token nunca aparece num corpo de resposta, e Authorization: Bearer não é aceito nesta
superfície. Um XSS que consegue ler um token consegue se passar por um operador
indefinidamente; um que só consegue usar um cookie é limitado pelo browser.
SameSite=Strict raciocina sobre o domínio registrável, não sobre a origem.
admin.slotbattle.exemplo.com e api.slotbattle.exemplo.com são cross-origin mas same-site, e
funcionam. console.exemplo.net e api.exemplo.com não.
Erre isso e toda requisição autenticada falha em silêncio: o browser nunca anexa o cookie, nada loga erro, e as requisições voltam não autenticadas.
Decida isso antes de comprar os domínios. Não dá para contornar pelo código da aplicação.
CORS também importa aqui. Credenciais só são permitidas para uma origem nomeada, nunca para
*, e uma allowlist de origem vazia faz o browser se recusar a enviar o cookie.
Três formas de entrar
Senha, opcionalmente com um código TOTP quando a conta tem segundo fator ativo.
Magic link, um código de uso único enviado por e-mail para o endereço.
Reset de senha, o mesmo mecanismo com desfecho diferente.
202 incondicionalmenteElas respondem 202 exista ou não o endereço, que é o que impede usá-las para enumerar contas.
Isso também significa que e-mail não entregue é invisível pela API: se o e-mail não está
configurado, a rota ainda responde 202 e nada chega.
slotbattle:config-check é o que pega isso. A API não vai pegar.
Segundo fator
Faça o enrolamento, depois ative com um código. A ativação retorna códigos de recuperação, mostrados uma vez, sob a mesma regra das chaves de API.
Desativar TOTP é um DELETE com corpo carregando a senha. A alternativa,
POST /totp/disable, descreve o efeito com menos precisão.
invalid_code significa três coisas ao mesmo tempo
Errado, expirado e já usado respondem invalid_code. Não existe code_expired.
Distingui-los diria a quem está sondando um magic link que ele tinha o código certo mas chegou tarde.
Trocando de casino
O casino ativo viaja no X-Tenant-Id, não no token de sessão, que é o que permite a um
operador com acesso a vários casinos trocar sem se reautenticar.
A associação é checada em toda requisição, então o header declara uma intenção, e não um direito. Nomear um casino do qual você não é membro é recusado.
GET /admin/tenants é a única coleção alcançável sem o header: ela desenha o seletor de
casino, então exigir um casino faria escolher um depender de já ter escolhido um.
Throttling
Toda rota não autenticada é limitada dentro do próprio handler. Falhas sustentadas respondem
too_many_requests.
Falhas comuns
| Sintoma | Causa |
|---|---|
Todo login responde 500, inclusive com a senha certa | O segredo do JWT está vazio |
| O login passa, mas toda requisição seguinte fica não autenticada | Console e API em domínios registráveis diferentes |
| O browser se recusa a enviar o cookie | Allowlist de origem vazia, ou flag secure do cookie com HTTP puro |
| Magic links nunca chegam | E-mail não configurado. A API não consegue reportar isso, então rode o config check |