Skip to content

Require a method to update inner ioSocket object for connect / disconnect #86

Open
@davisford

Description

@davisford

In my app, I have both traditional http and websockets -- both are protected by JSON web token authentication. When a user logs in (i.e. post to http endpoint), a token is returned, and then the client will attempt to connect to the websocket endpoint with the token. The connection is rejected if the token isn't valid.

When a user logs out, the websocket is disconnected. I don't want to leave that channel open anymore b/c the user is no longer authenticated. Likewise, I don't want to re-use that same websocket if a new user logs in, b/c the authentication token will be different (and not valid for the new user).

What I'm left with is something like this:

angular.module('app.security')
   .factory('Socket', ['socketFactory', '$rootScope', function (socketFactory, $rootScope) {

      var socket, token = /* get token */

      function connect(token) {
         socket = io.connect('', { query: 'token=' + token, forceNew: true });
         socket.on('connect', function () { /* etc. */ });
         // other event handling
      }

      // connect if we have a token
      if (token) { connect(token); }

      $rootScope.on('login', function ( ) {
          token = /* get token */
          connect(token);
      });

      $rootScope.on('logout', function () { socket.disconnect(); })

      return socketFactory({ ioSocket: socket });
}]);

..and this is an example of how it is in injected into a controller to be used...

angular.module('app.something')
   .controller('FooCtrl', ['Socket', '$scope', function (Socket, $scope) {
      Socket.forward('time:request', $scope);
      $scope.$on('socket:time:response', function (evt, data) {
         console.log('the current time is ', data);
      });
      Socket.emit('time:request');
}]);

On login, the websocket is connected. On logout it is disconnected, and at the end, it is returning the socketFactory wrapper.

The problem here is that socketFactory.$get is only ever called once in the provider, which means that the very first time Socket is injected into a controller it is valid and connected. But if a user logs out and logs in again, angular re-injects the same instance into a controller, and the internal ioSocket has since been disconnected and is no longer good. (note the use of socket.io forceNew option which abandons the socket wholesale and initiates a brand new connection).

What is needed is something like the angular service recipe pattern which news up the object each time, so we don't re-use the same instance of the wrapper...either that or else an API exposed on socketFactory itself that allows one to replace the inner ioSocket reference.

Any ideas on the best way to accomplish this?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions