Assinado não significa autorizado

Prévia grátis 3 min de leitura

Um nome de stream assinado (dois cursos atrás) não pode ser adulterado. Um cliente não consegue inventar um novo; só pode apresentar um que o servidor gerou. Esse fato responde a uma pergunta e deixa outra em aberto. Provar que um nome é legítimo não diz nada sobre se este visitante, agora, pode ouvi-lo.

Uma chave para a aplicação inteira

Turbo.signed_stream_verifier, da turbo-rails-2.0.23 instalada nesta aplicação:

def signed_stream_verifier
  @signed_stream_verifier ||= ActiveSupport::MessageVerifier.new(signed_stream_verifier_key, digest: "SHA256", serializer: JSON)
end

E de onde vem a chave, turbo/engine.rb, sem edição:

initializer "turbo.signed_stream_verifier_key" do
  config.after_initialize do
    Turbo.signed_stream_verifier_key = config.turbo.signed_stream_verifier_key ||
      Rails.application.key_generator.generate_key("turbo/signed_stream_verifier_key")
  end
end

Um verificador e uma chave, derivada uma vez do secret_key_base desta aplicação pelo Rails.application.key_generator, divididos por todo nome de stream que a aplicação assina. O "catalog_roadmap" do roadmap público e um stream privado hipotético seriam verificados pela mesma chave. A chave prova que este servidor gerou o nome. Ela não faz ideia de quem está pedindo agora, porque uma chave única para a aplicação inteira nunca foi pensada para guardar isso.

O que "verificado" confere, mais uma vez

O Turbo::StreamsChannel#subscribed, lido no curso "Turbo Streams: WebSockets", é toda a checagem de autorização que vem com o Turbo:

def subscribed
  if stream_name = verified_stream_name_from_params
    stream_from stream_name
  else
    reject
  end
end

"Verificado" aqui quer dizer uma coisa: a assinatura bate com o conteúdo, sob a chave desta aplicação. Não quer dizer "a conexão atual do Action Cable pertence ao usuário para quem o stream foi feito". Nada nesse método lê current_user, confere uma sessão ou compara um id. Qualquer um com um nome de stream assinado de forma válida, não importa como o obteve, se inscreve com sucesso. O Turbo nunca foi pensado para responder "esta pessoa pode ver isto", só "este nome é de verdade".

Por que o único stream desta aplicação escapa

O "catalog_roadmap", exemplo dos dois cursos anteriores, está bem porque não há nada a proteger. O roadmap é dado público de cursos, visível a visitantes logados e anônimos, de propósito. A assinatura ainda importa ali (um nome adulterado poderia se inscrever em algo indevido), mas autorização nunca foi uma questão para um stream que todo mundo pode ver. Quando um stream é feito para uma pessoa e mais ninguém, essa lacuna, assinado mas não autorizado, vira o problema inteiro que este curso quer fechar.

Pontos-chave

  • O Turbo.signed_stream_verifier desta aplicação usa uma chave única para a aplicação inteira, derivada do secret_key_base. Todo nome de stream que a aplicação assina, público ou privado, divide essa chave.
  • O Turbo::StreamsChannel#subscribed, lido de novo, confere a assinatura e mais nada: sem current_user, sem checagem de sessão, sem lógica por usuário.
  • "Verificado" prova que um nome não foi adulterado. Não prova nada sobre se a conexão que o apresenta pertence à pessoa para quem o stream foi feito.
  • O único stream desta aplicação, "catalog_roadmap", está seguro sem autorização extra só porque é público. A lacuna desta aula passa a importar quando um stream não é para todo mundo.
Aula 1 de 7 · grátis

Continue com a aula 2

Assinado não significa secreto

A assinatura garante integridade, sem confidencialidade: um Base64.decode64 sem chave recupera o conteúdo do nome.

Com uma conta grátis você também tem os quizzes, seu progresso e suas anotações, e a discussão.

Digite para buscar...