grape-jsonapi-resources icon indicating copy to clipboard operation
grape-jsonapi-resources copied to clipboard

Authentication issue with formatter Grape::Formatter::JSONAPIResources

Open jedrekdomanski opened this issue 7 years ago • 2 comments

I have a core API class that defines my API and mounts my endpoints.

module API
  class Core < Grape::API
    prefix :api
    include ErrorHandlers
    helpers AuthHelpers
    default_format :json
    content_type :json, 'application/json'
    formatter :json, Grape::Formatter::JSONAPIResources

    mount ::Trips::Base
    mount ::Statistics::Base
    mount ::Users::Base
  end
end

AuthHelpers module provides me with global helper method for authentication in endpoints where I need to authenticate users.

module AuthHelpers
  extend Grape::API::Helpers

  def authenticate_user!
    begin
      payload = JsonWebToken.decode(token)
      @current_user = User.find_by(id: payload['user_id'])
    rescue
      error!(I18n.t('authorization.unauthenticated'), 401)
    end
  end

  def current_user
    @current_user ||= authenticate_user!
  end

  def token
    request.headers['Authorization'].split(' ').last
  end
end

I use it in all endpoint except UsersAPI because, obviously, I don't want to authenticate a user wher he/she is registering or loging in. Here's how I use it an example base endpoint class:

app/api/statistics/base.rb

module Statistics
  class Base < API::Core
    resources :stats do
      before { authenticate_user! }
      mount StatisticsAPI
    end
  end
end

So in before block I call authenticate_user!.

Now, I have installed gemgrape-jsonapi-resources and added formatter :json, Grape::Formatter::JSONAPIResources to my core API class as I want to return a nice pretty JSON in the response globally and since then I started to have issues with UsersAPI endpoint where, suddenly, all requests are failing due to Unauthorized 401 error. Here's my UsersAPI base class.

module Users
  class Base < API::Core
    resources :users do
      mount UsersAPI
    end
  end
end

Here I don't use authenticate_user! for the reasons I explained before and I am struggling to understand how, after adding formatter :json, Grape::Formatter::JSONAPIResources to the base API class, it is trying to authenticate the user. What am I doing wrong? Why am I getting Unauthorized 401 in endpoint where I do not even call authenticate_user! method?

I have tried switching to grape-actvive_model_serializers and I don't have this issue.

jedrekdomanski avatar Dec 12 '18 10:12 jedrekdomanski

@cdunn I have tried a trick. I renamed the method authenticate_user! to authenticate! and suddenly I got an error caught error of type NoMethodError in after callback inside Grape::Middleware::Formatter : undefined method authenticate_user!' for #<#<Class:0x000055de6bf3e798>:0x000055de6a8d08a8> Did you mean? authenticate! Why does the formatter requires a method authenticate_user!? I even tried changing resources to namespace but no luck. Can you help me?

module Users
  class Base < API::Core
    namespace :users do
      mount UsersAPI
    end
  end
end

jedrekdomanski avatar Dec 13 '18 00:12 jedrekdomanski

UPDATE I changed the formatter to Grape::Formatter::Json and it works so there is an issue with Grape::Formatter::JSONAPIResources

jedrekdomanski avatar Dec 13 '18 09:12 jedrekdomanski