I'm adding some authentication into my Rails API only app like so in my application_controller.rb:
def is_admin
authenticate_or_request_with_http_token do |token, options|
if User.find_by(:auth_token => token)
value = true
else
value = false
end
end
end
And in my controller:
admin = is_admin
if admin
@voices = Voice.all.map do |voice|
voice.format
end
else
@voices = 'Something else'
end
When I'm logged in, everything works fine as expected, however when I'm not logged in, I get the following error: Render and/or redirect were called multiple times in this action. Please note that you may only call render OR redirect, and at most once per action. Also note that neither redirect nor render terminate execution of the action, so if you want to exit an action after redirecting, you need to do something like "redirect_to(...) and return".
While not logged in, I was expecting to get the 'Something else' response, which I'd then go ahead and deal with it accordingly.
Any ideas why is this happening?
authenticate_or_request_with_http_token
is meant to be used in a before_action
filter which runs before the action. Or with an explicit return.
If you simply want to check if a user exists you would use authenticate_with_http_token
which does not send a response.
# app/helpers/authorization_helper.rb
module AuthorizationHelper
# returns true/false
# sets @current_user if the request is authenticated
def authenticate!
return true if @current_user # avoid re-querying the DB
authenticate_with_http_token do |token, options|
@current_user = User.find_by(:auth_token => token)
end
end
def is_admin?
authenticate!
end
end
# app/controllers/api_controller.rb
# or whatever controller you use as a base
class ApplicationController < ActionController::API
include AuthorizationHelper
end
# in your controller
def index
if is_admin?
@voices = Voice.all.map do |voice|
voice.format
else
@voices = 'Something else'
end
end
You can also do this in addition or rather an option to max's answer.
# app/controllers/application_controller.rb
class ApplicationController
def authorization!
authenticate_with_http_token do |token, options|
@current_user = User.find_by(:auth_token => token)
end
unless @user.present?
# You could return anything you want if the response if it's unauthorized. in this
# case I'll just return a json object
return render json: {
status: 300,
message: "Unauthorized access in the API"
}, status: 401
end
end
end
# in your controller just add a before_action method
before_action :authorization
def index
@voices = Voice.all.map do |voice|
voice.format
end
In this case you won't need to add an if statement in every request that requires an authentication.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With