# Preventing users from having multiple sessions

**URL:** https://forum.heroiclabs.com/t/preventing-users-from-having-multiple-sessions/36
**Category:** Local Setup
**Created:** [June 27, 2019, 9:39pm UTC](https://forum.heroiclabs.com/t/preventing-users-from-having-multiple-sessions/36 "2019-06-27T21:39:54Z")
**Posts on this page:** 14
**Page:** 1

<div class="post-metadata">

### Author: ![naskha01](https://sea2.discourse-cdn.com/flex020/user_avatar/forum.heroiclabs.com/naskha01/32/93_2.png) [@naskha01](https://forum.heroiclabs.com/u/naskha01)
#### Post date: [June 27, 2019, 9:39pm UTC](https://forum.heroiclabs.com/t/preventing-users-from-having-multiple-sessions/36/1 "2019-06-27T21:39:54Z")

</div>

is there a way to prevent users connecting from multiple devices ?

---

<div class="post-metadata">

### Author: ![hdjay0129](https://sea2.discourse-cdn.com/flex020/user_avatar/forum.heroiclabs.com/hdjay0129/32/1103_2.png) [@hdjay0129](https://forum.heroiclabs.com/u/hdjay0129)
#### Post date: [June 28, 2019, 4:44am UTC](https://forum.heroiclabs.com/t/preventing-users-from-having-multiple-sessions/36/2 "2019-06-28T04:44:14Z")

</div>

This is in **lua** -  
One way to prevent multiple session would be to create an rpc like below to check whether user has multiple sessions or not using the notification stream.  
Call this rpc after successful authentication.  
It uses default notification stream count for that user\_id.

```auto
function o_u_h.check_user_on_stream(context, payload)

    local result = {
        session_already_connected = false
    }

    -- checking for notification stream
    local count = nk.stream_count({mode = 0, subject = context.user_id})
    if (count > 1) then
        -- user is already connected
        result.session_already_connected = true
    end

    return nk.json_encode(result)

end
nk.register_rpc(o_u_h.check_user_on_stream, "check_user_on_stream")

```

---

<div class="post-metadata">

### Author: ![hdjay0129](https://sea2.discourse-cdn.com/flex020/user_avatar/forum.heroiclabs.com/hdjay0129/32/1103_2.png) [@hdjay0129](https://forum.heroiclabs.com/u/hdjay0129)
#### Post date: [June 28, 2019, 4:46am UTC](https://forum.heroiclabs.com/t/preventing-users-from-having-multiple-sessions/36/3 "2019-06-28T04:46:35Z")

</div>

@novabyte also shared it’s equivalent Golang code on community channel -  
Here’s that

```auto
type SessionCheckResponse struct {
    AlreadyConnected bool `json:"already_connected"`
}

func rpcSessionCheck(ctx context.Context, logger runtime.Logger, db *sql.DB, nk runtime.NakamaModule, payload string) (string, error) {
    userID, ok := ctx.Value(runtime.RUNTIME_CTX_USER_ID).(string)
    if !ok {
        return "", runtime.NewError("no ID for user; must be authenticated", 3)
    }
    // See how many presences the user has on their notification stream.
    count, err := nk.StreamCount(0, userID, "", "")
    if err != nil {
        return "", fmt.Errorf("unable to count notification stream for user: %s", userID)
    }
    response, err := json.Marshal(&SessionCheckResponse{AlreadyConnected: count > 1})
    if err != nil {
        logger.Error("unable to encode json: %v", err)
        return "", errors.New("failed to encode json")
    }
    return string(response), nil
}

```

You register it within your InitModule function like so:

```auto
 if err := initializer.RegisterRpc("SessionCheck", rpcSessionCheck); err != nil {
    return err
}

```

---

<div class="post-metadata">

### Author: ![hdjay0129](https://sea2.discourse-cdn.com/flex020/user_avatar/forum.heroiclabs.com/hdjay0129/32/1103_2.png) [@hdjay0129](https://forum.heroiclabs.com/u/hdjay0129)
#### Post date: [June 28, 2019, 4:48am UTC](https://forum.heroiclabs.com/t/preventing-users-from-having-multiple-sessions/36/4 "2019-06-28T04:48:48Z")

</div>

& I think, Instead of creating RPC, You can also hook that function code on the before hook for the authentication, but I don’t know if there is a way to return custom errors from the before hook to know the cause on client side.

---

<div class="post-metadata">

### Author: ![naskha01](https://sea2.discourse-cdn.com/flex020/user_avatar/forum.heroiclabs.com/naskha01/32/93_2.png) [@naskha01](https://forum.heroiclabs.com/u/naskha01)
#### Post date: [June 28, 2019, 10:09pm UTC](https://forum.heroiclabs.com/t/preventing-users-from-having-multiple-sessions/36/5 "2019-06-28T22:09:09Z")

</div>

Thanks a lot , u save my day

---

<div class="post-metadata">

### Author: ![novabyte](https://sea2.discourse-cdn.com/flex020/user_avatar/forum.heroiclabs.com/novabyte/32/1324_2.png) [@novabyte](https://forum.heroiclabs.com/u/novabyte)
#### Post date: [June 29, 2019, 12:11pm UTC](https://forum.heroiclabs.com/t/preventing-users-from-having-multiple-sessions/36/6 "2019-06-29T12:11:49Z")

</div>

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](https://heroiclabs.com/docs/social-in-app-notifications/) to that session. With the low level [streams feature](https://heroiclabs.com/docs/advanced-streams/) in Nakama you can take advantage of this info to check whether a session for the user already exists with a [stream count](https://heroiclabs.com/docs/advanced-streams/#counting-stream-presences) of that notification stream.

i.e. From the code @hdjay0129 shared:

```lua
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! 🙂

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:

```auto
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](https://heroiclabs.com/docs/runtime-code-basics/#before-hook) for an account get request:

```lua
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.

---

<div class="post-metadata">

### Author: ![surajTLabs](https://sea2.discourse-cdn.com/flex020/user_avatar/forum.heroiclabs.com/surajtlabs/32/1497_2.png) [@surajTLabs](https://forum.heroiclabs.com/u/surajTLabs)
#### Post date: [March 31, 2023, 11:59am UTC](https://forum.heroiclabs.com/t/preventing-users-from-having-multiple-sessions/36/7 "2023-03-31T11:59:48Z")

</div>

Let’s say if user already have active session on Device-A and he tries to login with same account from Device-B.

So, is there a way to disconnect previously connected user on Device-A while connecting on Device-B.

I can see that from nk.stream\_count we can find number of multiple sessions for a user, But how to get already connected sessionId so that we can disconnect it also from another device.

---

<div class="post-metadata">

### Author: ![demon](https://avatars.discourse-cdn.com/v4/letter/d/7ba0ec/32.png) [@demon](https://forum.heroiclabs.com/u/demon)
#### Post date: [April 2, 2023, 10:26pm UTC](https://forum.heroiclabs.com/t/preventing-users-from-having-multiple-sessions/36/8 "2023-04-02T22:26:11Z")

</div>

@surajTLabs

> **[Configuration](https://heroiclabs.com/docs/nakama/getting-started/configuration/#session)**
>
> Overview of how to provide a custom configuration for your Nakama server, and all available configuration properties.

Read about single\_socket. You can set that to true in your configraution file(typically a yaml file) to achieve what you want.

---

<div class="post-metadata">

### Author: ![surajTLabs](https://sea2.discourse-cdn.com/flex020/user_avatar/forum.heroiclabs.com/surajtlabs/32/1497_2.png) [@surajTLabs](https://forum.heroiclabs.com/u/surajTLabs)
#### Post date: [April 3, 2023, 4:46am UTC](https://forum.heroiclabs.com/t/preventing-users-from-having-multiple-sessions/36/9 "2023-04-03T04:46:55Z")

</div>

I tested with [`single_socket`](https://heroiclabs.com/docs/nakama/getting-started/configuration/#session.single_socket) parameter and it seems to solve that issue.

Is there a way to know, reason/more information in Unity Client that why socket is closed?

Because, in current game there is a logic which auto retries to connect to server if it’s disconnected.  
Due to this both parallel user will keep disconnecting each other one by one in a loop.

I also tried using [`single_match`](https://heroiclabs.com/docs/nakama/getting-started/configuration/#session.single_match), but it didn’t make any difference.

---

<div class="post-metadata">

### Author: ![surajTLabs](https://sea2.discourse-cdn.com/flex020/user_avatar/forum.heroiclabs.com/surajtlabs/32/1497_2.png) [@surajTLabs](https://forum.heroiclabs.com/u/surajTLabs)
#### Post date: [April 3, 2023, 1:25pm UTC](https://forum.heroiclabs.com/t/preventing-users-from-having-multiple-sessions/36/11 "2023-04-03T13:25:07Z")

</div>

To check active session from RPC first we need to authenticate.

With single\_socket enabled, the moment we authenticate with 2nd device it closes the session from 1st device. So, when the session is closed, I am unable to access the RPC, so is there any other way around to call the RPC to check active sessions?

---

<div class="post-metadata">

### Author: ![demon](https://avatars.discourse-cdn.com/v4/letter/d/7ba0ec/32.png) [@demon](https://forum.heroiclabs.com/u/demon)
#### Post date: [April 4, 2023, 9:09am UTC](https://forum.heroiclabs.com/t/preventing-users-from-having-multiple-sessions/36/12 "2023-04-04T09:09:42Z")

</div>

yeah that’s true. I misunderstood that.

---

<div class="post-metadata">

### Author: ![demon](https://avatars.discourse-cdn.com/v4/letter/d/7ba0ec/32.png) [@demon](https://forum.heroiclabs.com/u/demon)
#### Post date: [April 4, 2023, 4:47pm UTC](https://forum.heroiclabs.com/t/preventing-users-from-having-multiple-sessions/36/13 "2023-04-04T16:47:31Z")

</div>

@novabyte  
I have a similar situation but not quite the same. Using single\_socket makes sure that there’s only one active sessions by disconnecting the previous login.  
The problem with this solution is that single\_socket only disconnects socket, does not log out the user from that other device(previous login). This could pose as a security flaw for our game as the auth token and refresh token are still valid.  
Is there a way to invalidate these tokens(tokens from older login) ?

---

<div class="post-metadata">

### Author: ![novabyte](https://sea2.discourse-cdn.com/flex020/user_avatar/forum.heroiclabs.com/novabyte/32/1324_2.png) [@novabyte](https://forum.heroiclabs.com/u/novabyte)
#### Post date: [April 7, 2023, 7:42am UTC](https://forum.heroiclabs.com/t/preventing-users-from-having-multiple-sessions/36/14 "2023-04-07T07:42:59Z")

</div>

@demon There’s no way right now to invalidate the session token which would be authorized on the other device without it being done by the game client code. You could handle the socket disconnect and observe the leave reason and based on that issue a logout from the game client itself.

Your use case’s requirements make a lot of sense to become an official solution. Can you open a feature request on the GitHub issue tracker for Nakama?

---

<div class="post-metadata">

### Author: ![demon](https://avatars.discourse-cdn.com/v4/letter/d/7ba0ec/32.png) [@demon](https://forum.heroiclabs.com/u/demon)
#### Post date: [April 13, 2023, 8:33am UTC](https://forum.heroiclabs.com/t/preventing-users-from-having-multiple-sessions/36/15 "2023-04-13T08:33:50Z")

</div>

> <https://github.com/heroiclabs/nakama/issues/1014>
>
> Using single\_socket makes sure that there’s only one active sessions by disconne…cting the previous login. The problem with this solution is that single\_socket only disconnects socket, does not log out the user from that other device(previous login). This could pose as a security flaw as the auth token and refresh token are still valid.
> There should be a way to invalidate these tokens(tokens from older login) or simply log out the older login maybe through a configuration along side single\_socket.
> 
> Forum discussion:
> 
> My comment:
> https://forum.heroiclabs.com/t/preventing-users-from-having-multiple-sessions/36/13
> 
> Chris Molozian's comment:
> https://forum.heroiclabs.com/t/preventing-users-from-having-multiple-sessions/36/14
> 
> Chris has provided a solution in the above comment but that is still not secure because it is not Nakama authoritative which would be the most secure scenario.

Thank you Chris, I have already been thingking of that solution as a last resort hoping there might be a solution from within Nakama but since there isn’t any I would go on to log out the user. Since it is not the most ideal/secure solution, I have raised a [feature request](https://github.com/heroiclabs/nakama/issues/1014).
