Preventing users from having multiple sessions

Thanks @hdjay0129. That’s a great answer. I’ll add more detail for @naskha01 and anyone who stumbles across this question.

When a socket connection is opened with a session to Nakama the session is implicitly placed onto the notification stream. This allows the user to receive in-app notifications to that session. With the low level streams feature in Nakama you can take advantage of this info to check whether a session for the user already exists with a stream count of that notification stream.

i.e. From the code @hdjay0129 shared:

local user_id = context.user_id
local mode = 0 -- mode 0 is the notification stream for the user.
local count = nk.stream_count({ mode = mode, subject = user_id })
if (count > 1) then
    nk.logger_info(("User %q has %q active sessions"):format(user_id, count))
end

Streams are very powerful and underpin most of the realtime engine in the game server but they should be used with care! :slight_smile:

You can apply the above check with an RPC function called from the client or socket object in one of the sdks. For example with the Unity client sdk:

var client = new Client("http", "127.0.0.1", 7350, "defaultkey");
var session = ... // Authenticated user session. See docs
await client.RpcAsync(session, "SessionCheck"); // rpc id

Finally for when to initiate this check against the server from the game client depends on what client operations you execute at game start and whether you want to make the check only at a specific moment (like if the user wants to play a multiplayer match).

Exactly when to do it depends on the gameplay design but you could attach it as a preflight to a common request. For example in a before hook for an account get request:

local nk = require("nakama")
local function beforeAccountGet(context, payload)
    local count = nk.stream_count({ mode = 0, subject = context.user_id })
    if (count > 1) then
        error(("User already active: %q"):format(count))
    end
end
nk.register_req_before(beforeAccountGet, "GetAccount")

Hope this helps.

6 Likes