Ziyu
Ziyu

Reputation: 1137

socket.io-client how to set request header when making connection

I'm trying to set a http header when socket.io client makes the connection request. Is there a way to do this?

Here is what i'm doing:

// server side
var io = socketio(server);

io.use(function (socket, next) {
  // authorize using authorization header in socket.request.headers
});

// client side
var socket = io();  // i'm trying to set an authorization header in this http reqeust

Any ideas? Thanks.

Upvotes: 72

Views: 137621

Answers (10)

Julian Knight
Julian Knight

Reputation: 4923

Bearing in mind that custom request headers are ONLY available on initial connection (which always happens over http(s)) or if using the long-polling connection method (which also always happens over http(s)).

You can set custom headers that the Socket.IO server receives (Request Headers) in 2 ways.

From the client in the options:

transportOptions: {
    // Can only set headers when polling
    polling: {
        extraHeaders: {
            'x-my-header': 'This is my header',
        }
    },
},

OR on the SERVER using the headers event listener:

// Runs when a connection or long-poll request happens
io.engine.on('headers', (headers, req) => {
    // headers contains the response headers that go back to the client.
    headers['x-wowser'] = 'The Client gets this'

    // These are received by the node.js app
    // Allows overrides of socket.request.headers (=== socket.handshake.headers)
    req.headers['remote-user'] = 'test-user'
    req.headers['remote-name'] = 'Test User'
    req.headers['x-user-role'] = 'test-role'
})

As you can see, the 2nd method also allows you to set custom headers that the client receives as well (Response Headers).

Details are in the Socket.IO Server API docs

https://socket.io/docs/v4/server-api/#event-headers

Upvotes: 1

Daniel
Daniel

Reputation: 1205

If you store tokens in cookies, you can just provide withCredentials: true, option.

Upvotes: 0

Ray Foss
Ray Foss

Reputation: 3883

Short Answer: It's imposiburu based on spec... if you just need to pass info early... why not query parameters?

socket = io('localhost:5000', {
      path: '/mySocketPath',
      transports: ['websocket'],
      query: {
        token:'some-token-value'
      }
})

See @satpal-07 in https://github.com/socketio/socket.io-client/issues/1356#issuecomment-810023635

Upvotes: 1

Mohammed Abo-zaid
Mohammed Abo-zaid

Reputation: 426

For some reason, these request headers are only received if the socket server is also socket.io. If I connect to a python Websockets server for example I have no luck authenticating.

The only solution that worked for me is to use a different WebSocket client, for example, ws works fine.

import WebSocket from 'ws';

const socket = new WebSocket('wss://example.com/path', {
      headers: {
            Authorization: 'token'
         },
 });

Upvotes: 3

BuffaloDev
BuffaloDev

Reputation: 483

There's a new way to do this: https://socket.io/docs/v3/middlewares/. Look under the "Sending Credentials" section.

// client
const socket = io(server, {
    transports: ['websocket', 'polling', 'flashsocket'],
    auth: {
        token: 'abc'
    }
});

// server
io.use((socket, next) => {
    const token = socket.handshake.auth.token;
    if (isValidJwt(token)){
        next();
    }else{
        next(new Error("Socket authentication error"));
    }
});

async function isValidJwt(token){
    jwt.verify(token, secrets.jwt, function(err, decoded) {
        if (err){
            console.log(err);
            return false;
        }else{
            //console.log(decoded);
            return true;
        }
    });
}

Upvotes: 25

adamrights
adamrights

Reputation: 1731

This following information has been deprecated since socket.io 1.0

There are two methods of authorization: global or namespace (think route). The global method is set on the server with the io.set('authorization', function (handshakeData, callback) configuration call.

The handshakeData object contains the following information:

{
   headers: req.headers       // <Object> the headers of the request
 , time: (new Date) +''       // <String> date time of the connection
 , address: socket.address()  // <Object> remoteAddress and remotePort object
 , xdomain: !!headers.origin  // <Boolean> was it a cross domain request?
 , secure: socket.secure      // <Boolean> https connection
 , issued: +date              // <Number> EPOCH of when the handshake was created
 , url: request.url          // <String> the entrance path of the request
 , query: data.query          // <Object> the result of url.parse().query or a empty object
}

The above information and a deeper explanation is available on this documentation page.

Upvotes: 4

jagjeet
jagjeet

Reputation: 377

"transportOptions" options can be used to send extra headers in socket.io request. I also explained that here :-

Node.js + Socket.io | Set custom headers on the server

Upvotes: 2

Lu4
Lu4

Reputation: 15030

As of version 2.0.0 / 2017-01-22 engine.io-client supports

[feature] Allow extraHeaders to be set for browser clients in XHR requests (#519)

However at this point the socket.io-client is not updated to support this functionality, so couple of days may make this saga end until that time use the following instructions: https://facundoolano.wordpress.com/2014/10/11/better-authentication-for-socket-io-no-query-strings/

Upvotes: 3

ymyzk
ymyzk

Reputation: 983

You can use extraHeaders option, if you are using socket.io-client >= 1.4.

For example:

var socket = io("http://localhost", {
  extraHeaders: {
    Authorization: "Bearer authorization_token_here"
  }
});

engine.io-client, which is a backend of socket.io-client, introduced extraHeaders support on 2015-11-28.

Upvotes: 77

bakavic
bakavic

Reputation: 1357

It seems like the client doesn't support setting headers, as not all transports allow for the setting of headers.

This post by facundoolano details a workaround to authentication that doesn't require placing the auth token in the query string.

His workaround module can be found at https://github.com/invisiblejs/socketio-auth.

Makes me wonder why on server-side, socket.io allows for the request headers to be accessed...

Upvotes: 16

Related Questions