Existe alguma maneira de criar uma rota que ignore a autenticação?
Isso é usado para integrar com serviços de terceiros.
O requisito é fornecer ao serviço uma URL (cabeçalhos ou payloads de qualquer tipo não são suportados).
Antes, isso era possível adicionando “?api_key=…&api_username=” ao final, mas essa opção foi removida.
Você precisaria de um plugin personalizado que crie uma rota capaz de aceitar um payload e agir sobre ele. Esteja ciente de que, como não é possível autenticar o usuário, você pode precisar de uma forma de autenticar o payload.
Minha regra é não permitir contas anônimas. Portanto, não consigo acessar as rotas do plugin. O que eu precisaria é de uma maneira de criar uma rota para esse tipo de cenário.
Por exemplo,
# O Rails 3.2 padrão permite que a requisição passe com uma sessão em branco
# Aqui estamos sendo mais rigorosos e anulando a sessão / current_user
# e depois lançando uma exceção de CSRF
def handle_unverified_request
# NOTA: A chave de API é secreta; tê-la invalida a necessidade de um token CSRF
unless is_api? || is_user_api?
super
clear_current_user
render plain: "[\"BAD CSRF\"]", status: 403
end
end
Uma maneira de notificar, durante esse fluxo ou em todo o fluxo de autenticação, que um controlador e uma ação recebidos via parâmetros (definidos automaticamente ao chamar uma rota) podem contornar tudo e executar a rota.
Não tenho plena consciência de como tudo funciona, mas como existe uma opção de acesso anônimo, tenho certeza de que há uma maneira de fazer isso.
Isso permitiria que as pessoas criptografassem a carga útil, se necessário, mas para atualizações genéricas de informações no sistema, seria útil.
Através de um plugin, você pode adicionar sua nova rota ao DiscoursePluginRegistry.api_parameter_routes para que possa continuar passando credenciais de API via parâmetros de consulta:
# Por padrão, permitimos apenas cabeçalhos para envio de credenciais de API
# No entanto, em alguns cenários, é essencial enviá-las por parâmetros de URL
# então precisamos adicionar algumas exceções
def api_parameter_allowed?
request_method = @env["REQUEST_METHOD"]&.downcase&.to_sym
request_format = @env['action_dispatch.request.formats']&.first&.symbol
path_params = @env['action_dispatch.request.path_parameters']
request_route = "#{path_params[:controller]}##{path_params[:action]}" if path_params
if 'm_exposed#endpoint' == request_route && request_method == 'get'
puts 'Allowed'
return true
end
PARAMETER_API_PATTERNS.any? do |p|
(p[:method] == "*" || Array(p[:method]).include?(request_method)) &&
(p[:format] == "*" || Array(p[:format]).include?(request_format)) &&
(p[:route] == "*" || Array(p[:route]).include?(request_route))
end
end
Fiz isso apenas para minimizar os diffs do git no futuro.
Além disso, meu controlador:
# frozen_string_literal: true
class MExposedController < ::ApplicationController
skip_before_action :redirect_to_login_if_required, raise: false
def endpoint
render json: { state: "hello world" }
end
end
Acredito que adicionar requires_login ao seu controlador resolverá o problema. Dê uma olhada em alguns dos outros controladores em app/controllers para exemplos.
E você passou suas credenciais da API via parâmetros de consulta? Se sim, isso significa que sua rota provavelmente não foi adicionada corretamente à lista de exceções para permitir credenciais da API nos parâmetros de consulta. Talvez seja necessário depurar a lógica da lista de exceções e verificar se sua rota foi adicionada.