ActionCable and authentication with Devise (2/2)

An article, posted more than 8 years ago filed in authentication, ActionCable, devise, rails, ruby on rails, ruby, websockets & communication.

This is a short follow up on the previous article in which the ActionCable basics were explained. We can now add some level of authentication. Authentication is a bit harder than simply registering some before_action’s, but it is perfectly doable, especially if you’ve survived the previous tutorial.

ActionCable and authentication with Devise (2/2)

From the official Action Cable guide we can simply reuse the full connection.rb template:

module ApplicationCable
  class Connection < ActionCable::Connection::Base
    identified_by :current_user
 
    def connect
      self.current_user = find_verified_user
    end
 
    protected
      def find_verified_user
        if current_user = User.find_by(id: cookies.signed[:user_id])
          current_user
        else
          reject_unauthorized_connection
        end
      end
  end
end

But where is the :user_id-cookie coming from?

We make sure that Warden, which is used by Devise, sets it whenever it sets the user (and/or disconnects it)

Warden::Manager.after_set_user do |user,auth,opts|
  scope = opts[:scope]
  auth.cookies.signed["#{scope}_id"] = user.id
end

Warden::Manager.before_logout do |user, auth, opts|
  scope = opts[:scope]
  auth.cookies.signed["#{scope}_id"] = nil
end

Now you can do some checks when setting the checklist, in its most basic form this should be something along the lines of:

# app/channels/check_list_channel.rb
class CheckListChannel < ApplicationCable::Channel
  def subscribed
  end
  def start_listening stream_prefs
    check_list = CheckList.find stream_prefs['check_list_id']
    stream_for check_list if check_list.users.include? current_user
  end
  ...
end

Ok, that’s it! For more information, do check the Official Ruby on Rails ActionCable Guide. I will leave you with some notes when going in production.

Some notes when going in production

  • Make sure you can open enough database connections. The default connectionpool is 5 if I remember correctly, that is barely enough.
  • Running ngingx like we do? Add the following lines to your sites’ config:

    location /cable {
      passenger_app_group_name sitename_websocket;
      passenger_force_max_concurrent_requests_per_process 0;
    }
    

Enjoyed this? Follow me on Mastodon or add the RSS, euh ATOM feed to your feed reader.

Op de hoogte blijven?

Maandelijks maak ik een selectie artikelen en zorg ik voor wat extra context bij de meer technische stukken. Schrijf je hieronder in:

Mailfrequentie = 1x per maand. Je privacy wordt serieus genomen: de mailinglijst bestaat alleen op onze servers.