text: Q:
  
  How To use devise_token_auth with ActionCable for authenticating user?
  
  I have a Rails 5 API with devise_token_auth gem authentications.
  Now I want personal chat for authenticated users. I do not have assets as I am using API and front is in native apps and I want native apps messaging.
  So how I can authenticate users to use action cable for personal messaging using devise_token_auth gem
  
  A:
  
  No cookies are generally supported in Rails 5 API. See: http://guides.rubyonrails.org/api_app.html#creating-a-new-application .
  If you do a common HTTP-authentification at first somewhere at your site ( with devise_token_auth gem), then you get 3 auth headers - access_token, client, uid.
  In such case you can use the Basic authentification for your Websockets connection (according https://devcenter.heroku.com/articles/websocket-security#authentication-authorization ) using these 3 auth headers:
  Call (I use Chrome Simple WebSocket Client):
  ws://localhost:3000/cable/?access-token=ZigtvvcKK7B7rsF_20bGHg&client=TccPxBrirWOO9k5fK4l_NA&uid=client1@example.com
  
  Then process:
  # Be sure to restart your server when you modify this file. Action Cable runs in an EventMachine loop that does not support auto reloading.
  module ApplicationCable
    class Connection < ActionCable::Connection::Base
      identified_by :current_user
  
      def connect
  
          params = request.query_parameters()
  
          access_token = params["access-token"]
          uid = params["uid"]
          client = params["client"]
  
          self.current_user = find_verified_user access_token, uid, client
          logger.add_tags 'ActionCable', current_user.email
      end
  
      protected
  
          def find_verified_user token, uid, client_id # this checks whether a user is authenticated with devise
  
              user = User.find_by email: uid
  # http://www.rubydoc.info/gems/devise_token_auth/0.1.38/DeviseTokenAuth%2FConcerns%2FUser:valid_token%3F
              if user && user.valid_token?(token, client_id)
                  user
              else
                  reject_unauthorized_connection
              end
          end   
    end
  end
  
  This is similar to the common Websockets auth https://rubytutorial.io/actioncable-devise-authentication/
  Such authentication is probably enough. I believe it is not necessary additionally to auth at the channel subscription and on every Websocket message sent to server:
  http://guides.rubyonrails.org/action_cable_overview.html#server-side-components-connections
  
  For every WebSocket accepted by the server, a connection object is instantiated. This object becomes the parent of all the channel subscriptions that are created from there on. The connection itself does not deal with any specific application logic beyond authentication and authorization.
  
  So if your connection is identified_by :current_user, you can later access current_user wherever inside your FooChannel < ApplicationCable::Channel! Example:
  class AppearanceChannel < ApplicationCable::Channel
    def subscribed
  
      stream_from "appearance_channel"
  
      if current_user
  
        ActionCable.server.broadcast "appearance_channel", { user: current_user.id, online: :on }
  
        current_user.online = true
  
        current_user.save!
  
      end
  
    end
  
    def unsubscribed
  
      if current_user
  
        # Any cleanup needed when channel is unsubscribed
        ActionCable.server.broadcast "appearance_channel", { user: current_user.id, online: :off }
  
        current_user.online = false
  
        current_user.save!      
  
      end
  
    end 
  
  end
  
  PS I you want to use cookies in Rails 5 API, you can switch it on:
  http://guides.rubyonrails.org/api_app.html#other-middleware
  config/application.rb
  config.middleware.use ActionDispatch::Cookies
  
  http://guides.rubyonrails.org/api_app.html#adding-other-modules
  controllers/api/application_controller.rb
  class Api::ApplicationController < ActionController::API
  
      include ActionController::Cookies
  ...
  
  A:
  
  Here the auth_headers set in the cookies by ng-token-auth are used to determine if the request is authenticated, if not the connection is refused.
  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 # this checks whether a user is authenticated with devise_token_auth
          # parse cookies for values necessary for authentication
          auth_headers = JSON.parse(cookies['auth_headers'])
  
          uid_name          = DeviseTokenAuth.headers_names[:'uid']
          access_token_name = DeviseTokenAuth.headers_names[:'access-token']
          client_name       = DeviseTokenAuth.headers_names[:'client']
  
          uid        = auth_headers[uid_name]
          token      = auth_headers[access_token_name]
          client_id  = auth_headers[client_name]
  
          user = User.find_by_uid(uid)
  
          if user && user.valid_token?(token, client_id)
            user
          else
            reject_unauthorized_connection
          end
        end
    end
  end
  
  