1

A common way to handle authentication/authorization of websocket connections is to use cookie sent on initial http upgrade request. This is shown here http://edgeguides.rubyonrails.org/action_cable_overview.html

But what if I don't want to use cookie, but rather a token? Couple of hacks discussed here Send auth_token for authentication to ActionCable but it's too hacky imo.

What if I move the token authorization logic to channel:

module ApplicationCable
  class Connection < ActionCable::Connection::Base
    identified_by :connection_id

    def connect
      self.connection_id = SecureRandom.hex # accept anyone, identify by random string
    end
  end
end

This will accept any connection. And than:

class TestChannel < ApplicationCable::Channel
  def subscribed
    if authorize(params[:token]) # check the token here   
      stream_from "test:1"
    else
      connection.close # alternatively `reject_subscription` to keep ws connection open
    end
  end

  def unsubscribed
    stop_all_streams
  end
end

Frontend subscription will look like this

App.test = App.cable.subscriptions.create(channel: "TestChannel", token: "hello-world")

This seems to work. The individual connection is identified by a random string and each channel subscription holds this unique connection. When broadcast to this channel is made it will push the data to all subscribers through their unique connections. So if we rejected a subscriber here it won't receive anything. But we cannot close unauthorized connections before subscription attempt. I can just open the connection to /cable and hold it as long as I want.

But is this safe? The obvious problem here is that anybody can open as many ws connection as he like. Is this the only problem with such approach?

Oleg Antonyan
  • 2,943
  • 3
  • 28
  • 44
  • for security concerns wit cookies you need to read http://edgeguides.rubyonrails.org/security.html – Fabrizio Bertoglio Dec 28 '17 at 14:49
  • I don't want to use cookies, this is the whole point. My concern is about the approach I described where I don't authorize ws connection, but authorize a specific subscription to a channel – Oleg Antonyan Dec 28 '17 at 14:54

0 Answers0