Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Client should ensure socket.io upgrade is complete before authenticating #275

Closed
zender opened this Issue Aug 19, 2016 · 15 comments

Comments

Projects
None yet
6 participants
@zender
Copy link

zender commented Aug 19, 2016

I have the following code in Angular 2:

import { Injectable } from '@angular/core';
import {Parameters} from '../../../parameters';
import {AuthService} from '../security/auth.service';

declare const io;
declare const feathers;

@Injectable()
export class SocketService {

  private _app: any;

  constructor(private authService: AuthService) {
    this.connect();
    this.authenticate();
  }

  connect(): void {
    var authService: AuthService = this.authService;
    var socket: any = io(Parameters.URL);

    var app: any = feathers()
      .configure(feathers.socketio(socket))
      .configure(feathers.hooks())
      .configure(feathers.authentication({ storage: localStorage, tokenKey: 'jwt'}))
    ;

    this._app = app;
  }

  authenticate(): Promise<any> {
    return this._app.authenticate({
      type: 'token',
      token: this.authService.getToken(),
    }).then(() => {
      console.info('Authenticated!');

    }).catch(function(error){
      console.info('Error authenticating!', error);
    });
  }

  getResource(service: string): any {
    return this._app.service(service);
  }
}

authenticate() method works fine but when I try to call getResource("some service") .someMethod then it says that token is missing.

Any suggestion how to fix that?

@zender zender changed the title Autentication problem with socketIO Authentication problem with socketIO Aug 19, 2016

@zender

This comment has been minimized.

Copy link
Author

zender commented Aug 19, 2016

Also the code below seems not to work (params are never set):

app.mixins.push(function(service) {
  service.before((hook) => {
    Object.assign(hook.params, {
      user: authService.getUser(),
      token:authService.getToken()
    });

    return hook;
  });
});
@daffl

This comment has been minimized.

Copy link
Member

daffl commented Aug 19, 2016

I'm not sure what getResource("some service") does. The token will only be set automatically on service calls that are used on the client via app.service('some service'). For any other client mechanism you will have to add it yourself.

@zender

This comment has been minimized.

Copy link
Author

zender commented Aug 19, 2016

It is working in REST as expected but using socketIO, token is not sent to the server at all.

Shall I provide you with some code?

@daffl

This comment has been minimized.

Copy link
Member

daffl commented Aug 20, 2016

Yes please. Maybe a repository to reproduce. I have definitely used authentication and service requests with Socket.io before.

@zender

This comment has been minimized.

Copy link
Author

zender commented Aug 21, 2016

I have created a simple featherjs app: https://github.com/zender/feathers-285
Also client app (angular2): https://github.com/zender/feathers-client-285

REST provider is working without any problems but socketio is not sending the token.

feathers-client does not read token from local storage (I had to set it manually) - https://github.com/zender/feathers-client-285/blob/master/src/app/shared/services/rest.service.ts#L36

Also hooks are not working either on the client side: https://github.com/zender/feathers-client-285/blob/master/src/app/shared/services/rest.service.ts#L25

Thank you in advance for your support.

@bertho-zero

This comment has been minimized.

Copy link
Contributor

bertho-zero commented Aug 25, 2016

I have the same problem, I am logged in rest but not in socket, I get an error 'token missing'.

So it would be nice to reconnect the user to the socket with cookies.

@bertho-zero

This comment has been minimized.

Copy link
Contributor

bertho-zero commented Aug 28, 2016

I sign in with facebook JS SDK in react app, after I use facebook-token passport strategy, it's work but if I also use a socket connection for a chat I'm not connected, how to connect the socket after a rest connection?

On client-side I noticed that we can't connect with socket on social provider: app.authenticate('facebook', data) is disallow and app.service('/auth/facebook').create() work but only if app use rest.

@zender

This comment has been minimized.

Copy link
Author

zender commented Aug 29, 2016

any updates???

@fedevela

This comment has been minimized.

Copy link

fedevela commented Aug 29, 2016

I would recommend using a basic feathers example that works for you, then modifying what you need on top of that.

@fedevela

This comment has been minimized.

Copy link

fedevela commented Aug 29, 2016

When i deploy a feathers application, the token gets set automatically when I access through the feather services, but get a 401 when doing it any other way.

@marshallswain

This comment has been minimized.

Copy link
Member

marshallswain commented Sep 24, 2016

For anybody having this issue, please make sure that your socket.io connection's upgrade process has fully stabilized before you call authenticate.

Socket.IO never assumes that WebSocket will just work, because in practice there’s a good chance that it won’t. Instead, it establishes a connection with XHR or JSONP right away, and then attempts to upgrade the connection to WebSocket. Compared to the fallback method which relies on timeouts, this means that none of your users will have a degraded experience. http://socket.io/blog/introducing-socket-io-1-0/

If you call authenticate right when socket.io connects, and you haven't locked the transports to websocket, the XHR-based connection with be authenticated, but then will subsequently be lost in the upgrade to JSONP or WebSockets. There are two workarounds to this problem. One is to configure your socket.io connection transports to only use WebSockets, then you can always assume you've got the right connection. The client code would look something like this:

const feathers = require('feathers/client')
const socketio = require('feathers-socketio/client');
const hooks = require('feathers-hooks');
const io = require('socket.io-client');
const authentication = require('feathers-authentication/client');

const socket = io('http://api.my-feathers-server.com', {
  transports: ['websocket']
});
const app = feathers()
  .configure(hooks())
  .configure(socketio(socket));
  .configure(authentication({ storage: window.localStorage }));

app.authenticate();

The downside to the above is that it won't work with clients that aren't compatible with WebSockets. So, the alternative would be to make sure you authenticate after the transport upgrade has occurred:

const feathers = require('feathers/client')
const socketio = require('feathers-socketio/client');
const hooks = require('feathers-hooks');
const io = require('socket.io-client');
const authentication = require('feathers-authentication/client');

const socket = io('http://api.my-feathers-server.com', {
  transports: ['websocket']
});
const app = feathers()
  .configure(hooks())
  .configure(socketio(socket));
  .configure(authentication({ storage: window.localStorage }));

socket.io.engine.on('upgrade', function(transport) {
  console.log('transport changed');
  app.authenticate();
});

See this Stack Overflow answer for more examples.

marshallswain added a commit to feathersjs/docs that referenced this issue Sep 24, 2016

Add a note about socket.io connections upgrades.
You have to authenticate after the transport upgrades.  See feathersjs/authentication#275
@ekryski

This comment has been minimized.

Copy link
Member

ekryski commented Oct 1, 2016

@marshallswain @daffl maybe we should do this inside the client itself.

@marshallswain

This comment has been minimized.

Copy link
Member

marshallswain commented Oct 1, 2016

I think so. It's something that you would want in every app, I think.

@ekryski

This comment has been minimized.

Copy link
Member

ekryski commented Oct 4, 2016

Ya I agree. Going to change the title on this.

@ekryski ekryski changed the title Authentication problem with socketIO Client should ensure socket.io upgrade is complete before authenticating Oct 4, 2016

@marshallswain

This comment has been minimized.

Copy link
Member

marshallswain commented Oct 25, 2016

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.