Home > Back-end >  Secure Action cable with Doorkeeper Authorisation
Secure Action cable with Doorkeeper Authorisation

Time:01-13

I am working on ActionCable and implemented Doorkeeper Authorization in my rails application.

I want to implement authenticate my client with Doorkeeper::AccessToken with ActionCable

Here is how I authenticated right now:

module ApplicationCable
  class Connection < ActionCable::Connection::Base
    identified_by :current_user
    identified_by :room_id

    def connect
      self.current_user = find_verified_user
      self.room_id = @user.ac_channel_room
    end

    def disconnect
      # When user will disconnect action cable, this method call will be executed.
    end

    private

    def find_verified_user 
      check_access_token
      @user = User.find_by_id(@resource_owner_id) if @resource_owner_id
      reject_unauthorized_connection unless @user
    end

    def check_access_token
      # Check provided token is valid or not
      params = request.query_parameters
      @access_token ||= Doorkeeper::AccessToken.by_token(params[:access_token])
      @resource_owner_id = @access_token&.resource_owner_id
    end
  end
end

Problem is this is allowing experied access tokens as well.

Please help!

CodePudding user response:

Your question will allow action cable connection with expired Doorkeeper::AccessToken objects.

Here is the solution:

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

    def connect
      self.current_user = authenticate!
    end

    protected

    def authenticate!
      reject_unauthorized_connection unless doorkeeper_token&.acceptable?(@_doorkeeper_scopes)

      # this will still allow expired tokens
      # you will need to check if token is valid with something like
      # doorkeeper_token&.acceptable?(@_doorkeeper_scopes)

      user = User.find_by(id: doorkeeper_token.try(:resource_owner_id))

      user || reject_unauthorized_connection
    end

    def doorkeeper_token
      ::Doorkeeper.authenticate(request)
    end
  end
end

# ...

class SomeChannel < ApplicationCable::Channel
  def subscribed
     reject unless current_user
     stream_from 'some'
  end
end
  • Related