Pular para o conteúdo principal

Chaves e credenciais

O SlotBattle tem quatro credenciais. Elas não compartilham código, armazenamento nem modos de falha, para que adicionar autenticação a uma rota nova não escolha a errada por proximidade.

CredencialQuem guardaPor onde trafegaRotacionável
Chave de API do tenantBackend do seu casinoAuthorization: BearerEmitir + revogar
Sessão de consoleBrowser de um operadorCookie HttpOnlyExpiração + logout
Token de viewerBrowser de um espectadorSubprotocolo do WebSocketChave de assinatura, com janela
Segredo de callback do gravadorO gravadorHMAC sobre o corpo da requisiçãoRedeploy

1. Chave de API do tenant

A credencial servidor a servidor, e a que o seu backend usa.

Authorization: Bearer sbk_3f9a1c...

Formato. Prefixo sbk_ seguido de 64 caracteres hex (32 bytes aleatórios).

Armazenamento. Só o hash SHA-256 é persistido, mais os 12 primeiros caracteres (sbk_ + 8 hex) para exibição no console. O texto puro é mostrado uma vez, na criação. Não há como exibi-lo de novo: perdê-lo significa emitir uma substituta e revogar a antiga.

Escopos. Cada chave carrega o próprio conjunto, checado por rota:

EscopoConcede
games:readLer o catálogo de jogos
battles:readLer batalhas
battles:writeAbrir e gerenciar batalhas
bots:writeSentar bots
viewer:mintEmitir tokens de viewer
demo:mintEmitir uma sessão de jogo demo. Só avaliação, nunca o fluxo de produção
bots:write é separado de battles:write

Sentar bots gasta as sessões de provedor do próprio casino, o que é um ato diferente de abrir uma batalha. Uma chave que só abre batalhas não consegue enchê-las de bots em silêncio. Emita o conjunto mais estreito que funciona.

Emissão. Pelo console (Casino → Chaves de API), ou pelo seu host, se a sua conta não carrega apikeys.write. A revogação é imediata.

O tenant é derivado da chave, nunca enviado junto. Veja Tenancy.

2. Sessão de console

A credencial do console admin.

É um cookie HttpOnly com escopo /admin, SameSite=Strict, carregando um token de sessão assinado. O token nunca aparece num corpo de resposta, e Authorization: Bearer não é aceito nessa superfície. Um bearer token ao alcance do JavaScript pode ser lido por um XSS e reapresentado indefinidamente; um cookie que o script não lê é limitado pelo browser.

SameSite=Strict restringe o seu DNS

SameSite=Strict raciocina sobre o domínio registrável. O console e a API precisam compartilhar um: painel.exemplo.com e api.exemplo.com funcionam; painel.exemplo.net e api.exemplo.com não.

Separados em domínios registráveis distintos, toda requisição autenticada falha em silêncio. O browser não anexa o cookie, nada loga erro, e as requisições voltam não autenticadas. Decida isso antes de comprar o domínio.

Não existe rota de registro. A sua primeira conta de operador é criada para você pela plataforma. Segundos fatores opcionais, TOTP com códigos de recuperação e magic links por e-mail, ficam por cima.

3. Token de viewer

Curto, com escopo de batalha, e a única credencial que chega a um browser não confiável.

O que é. Um JWT assinado com Ed25519, audiência slotbattle-ws, com escopo de uma batalha, válido por 15 minutos.

Como trafega. Não na URL, mas no header de subprotocolo do WebSocket:

Sec-WebSocket-Protocol: slotbattle.jwt, <token>

Um token em query string cai em log de acesso, log de proxy e histórico do browser. O subprotocolo é a única forma alcançável pelo browser de enviar uma credencial no handshake de WebSocket, já que browsers não conseguem definir headers arbitrários ali.

Como conseguir um. Criar uma batalha e adicionar um assento retornam um na resposta. Se expirou, o que acontece num lobby que ficou aberto por vinte minutos, emita um novo com POST /battles/{id}/viewer-tokens, que custa viewer:mint.

Rotacionando a chave de assinatura

Um token de viewer vive 15 minutos e já está no browser de todo mundo que está assistindo. Trocar a chave de uma vez invalida todos eles ao mesmo tempo, derrubando todo espectador de toda batalha em andamento.

A rotação, portanto, nomeia uma chave nova e deixa a anterior verificando até se aposentar:

O kid no header de cada token é o que permite a um verificador segurar as duas chaves. Uma janela de aposentadoria menor que o tempo de vida de um token é recusada, porque deixaria a pé tokens ainda válidos.

Exatamente uma chave fica ativa por vez, garantido por uma restrição no banco e não por lógica de serviço que duas rotações concorrentes poderiam correr.

A rotação é uma operação de plataforma, só para super-usuário: uma chave assina para todo casino, então não é recurso de nenhum casino em particular.

Só bootstrap

A variável de ambiente da chave de assinatura é um valor de bootstrap. Vale só enquanto a tabela de chaves está vazia. Uma vez que exista uma chave, a rotação é a única forma de trocá-la, e editar a variável de ambiente não tem efeito.

4. Segredo de callback do gravador

Interno. O gravador assina o callback terminal de cada assento com HMAC sobre o corpo cru da requisição, e a assinatura é a única credencial daquela rota; não há auth de tenant nela.

Você nunca lida com esta. Ela vive entre o control plane da plataforma e os gravadores dela, e está listada aqui para que recorder numa linha de log não seja confundido com uma credencial que você deveria ter recebido.

Todo ato com credencial é atribuído

Emitir uma chave, revogar uma chave e rotacionar a chave de assinatura registram quem fez, como o endereço do ator na época, capturado em vez de referenciado.

Uma chave estrangeira para a tabela de usuários faria cascade ou viraria nula quando aquele usuário fosse apagado, apagando o registro. O ator sempre vem da sessão autenticada, nunca do corpo da requisição; nomear um no payload é um 400.

Uma chave emitida fora do console não tem usuário logado e reporta CLI / unknown em vez de vazio, porque célula vazia parece falha de renderização.

Orientações práticas

Dê a cada consumidor a própria chave. Uma chave por serviço de backend, com escopo do que aquele serviço faz. Revogar uma chave compartilhada derruba todos os consumidores de uma vez.

Nunca deixe uma chave de API chegar a um browser. É uma credencial servidor a servidor com raio de dano do tamanho do casino. O tutorial passa toda chamada por handlers no servidor justamente por isso. Veja Assista a uma batalha ao vivo.

Emita tokens de viewer por espectador, por batalha. Eles são baratos, curtos e com escopo. Reusar um entre batalhas não é possível, e reusar um entre espectadores descarta a única granularidade de revogação disponível.

Próximo