Why am I not able to retrieve current_user
inside my channel or how should I retrieve current_user
?
What do I use?
Trying to get current_user
inside my ActionCable channel as described in rubydoc.info
The code looks like
class MessageChannel < ApplicationCable::Channel
identified_by :current_user
def subscribed
stream_from 'message_' + find_current_user_privileges
end
def unsubscribed
# Any cleanup needed when channel is unsubscribed
end
protected
def find_current_user_privileges
if current_user.has_role? :admin
'admin'
else
'user_' + current_user.id
end
end
end
And running it, I get this error:
[NoMethodError - undefined method `identified_by' for MessageChannel:Class]
And if I remove identified_by :current_user
, I get
[NameError - undefined local variable or method `current_user' for #<MessageChannel:0x7ace398>]
If you see the doc you provided, you will know that identified_by
is not a method for a Channel
instance. It is a method for Actioncable::Connection
.
From Rails guide for Actioncable Overview, this is how a Connection
class looks like:
#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
end
private
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
As you can see, current_user
is not available here. Instead, you have to create a current_user
here in connection.
The websocket server doesn't have a session, but it can read the same cookies as the main app. So I guess, you need to save cookie after authentication.
if you are using devise gems in rails, Please replace this function:
def find_verified_user # this checks whether a user is authenticated with devise
if verified_user = env['warden'].user
verified_user
else
reject_unauthorized_connection
end
end
I hope this will help you.
After setting self.current_user
in ApplicationCable::Connection
it become available in the channel instances.
So you can set up your authentication like Sajan wrote and just use current_user
in MessageChannel
For example this code worked for me
module ApplicationCable
class Connection < ActionCable::Connection::Base
identified_by :verified_user
def connect
self.verified_user = find_verified_user
end
private
def current_user
jwt = cookies.signed[:jwt]
return unless jwt
decoded = JwtDecodingService.new(jwt).decrypt!
@current_user ||= User.find(decoded['sub']['user_id'])
end
def find_verified_user
current_user || reject_unauthorized_connection
end
end
end
class NextFeaturedPlaylistChannel < ApplicationCable::Channel
def subscribed
stream_from "next_featured_playlist_#{verified_user.id}"
end
end
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With