Assinado não significa autorizado
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_verifierdesta aplicação usa uma chave única para a aplicação inteira, derivada dosecret_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: semcurrent_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.
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.