Kansha
Kansha

Reputation: 570

Getting AuthLogic to work with ActionCable

I'm working on a new Rails 5 (RC1) app. I used AuthLogic for user authentication, and it works great as always, until I got to ActionCable.

#app/channels/application_cable/connection.rb
module ApplicationCable
  class Connection < ActionCable::Connection::Base
    identified_by :current_user

    def connect
      self.current_user = UserSession.find
    end
  end
end

I get the error: You must activate the Authlogic::Session::Base.controller with a controller object before creating objects

I tried:

Authlogic::Session::Base.controller = Authlogic::ControllerAdapters::RailsAdapter.new(self)

But that does not work because the Connection class is not a Controller.

I look at the AuthLogic code, but I can't figure out how to bypass its dependence on a controller object. I just need to load the user's session. Any thoughts?

Upvotes: 0

Views: 1043

Answers (2)

Jonathon Horsman
Jonathon Horsman

Reputation: 2333

Assuming you're using Authlogic default, the persistence token is stored in the cookie under the key 'user_credentials'.

So you can lookup your user like this:

# app/channels/application_cable/connection.rb
module ApplicationCable
  class Connection < ActionCable::Connection::Base

    def connect
      verify_user
    end

    private
    def verify_user
      reject_unauthorized_connection unless verified_user?
    end

    def verified_user?
      cookie_key && User.find_by_persistence_token(token)
    end

    def token
      cookie && cookie.include?('::') && cookie.split("::")[0]
    end

    def cookie
     cookies['user_credentials']
    end

  end
end

Upvotes: 1

Kansha
Kansha

Reputation: 570

I figured it out on my own. I feel it is sort of hacky, basically in my ApplicationController I set a secure cookie with the AuthLogic persistence_token, then I can read this token and manually load the user in ActionCable.

class ApplicationController < ActionController::Base
  before_action :set_verify_cookie

  def set_verify_cookie
    #action cable needs a way outside of controller logic to lookup a user
   return unless current_user
    cookies.signed[:vvc] = current_user.persistence_token
  end
end

#app/channels/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', self.current_user.username unless self.current_user.nil?
    end

    protected

    def find_verified_user_or_guest
      User.find_by(:persistence_token => cookies.signed[:vvc])
    end
end

One potential gotch, the cookie needs to be cleared on logout or ActionCable will still find the user on subsequent page loads.

#app/controllers/user_sessions_controller.rb
class UserSessionsController < ApplicationController

  def destroy
    cookies.signed[:vvc] = nil
    current_user_session.destroy
    flash[:success] = "Logout successful!"
    redirect_to root_url
  end
end

Upvotes: 5

Related Questions