title: AngularJS: Sending Authentication Headers over Websocket
body: <p>I am having difficulty authenticating requests to a WebSocket API.</p>
  
  <p>The Site I am working with (www.bitmex.com) provides a REST API and a WebSocket API.</p>
  
  <p>Both of their API's allow authentication with an API Key.</p>
  
  <p><strong>Authentication Requirements</strong></p>
  
  <p>The API provides the following documentation for authentication with API Keys:</p>
  
  <pre><code>    Authentication is done by sending the following HTTP headers:
  
          api-expires: a UNIX timestamp in the future (eg: 5 seconds).
          api-key: Your public API key. This the id param returned when you create an API Key via the API.
          api-signature: A signature of the request you are making. It is calculated as hex(HMAC_SHA256(verb + url + nonce + data)).
  </code></pre>
  
  <p><strong>REST API</strong></p>
  
  <p>I've created a NodeJS module for sending requests to the REST API, I've defined the following headers</p>
  
  <pre><code>    headers = {
          "User-Agent": "BitMEX NodeJS API Client",
          "api-expires": expires,
          "api-key": this.api_key,
          "api-signature": this.signMessage(verb, reqUrl, expires, params)
      };
  
      where the signMessage function looks like: 
  
      BitMEX.prototype.signMessage = function signMessage(verb, url, nonce, data) {
          if (!data || _.isEmpty(data)) data = '';
          else if(_.isObject(data)) data = formatParameters(data);
  
          return crypto.createHmac('sha256', this.secret).update(verb + url + nonce + data).digest('hex');
      };
  </code></pre>
  
  <p><strong><em>This works great for the REST API and does everything I need it to in the backend of my application.</em></strong></p>
  
  <p><strong>WebSocket API</strong></p>
  
  <p>I am trying to use WebSocket get realtime data and display it in a browser based interface.</p>
  
  <p>The documentation on the site states:</p>
  
  <pre><code>To use an API Key with websockets, you must sign the initial upgrade request in the same manner you would sign other REST calls. 
  </code></pre>
  
  <p>I've been implementing this in AngularJS using the ng-websocket module.</p>
  
  <pre><code>    exchange.dataStream = $websocket('wss://testnet.bitmex.com/realtime');
  
      exchange.dataStream.onMessage(function incoming (message) {
          console.log("BitMEX: WS MESSAGE RECEIVED: " + message.data);    
  
          // .. handle data here ... 
  
      });
  
      exchange.dataStream.send({"op":"getAccount"});
  </code></pre>
  
  <p><strong>The problem that I've run into is I can't find anyway to send the headers using ng-websocket that are needed for authentication.</strong></p>
  
  <p>If I am presently logged in to BitMEX from another tab in my browser, this will connect, get the data, and work as expected.</p>
  
  <p>However, if I am not currently logged in to the site, it will throw the following error:</p>
  
  <pre><code>    BitMEX: WS MESSAGE RECEIVED: {"status":401,"error":"Not authenticated.","meta":{},"request":{"op":"getAccount"}}
  </code></pre>
  
  <p>There is a python example provided here: <a href="https://github.com/BitMEX/market-maker/blob/master/test/websocket-apikey-auth-test.py" rel="nofollow">https://github.com/BitMEX/market-maker/blob/master/test/websocket-apikey-auth-test.py</a> that goes through the Authentication process, 
  but I haven't found a way to accomplish this in AngularJS.</p>
  
  <p><strong>Summary</strong></p>
  
  <p><strong>#1) When logged in to BitMEX, and the Websocket is working, is Chrome somehow using the website's cookies to authenticate the websocket requests?</strong></p>
  
  <p>Looking at an overview of websockets here: <a href="http://enterprisewebbook.com/ch8_websockets.html" rel="nofollow">http://enterprisewebbook.com/ch8_websockets.html</a>
  The initial handshake upgrades the connection from "HTTP" to the WebSocket protocol,</p>
  
  <p><strong>#2) Because this initial connection is over HTTP, is there any way to attach the headers required to this initial HTTP request?</strong></p>