Olá! Desenvolvemos um plugin SSO personalizado para agrupar os dados de login da nossa empresa em um pacote que o Discourse pode usar para gerenciar logins e criar contas. Com a versão v2.7.0beta4, começamos a receber erros indicando que não estávamos fornecendo um novo parâmetro: secure_session. Não consegui encontrar nenhuma informação sobre qual deve ser o formato desse parâmetro ou o que ele deve conter. Existe alguma documentação adicional sobre essa atualização?
Você sabe qual é a mensagem de erro exata que está aparecendo? Meu entendimento é que o Discourse agora vincula o parâmetro nonce do SSO à sessão do usuário. Isso significa que, se um aplicativo estiver gerando o nonce fazendo uma solicitação em segundo plano para /session/sso, o nonce não será válido. Possivelmente, esse é o problema que você está enfrentando.
O arquivo service_gateway_current_user.rb faz parte do nosso plugin para construir o payload a ser enviado para DiscourseSingleSignOn com base nos cabeçalhos “Service Gateway” (sendo “Service Gateway” a estrutura interna da nossa empresa para determinar se você está logado em nosso sistema).
Para explicar essa parte do stack trace:
Nossa função current_user usa nossos cabeçalhos para buscar um SingleSignOnRecord onde o external_id corresponda ao ID do Usuário nos cabeçalhos. Se não for esse o caso, entramos na seção create_sso_record.
create_sso_record cria um hash – { external_id: sg_headers[:user_id], email: sg_headers[:email] } – e o envia para nossa função upsert_sso_record.
upsert_sso_record recebe esse hash (payload no contexto abaixo) e tenta criar um objeto DiscourseSingleSignOn:
def upsert_sso_record(payload)
encoded_query = Base64.encode64(payload.to_query)
sig = OpenSSL::HMAC.hexdigest('sha256', ENV['SSO_SECRET'], encoded_query)
sso = DiscourseSingleSignOn.parse({ sso: encoded_query, sig: sig }.to_query)
if SiteSetting.verbose_sso_logging
Rails.logger.warn("Verbose SSO log: Started SSO process\n\n#{sso.diagnostics}")
Rails.logger.warn("SSO Payload:\n\n#{payload}")
end
begin
user = sso.lookup_or_create_user(@request.ip)
rescue ActiveRecord::RecordInvalid => ex
Rails.logger.error "Unable to find/create sso user #{ex}"
end
user
end
A chamada parse na terceira linha dessa função é onde parece estar ocorrendo o problema. Assim que tenta initialize o objeto, o valor secure_session que ela espera não está presente.
Estou me perguntando se definir a nova configuração do site discourse_connect_csrf_protection como false resolverá o problema para você. Essa configuração do site está oculta, portanto precisa ser definida no console do Rails. Você pode encontrar detalhes sobre isso nas respostas a este tópico: DiscourseConnect flow no longer functions.
Infelizmente, não acho que essa nova configuração ajudará sozinha — os detalhes internos do código ainda exigirão a passagem de um objeto secure_session, mesmo que ele não seja utilizado.
Em geral, recomendamos o uso dos hooks oficiais para plugins de autenticação, em vez de substituir a implementação do DiscourseConnect do núcleo.
É difícil ter certeza sem ver o plugin inteiro, mas você pode tentar passar um valor nil para secure_session. Fazer isso, junto com ativar a nova configuração do site, pode ajudar a deixar as coisas um pouco mais próximas de funcionar.
Depois de investigar um pouco mais o código da v2.7.0.beta4, vejo que o ApplicationController tem uma definição de secure_session. Alterar nosso código do plugin para o seguinte parece funcionar em nosso ambiente de Staging:
sso = DiscourseSingleSignOn.parse({ sso: encoded_query, sig: sig }.to_query, secure_session: secure_session)