Reputation: 1137
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
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
Reputation: 1205
If you store tokens in cookies, you can just provide withCredentials: true,
option.
Upvotes: 0
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
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
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
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
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
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
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
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