Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Common authentication for all namespaces in socket.io 3 #3842

Answered by darrachequesne
AntonNeld asked this question in Q&A
Discussion options

Hi,

I'm confused about how authentication is intended to work when you have multiple namespaces in socket.io 3. We currently (with socket.io 2) use something like https://github.com/socketio/socket.io/blob/master/examples/passport-example/index.js, where we put authentication middleware on the '/' namespace. This then gets executed for every connection.

But we cannot do this with socket.io 3, since sockets no longer always connect to '/'. Instead we have to add this middleware to all namespaces, which seems a bit risky. What if someone uses io.of('foo') in some part of the code, but forgets to add authentication middleware to the namespace? Everything will seem to work, except that the namespace is accessible to all.

Am I missing something, or is this the best option?

(I also tried the 'allowRequest' option when creating the server, but that seems to cause the client to keep trying to connect after being rejected. We also have some other things we do on every new connection, which makes this a less attractive option.)

You must be logged in to vote

Thanks for raising this issue, that's indeed a change from v2 to v3.

A possible workaround would be to override the io.of method:

const of = io.of;
io.of = (...args) => {
 const nsp = of.call(io, ...args);
 nsp.use(yourMiddleware);
 return nsp;
}

Dynamic namespaces could work too, depending on your use case:

const parentNamespace = io.of(/^\/dynamic-\d+$/);
parentNamespace.use(yourMiddleware); // attached to all child namespaces

Replies: 2 comments 6 replies

Comment options

Thanks for raising this issue, that's indeed a change from v2 to v3.

A possible workaround would be to override the io.of method:

const of = io.of;
io.of = (...args) => {
 const nsp = of.call(io, ...args);
 nsp.use(yourMiddleware);
 return nsp;
}

Dynamic namespaces could work too, depending on your use case:

const parentNamespace = io.of(/^\/dynamic-\d+$/);
parentNamespace.use(yourMiddleware); // attached to all child namespaces
You must be logged in to vote
3 replies
Comment options

Okay, thanks! Good to know I wasn't missing some big obvious thing.

Overriding io.of would work, with the tradeoff that it makes the code more confusing. I'm leaning towards just being disciplined when creating namespaces, but we'll see what we decide on. Good to know the option exists, anyway. (Dynamic namespaces wouldn't work for our use case, since the server emits to explicitly defined namespaces.)

It would be a useful feature to be able to define global middleware, I think. All three examples in the docs (auth, logging, rate limiting) seem like things you would often want to share between namespaces.

Comment options

That sounds reasonable 👍 : #3851

Comment options

Even though this sort of works the behaviour is entirely different.

Before if you had an auth middleware on the default namespace you would only authenticate once. With this solution the authentication process will occur for every namespace.

I fixed this by adding a promise to the socket.client to be reused, however that feels like a hack.

@darrachequesne It would be beneficial to have a one call to handle authentication process as you could before.

Answer selected by darrachequesne
Comment options

any update on this? I also would like to add a middleware for all namespaces.

You must be logged in to vote
3 replies
Comment options

I guess we could indeed add it. Any suggestion for the method name?

Comment options

useDeep?

Comment options

useGlobal?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

AltStyle によって変換されたページ (->オリジナル) /