-
Notifications
You must be signed in to change notification settings - Fork 225
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
Don't allow inheriting session unless username matches #398
Comments
Hi @snej, currently the authentication is called before inheritClientSession: Lines 443 to 457 in 5966c7f
Although with static username, it is reasonable to assume username should remain the same to inherit a clientID, but I have seen use-case where username is dynamic, like using JWT. Given MQTT spec (section 5.4.2) leaves what should be checked (username, IP, etc) to the authentication mechanisms, perhaps implementing custom OnConnectAuthenticate is the better route if the requirement is to associate username with clientID? |
Yes, but this issue isn't related to client authentication, rather to channel authorization. For example, if I log in with my valid username and password, but use a session ID that matches your last session, then I will end up with all of your channel subscriptions, whether or not I was supposed to be able to access those channels.
That seems reasonable. The Auth Ledger hook should be updated to do this, then, since I assume that's what most developers will use. The check in the hook would probably look something like this? func (h *myAuthHook) OnConnectAuthenticate(cl *mochi.Client, pk packets.Packet) bool {
existing, _ := h.server.Clients.Get(pk.Connect.ClientIdentifier)
if existing != nil && !slices.Equal(existing.Properties.Username, cl.Properties.Username) {
return false
}
...
} This does have the problem that the error sent to the client will be ErrBadUsernameOrPassword, which isn't accurate; probably ErrClientIdentifierNotValid would be better. Is there any way to customize the error returned to the client? |
Just to ensure we're on the same page, session ID means the client ID the client used to connect? If so, then the use-case you described for the complete authentication should includes clientID/username/password. I assume that username/password should always be associated with a clientID (not only on inheriting a session)
There are 2 general use-cases of mochi-mqtt:
Yes, currently OnConnectAuthenticate only returns a bool. We can either change the hardcoded return code to something generic like Lines 443 to 450 in 5966c7f
or change the signature of OnConnectAuthenticate. Thoughts @mochi-co? |
@snej Consider a scenario where I want all devices to log in using a single username and password, but each device is identified by a different ClientID. I think the association between username and clientID should be managed and allocated by the users themselves through hooks for better suitability. |
I'm fine having the Server struct not enforce matching usernames; I'll close this PR. But it would be good if the |
I had initially put this check into the mochi Server class, and submitted a PR; but others pointed out that in some cases it's intentional to have a single username/password that multiple clients connect with. (See discussion in mochi-mqtt/server#398 ) So instead I've moved this check to our auth hook.
The method Server.inheritClientSession will use a persistent session with a matching ID without comparing the usernames first. This allows a client (accidentally or maliciously) to take over a session belonging to a different user, if it can guess the session ID.
Most seriously, this means the client would inherit the other user's topic subscriptions. It looks as though this bypasses authorization hooks, so the user could have access to topics it shouldn't; that could be a serious security vulnerability.
At a minimum, it allows a client to disconnect another client or wipe out its persistent session if it can guess the ID; an annoying DoS.
This seems to be covered by section 5.4.2 of the MQTT spec:
The fix is pretty simple. I'll post a PR shortly.
The text was updated successfully, but these errors were encountered: