Authentication
Rack middlewares
Most authentication strategies rely on request cookies or session (directly or indirectly).
Cookies and Rails session object are supported in AnyCable out-of-the-box. If you rely on some
other Rack request properties (e.g., request.env["something"]
) for your authentication, you must configure
AnyCable Rack middleware stack to make them work (because requests in AnyCable are not passed through the default Rails stack).
You can do this through the AnyCable::Rails::Rack.middleware
object in your configuration. See Devise/Warden example below.
Devise/Warden
Devise relies on warden
Rack middleware to authenticate users.
In order to make it work with AnyCable, you must add this middleware to AnyCable's middleware stack like this:
AnyCable::Rails::Rack.middleware.use Warden::Manager do |config|
Devise.warden_config = config
end
You can put this code, for example, into an initializer (config/initializers/anycable.rb
) or any other configuration file.
Then, you can access the current user via env["warden"].user(scope)
in your connection class (where scope
is Warden scope, usually, :user
).
Manually building Warden session
You can also try building a Warden context yourself (e.g., if you use a custom session storage mechanism or other modifications). Here is a real-life example:
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
redis = Redis.new(url: ENV["REDIS_URL"])
# this key should have the same `key_prefix` as setup in redis_session_store config (see above)
rkey = "xylophone:session:#{cookies[app_cookies_key]}"
session_data = redis.get(rkey)
if session_data.present?
env["rack.session"] = JSON.parse(session_data, quirks_mode: true)
Warden::SessionSerializer.new(env).fetch(:user)
else
reject_unauthorized_connection
end
end
def app_cookies_key
Rails.application.config.session_options[:key] ||
raise("No session cookies key in config")
end
end
end