Is there any way I can create a route that bypasses authentication.
This is used to integrate with 3rd party services.
The requirement is providing the service an URL (headers or payloads of any type are not supported).
Previously this was possible by appending “?api_key=…&api_username=” but that is now gone.
You would need a custom plugin that creates a route that can accept a payload and act on it. Do be aware since you’re not able to authenticate the user, you may need a way to authenticate the payload.
My rule is no anonymous accounts. So i cannot access the plugin routes. What I would need is a way for a route to be created for this type of scenario.
For example,
# Default Rails 3.2 lets the request through with a blank session
# we are being more pedantic here and nulling session / current_user
# and then raising a CSRF exception
def handle_unverified_request
# NOTE: API key is secret, having it invalidates the need for a CSRF token
unless is_api? || is_user_api?
super
clear_current_user
render plain: "[\"BAD CSRF\"]", status: 403
end
end
A way to notify during this flow or the whole flow of authentication that a controller and an action received via params (set automatically when you call a route) can bypass everything and execute the route.
I’m not fully aware of how everything works, but since there is an anonymous access option, I’m sure there is a way to do it.
This would allow for people to encrypt the payload if needed, but for generic information updating the system, it would be useful.
Via a plugin you can add your new route to the DiscoursePluginRegistry.api_parameter_routes so that you can continue to pass in api credentials via query parameters:
# By default we only allow headers for sending API credentials
# However, in some scenarios it is essential to send them via url parameters
# so we need to add some 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 '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
I did this just to minimize the git diffs for future.
Also, my controller:
# 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
And you passed in your api credentials via query params? If so, that means your route probably didn’t get added correctly to the bypass for allowing api creds in query params. You may need to debug the bypass logic and see if your route was ever added.