varvet / pundit

Minimal authorization through OO design and pure Ruby classes
MIT License
8.26k stars 627 forks source link

Use with two_factor_authentication gem #642

Closed davidkrider closed 2 years ago

davidkrider commented 4 years ago

I've "taken the training wheels off" my Pundit setup by adding after_action :verify_authorized to my ApplicationPolicy. I'm using Devise with the two_factor_authentication plugin, and ActiveAdmin. So Devise authentications have now been "absorbed" into the /admin namespace, and the 2-factor controller lives somewhere in the mix. This has been working fine until I forced explicit definitions of policy. Now, when the app tries to serve the page to allow a user to enter the OTP, I get the following error:

Started GET "/admin/two_factor_authentication" for ::1 at 2020-02-24 14:27:13 -0500
   (0.8ms)  SELECT "schema_migrations"."version" FROM "schema_migrations" ORDER BY "schema_migrations"."version" ASC
  ↳ /Users/davidkrider/.rvm/gems/ruby-2.5.5/gems/activerecord-5.2.3/lib/active_record/log_subscriber.rb:98
Processing by Devise::TwoFactorAuthenticationController#show as HTML
  User Load (0.5ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = $1 ORDER BY "users"."id" ASC LIMIT $2  [["id", 2], ["LIMIT", 1]]
  ↳ /Users/davidkrider/.rvm/gems/ruby-2.5.5/gems/activerecord-5.2.3/lib/active_record/log_subscriber.rb:98
  Rendering devise/two_factor_authentication/show.html.haml within layouts/application
  Rendered devise/two_factor_authentication/show.html.haml within layouts/application (6.4ms)
  Role Load (0.2ms)  SELECT  "roles".* FROM "roles" WHERE "roles"."id" = $1 LIMIT $2  [["id", 3], ["LIMIT", 1]]
  ↳ app/models/user.rb:47
Completed 500 Internal Server Error in 767ms (Views: 728.7ms | ActiveRecord: 6.6ms)

Pundit::AuthorizationNotPerformedError - Devise::TwoFactorAuthenticationController:

Started POST "/__better_errors/c9b9b9703df4dabc/variables" for ::1 at 2020-02-24 14:27:14 -0500

There are hints in there about where my policy should go and what it should be named and what model it should apply to, but I've tried a dozen configurations, and I can't seem to sort it out. There are no obvious variables to inspect at the point of the failure to lead me to understand what file path, policy name, and class Pundit is looking for. How should I cover this path with a policy?

Burgestrand commented 2 years ago

Just guessing; assuming Devise::TwoFactorAuthenticationController inherits from ApplicationController, and you happen to have the after_action-filter from the Pundit README, then you will get this error because that controller isn't calling authorize anywhere.

One way around this is to skip authorization for all devise controllers, something like this:

class ApplicationController < ActionController::Base
  include Pundit
  after_action :verify_authorized, unless: :devise_controller?
end