Search code examples
ruby-on-railsdoorkeeper

Explicitly allow Doorkeeper scope in controller


In my current application I have two doorkeeper scopes, user and admin. In the doorkeeper documentation for setting scopes in an API it shows

class Api::V1::ProductsController < Api::V1::ApiController
  before_action -> { doorkeeper_authorize! :public }, only: :index
  before_action only: [:create, :update, :destroy] do
    doorkeeper_authorize! :admin, :write
  end

  ...
end

I don't want to call doorkeeper in every controller, so in my ApplicationController I have

module API
  module V1
    class ApplicationController < ActionController::API
      before_action { doorkeeper_authorize! :user, :project }
      ...

    end
  end
end

but I don't want to give :project access to every controller. Is there a way for me to allow user in our application controller before_action { doorkeeper_authorize! :user } and on a per-controller basis allow project? ie:

module API
  module V1
    class SomeController < ApplicationController
      before_action only: [:index, :show] { doorkeeper_authorize! :project }

      ...
    end
  end
end

Solution

  • I was able to solve this by doing the following in my API::V1::ApplicationController

    module API
      module V1
        class ApplicationController < ActionController::API
          WHITELISTED_PROJECT_CONTROLLERS = %w( projects pre_task_plans
                                                job_hazard_analyses ).freeze
    
          before_action :authorize!
    
          def authorize!
            if project_scope?
              if !WHITELISTED_PROJECT_CONTROLLERS.include?(controller_name)
                return user_not_authorized
              end
            end
            doorkeeper_authorize! :user, :project
          end
    
          def project_scope?
            doorkeeper_token&.scopes&.any? { |s| s == 'project' }
          end
    
         ...
    
        end
      end
    end