Existe-t-il un moyen de créer une route qui contourne l’authentification ?
Cela est utilisé pour l’intégration avec des services tiers.
La nécessité est de fournir au service une URL (les en-têtes ou les charges utiles de tout type ne sont pas pris en charge).
Auparavant, cela était possible en ajoutant « ?api_key=…&api_username= », mais cette option n’existe plus.
Vous aurez besoin d’un plugin personnalisé qui crée une route capable d’accepter un contenu et d’agir en conséquence. Sachez que, puisque vous ne pouvez pas authentifier l’utilisateur, vous devrez peut-être mettre en place un moyen d’authentifier le contenu.
Ma règle est de ne pas autoriser les comptes anonymes. Je ne peux donc pas accéder aux routes du plugin. Ce dont j’aurais besoin, c’est d’un moyen de créer une route adaptée à ce type de scénario.
Par exemple,
# Rails 3.2 par défaut laisse passer la requête avec une session vide
# Nous sommes ici plus rigoristes en annulant la session / current_user
# puis en levant une exception CSRF
def handle_unverified_request
# NOTE : La clé API est secrète ; son utilisation rend inutile le jeton CSRF
unless is_api? || is_user_api?
super
clear_current_user
render plain: "[\"BAD CSRF\"]", status: 403
end
end
Une façon de notifier, durant ce flux ou tout le flux d’authentification, qu’un contrôleur et une action reçus via des paramètres (définis automatiquement lors de l’appel d’une route) peuvent contourner toutes les vérifications et exécuter la route.
Je ne maîtrise pas parfaitement le fonctionnement global, mais puisqu’il existe une option d’accès anonyme, je suis certain qu’une solution est possible.
Cela permettrait aux utilisateurs de chiffrer la charge utile si nécessaire, mais pour des mises à jour génériques du système, cela serait très utile.
Via un plugin, vous pouvez ajouter votre nouvelle route à DiscoursePluginRegistry.api_parameter_routes afin de continuer à transmettre les identifiants API via des paramètres de requête :
# Par défaut, nous autorisons uniquement les en-têtes pour l'envoi des identifiants API
# Cependant, dans certains scénarios, il est essentiel de les envoyer via des paramètres d'URL
# nous devons donc ajouter quelques exceptions
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 'Autorisé'
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
J’ai fait cela simplement pour minimiser les différences dans git à l’avenir.
Aussi, mon contrôleur :
# 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
Je pense que l’ajout de requires_login à votre contrôleur fera l’affaire. Jetez un œil à certains des autres contrôleurs dans app/controllers pour des exemples.
Et vous avez transmis vos identifiants API via des paramètres de requête ? Si c’est le cas, cela signifie que votre route n’a probablement pas été ajoutée correctement à la liste de contournement pour autoriser les identifiants API dans les paramètres de requête. Vous devrez peut-être déboguer la logique de contournement et vérifier si votre route a bien été ajoutée.