How to use Action Cable with Devise

The websocket server is running in a separate process from the Rails application so to authenticate the user we need cookies.

  1. Set up cookies in Devise
    # app/config/initializers/warden_hooks.rb
    Warden::Manager.after_set_user do |user,auth,opts|
      scope = opts[:scope]
      auth.cookies.signed["#{scope}.id"] = user.id
      auth.cookies.signed["#{scope}.expires_at"] = 30.minutes.from_now
    end
    
    # app/config/initializers/warden_hooks.rb
    ...
    
    Warden::Manager.before_logout do |user, auth, opts|
      scope = opts[:scope]
      auth.cookies.signed["#{scope}.id"] = nil
      auth.cookies.signed["#{scope}.expires_at"] = nil
    end
    ...
  2. Configure AC connection
    # app/channels/application_cable/connection.rb
    module ApplicationCable
      class Connection < ActionCable::Connection::Base
        identified_by :current_user
    
        def connect
          self.current_user = find_verified_user
          logger.add_tags 'ActionCable', current_user.name
        end
    
    protected
      def find_verified_user
        verified_user = User.find_by(id: cookies.signed['user.id'])
        if verified_user && cookies.signed['user.expires_at'] > Time.now
          verified_user
        else
          reject_unauthorized_connection
        end
      end
      end
    end