Search code examples
ruby-on-railsrubydevise

Devise infinite loop Filter chain halted as :require_no_authentication


I have a weird issue using Ruby on Rails 6 and Devise. After signing in or signing out, the app is on an infinite loop instead of redirecting to the root_path. The root_path does not require any authentication so it shouldn't redirect.

Error logs:

Started POST "/utilisateurs/connexion" for ::1 at 2023-12-27 10:22:42 +0100 Processing by Users::SessionsController#create as HTML Parameters: {"authenticity_token"=>"[FILTERED]", "user"=>{"email"=>"email@email.fr", "password"=>"[FILTERED]", "remember_me"=>"0"}, "commit"=>"Je me connecte"} User Load (0.2ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 ORDER BY "users"."id" ASC LIMIT $2 [["id", 55786], ["LIMIT", 1]] after_sign_in_path_for Redirected to http://localhost:3000/ Filter chain halted as :require_no_authentication rendered or redirected

Completed 302 Found in 3ms (ActiveRecord: 0.2ms | Allocations: 1911)

Started GET "/utilisateurs/" for ::1 at 2023-12-27 10:22:42 +0100

Routes:

devise_for :users, 
path: "utilisateurs",
controllers: { 
    sessions: 'users/sessions', 
    registrations: 'users/registrations', 
    passwords: 'users/passwords',
    confirmations: 'users/confirmations'
},
:path_names => { :sign_in => 'connexion', :sign_up => 'inscription', :sign_out => 'deconnexion', password: 'retrouver_mot_de_passe', edit: 'finaliser-inscription' }

User model:

class User < ApplicationRecord
    attr_accessor :skip_password_validation
    before_validation :check_pseudo, only: [:create, :update]
    validates :pseudo, presence: true
    validates :email, 
                        format: { with: URI::MailTo::EMAIL_REGEXP },
                        presence: true,
                        uniqueness: true

    has_secure_token

  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :validatable, :confirmable, :trackable

    has_many :comments, dependent: :nullify
    has_one :author, dependent: :nullify
    has_one :blitz_score, :dependent => :destroy
    has_one :blitz_conjugaison_score, :dependent => :destroy
    has_many :quiz_scores, :dependent => :destroy
    has_many :dictee_scores, :dependent => :destroy
    has_many :crossword_scores, :dependent => :destroy
    has_many :track_subscribers, :dependent => :destroy

    def authenticatable_salt
    return super unless session_token

    "#{super}#{session_token}"
  end

  def invalidate_all_sessions!
    update_attribute(:session_token, SecureRandom.hex)
  end

    protected

    def check_pseudo
        unless self.pseudo.present?
            self.pseudo = self.email.split("@")[0] if self.email.present?
        end
    end

    def password_required?
    return false if skip_password_validation
    super
  end
end

Note that I don't require the password to create an account. Visitors give their email first, then they can fill in their pseudo and password after they confirm their account.

Sessions controller:

class Users::SessionsController < Devise::SessionsController
    layout 'blank'

  protected
    
    def after_sign_in_path_for(resource_or_scope)
        root_path
    end 
    
    def after_sign_out_path_for(resource_or_scope)
        root_path
    end
end

Devise initializer:

Devise.setup do |config|

  require 'devise/orm/active_record'

  config.case_insensitive_keys = [:email]

  config.strip_whitespace_keys = [:email]

  config.skip_session_storage = [:http_auth]

  config.stretches = Rails.env.test? ? 1 : 12

  config.reconfirmable = false

  config.expire_all_remember_me_on_sign_out = true

  config.password_length = 6..128

  config.email_regexp = /\A[^@\s]+@[^@\s]+\z/

  config.reset_password_within = 24.hours

  config.navigational_formats = ['*/*', :html]

  config.sign_out_via = :delete
end

Development config:

Rails.application.configure do
  config.cache_classes = false

  config.eager_load = false

  config.consider_all_requests_local = true

  if Rails.root.join('tmp', 'caching-dev.txt').exist?
    config.action_controller.perform_caching = false
    config.action_controller.enable_fragment_cache_logging = true

    config.cache_store = :memory_store
    config.public_file_server.headers = {
      'Cache-Control' => "public, max-age=#{2.days.to_i}"
    }
  else
    config.action_controller.perform_caching = false

    config.cache_store = :null_store
  end

  config.active_storage.service = :local

  config.action_mailer.raise_delivery_errors = false

  config.action_mailer.perform_caching = false

    config.action_mailer.default_url_options = { host: 'localhost', port: 3000 }
    config.action_mailer.delivery_method = :mailjet

  config.active_support.deprecation = :log

  config.active_record.migration_error = :page_load

  config.active_record.verbose_query_logs = true

  config.assets.debug = true

  config.assets.quiet = true

  config.file_watcher = ActiveSupport::EventedFileUpdateChecker
    
    config.active_job.queue_adapter = :sidekiq

    config.i18n.default_locale = :fr

    config.after_initialize do
        Bullet.enable = true
        Bullet.bullet_logger = true
        Bullet.unused_eager_loading_enable = false
        Bullet.raise = false
    end
end

I tried the following without success:

  • Removed the Devise custom controllers
  • Clear cookies + cache in development and restart the server
  • Removed the skip_password_validation in User model
  • Started the rails server on a different port

Not sure if this could be the origin of the issue, but I am working on several other rails apps. I fire them separately using rails s and the server is on localhost:3000. Maybe this could mess up with the sessions or else?

Thank you for your help.


Solution

  • In the end, the issue was related to the service-worker.js of the PWA implementation.

    Somehow, Devise was redirecting to the service-worker.js, resulting in an infinite redirect loop.