0

I have this following controller for my application:

class Api::BaseApiController< ApplicationController
  before_action :parse_request, :authenticate_member_from_token!

  def index
    render nothing: true, status: 200
  end

  protected
    def authenticate_member_from_token!
      if !request.headers[:escambo_token]
        @member = Member.find_by_valid_token(:activate, request.headers['escambo_token'])
        if !@member
          render nothing: true, status: :unauthorized
        end
      end
    end

Then, I have another controller that inherits from that Controller:

class Api::CategoryController < Api::BaseApiController
  before_action :find_category, except: [:index]

  def index
    @category = Category.all
    puts(@category)
    render json: @category
  end

But the controller is allowing requests without the token.

EDIT 1: for some reason the index action started to working normally. But still not doing the validation for the token.

EDIT 2: fixing method from private to protected

olegario
  • 711
  • 2
  • 16
  • 35
  • @SergioTulentsev already fixed! Thanks. – olegario Apr 04 '18 at 17:11
  • are you sure it's going through the correct methods? you can put breapoints in there to ensure they're being called – max pleaner Apr 04 '18 at 17:11
  • @maxpleaner I edited the question again. – olegario Apr 04 '18 at 17:14
  • @olegario: so you're saying it doesn't enter `authenticate_member_from_token!`? How do you know? Does it enter `parse_request`? – Sergio Tulentsev Apr 04 '18 at 17:15
  • 1
    If `authenticate_member_from_token!` isn't being called, then there's something crucial missing from your code above. I see no reason why it wouldn't be called. – Tom Lord Apr 04 '18 at 17:16
  • @TomLord, it is being called, but I'm sending a fake token (not valid), and the method accepts. – olegario Apr 04 '18 at 17:21
  • @olegario Does `parse_request` before action work in `Api::CategoryController#index`? – Martin Apr 04 '18 at 17:23
  • @MartinZinovsky, yes, it is. – olegario Apr 04 '18 at 17:25
  • @olegario OK, but that's exactly what your code was saying to do... I'll write an answer if what I *think* you want it to do below... – Tom Lord Apr 04 '18 at 17:25
  • @olegario And `authenticate_member_from_token!` works if you explicitly add it to `Api::CategoryController`? – Martin Apr 04 '18 at 17:27
  • @MartinZinovsky, it is wokring normally by now, but now I sending a header with a fake token and the method is respoondig with 400 status code: `request.headers['escambo_token'] = "#{@member.tokens.last.token}"` – olegario Apr 04 '18 at 17:33
  • @olegario: `:escambo_token != 'escambo_token'`, generally. Not sure how `headers` handles this. – Sergio Tulentsev Apr 04 '18 at 17:36
  • @olegario try approach suggested in [this SO question](https://stackoverflow.com/questions/19972313/accessing-custom-header-variables-in-ruby-on-rails). `request.headers['HTTP_ESCAMBO_TOKEN']` or `request.headers['escambo-token']` – Martin Apr 04 '18 at 17:45

1 Answers1

1

Your code needs to render :unauthorized if the token is missing, OR invalid. In other words, you need the code to be along the lines of:

def authenticate_member_from_token!
  unless Member.find_by_valid_token(:activate, request.headers['escambo_token'])
    render nothing: true, status: :unauthorized
  end
end

However, with this code you may find yourself double-rendering in the controller. A cleaner approach could be to instead raise an exception, then rescue from it and render appropriately - e.g.

EscamboTokenInvalid = Class.new(StandardError)
rescue_from EscamboTokenInvalid, with: :escambo_unauthorized

def authenticate_member_from_token!
  unless Member.find_by_valid_token(:activate, request.headers['escambo_token'])
    raise EscamboTokenInvalid
  end
end

def escambo_unauthorized
  render nothing: true, status: :unauthorized
end
Tom Lord
  • 27,404
  • 4
  • 50
  • 77