Session Management #

Authentication, coupled with user accounts and session management, can seem complex. There are lots of moving parts that come together, such as:

  • Player behavior
  • Player device
  • Social provider accounts
  • Nakama user accounts

It’s tempting to start coding right away and hope to glue together an unrelated collection of concepts. That can work, but you may frustrate yourself (and your players) with trial-and-error missteps.

Instead, we can approach these concepts as a whole, layering different kinds of sessions — play, social, and authentication — in your code and your players’ experience.

Session types #

The term session is a bit overloaded, used to mean different things in different contexts, from abstract ideas of play to the low-level mechanics of game development. For the purposes of authentication, we care about three types : Play, Sign-in, and Authentication sessions.

Other session types exist and have a role in developing authentication for your game (such as a network TCP session or a cryptographic TLS session). For this topic let’s assume these underlying protocols just work and focus more on player interactions.

Play session #

A play session represents the time a player plays the game before stopping. A play session and its length varies by game type, platform, and player. It may last the length of a turn, round, or match (or many turns, rounds, or matches) and it might be influenced by your player’s attention span and motivation.

Play sessions are how your player experiences the game.

Sign-in session #

A sign-in sessions represents the time your player is signed into their account. This is often through a provider like Google Play Games, Apple Game Center, or your own account infrastructure.

Sign-in sessions are how your game identifies a distinct player. They are a way of tracking a particular player.

Authentication session #

A sign-in sessions represents the time a client and the server are in trusted communication with each other. You can also think of this as a Nakama session.

Sessions overlap #

Players don’t generally think about being signed-in or server connections. They think about playing and not playing. They don’t expect to enter their password or face down a “Connecting” screen every time they take a turn.

As a consequence, session types overlap and depend on each other. This is how sign-ins and authentication support your game: they run longer or shorter than a play session, in ways that are (hopefully) transparent to the player.

You can imagine your game being in many sessions at once: the player signed in, the player spending time playing the game, and the client in connection with Nakama.

The overlap between player behaviors and session types
The overlap between player behaviors and session types

But session types aren’t tightly connected to each other. A player may only play for a few minutes each day, but stay logged into their Apple account for days or weeks. A server connection might be established briefly and intermittently, or persist at length, depending on the game. Sessions need to begin and end in relation with player and game activity.

Starting a session #

Before a client can do anything on the server, such as matchmaking or updating a leaderboard, the client must authenticate with the server.

Authentication marks the start of a session with Nakama. Typically, you authenticate each time the game starts.

The lifecycle for a session in Nakama look like:

  1. Start a session. Identify the player or device with the authenticate API, Nakama responds with a session object.

  2. Make requests using your session object.

  3. When the session expires, refresh or reauthenticate, if needed.

The first step is the most complex. To start the session, your client makes a request to authenticate with an identifier. This ID can come from many sources: social providers’s OAuth tokens, device IDs, usernames and passwords, or a custom service of your own. Wherever your credentials come from, they all say the same thing: this player or device is playing and not any other.

Authentication and social profiles #

This is where the authentication session and sign-in session layers come together. Authentication maps your player’s sign-in session to Nakama session.

Typically, the identifier used with the authentication API is a token from a social provider, such as Apple Game Center, Google Play Games, or Facebook.

If your player is not yet signed in, this is when your game triggers the sign-in flow and gets a new identifier. If your player is signed in, then you pass in the identifier already on-hand.

When you authenticate with a player’s sign-in ID, you map your player’s sign-in ID with their Nakama user account. This is how you begin to knit together play session, sign-in session, and authentication session. When you want to get user data later, you can look it up by Nakama user ID or social provider ID.

Presenting the session object #

After successfully authenticating, Nakama replies with a special session object: a JSON Web Token (JWT). The session object is like a building access badge with an expiration date. You need it to open doors: making further requests to the Nakama server.

JWTs are cryptographically-signed JSON objects. A Nakama session object JWT contains some details — including an expiration date and time — that’s been signed with the server’s private key.

As long as the JWT has not expired and has not been tampered with, the server can securely validate the JWT. At the same time, the JWT is not encrypted, so your client code can inspect its contents too.

Here’s an example JWT in it’s encoded form:

1
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1aWQiOiJmNDA4MmFhMC1hYWQwLTQ1MjYtODkwZC1iYTUwYjI0NmJlMTkiLCJ1c24iOiJhS25pWU5pZ1FiIiwiZXhwIjoxNTk3NjY3MjIwfQ.1fdAmq3nrDcPy0k6BwPCcULmhLiB54Z_feEuDaINNsA

Decoded, it becomes this JSON object:

1
2
3
4
5
{
    "uid": "f4082aa0-aad0-4526-890d-ba50b246be19",
    "usn": "aKniYNigQb",
    "exp": 1597667220
}

The JWT contains three key keys:

  • uid - An ID for the authenticated Nakama user (the Nakama user records may have one or more social identifiers, but this is Nakama’s unique reference to the user)
  • usn - Username
  • exp - An expiration date and time in Unix timestamp format

Armed with this JWT, your code presents the JWT (in encoded form) with every new request to Nakama. By using the JWT requests to Nakama are lightweight and the server can validate the request quickly. Thanks to the cryptographic signature, Nakama can validate the request without the delay of a database lookup.

In other words, cache that JWT! As long as you have a valid session object, you can support the play session by setting up matches, updating leaderboards, adding a player to a chat group, and more.

How a session ends #

The session object expires after the time set in your Nakama configuration. If you try to make a request with an expired session object the request is denied with a 401 Unauthorized error.

When it expires, you can’t make new requests to Nakama (though active socket connections continue until closed even if the original token has expired). If you want to continue making requests, you can refresh the session using a valid refresh token.

If the refresh token is also expired then you have to go back to the beginning and re-authenticate.

But that doesn’t necessarily mean your sign-in session or play session has ended at the same time. For example, if you still have a valid sign-in session with Game Center and the player is still in an active play session, then you can re-authenticate without missing a beat. You don’t have to ask the player to sign-in again or force them out of the game before you re-authenticate.

Likewise, just because a session has ended doesn’t mean that you must re-authenticate immediately. You might wait for the player’s next play session or wait for a specific game action that requires Nakama.

Why ending a session can be useful #

Sometimes it can be useful to manually end a session on the client. For example you may want to do this to give the user the ability to logout of the game, switch user accounts or to purge local state data from the device.

One important reason to add an option to manually end the session is in situations where the user is using a shared device. Manually ending the session and purging the local session data will prevent unauthorized access to the user’s account and game data.

Building session management into your game #

Layering different kinds of sessions into your game might feel complicated. But Nakama can help you with low-level details.

On the server, the Nakama API provides a general authenticate endpoint, plus endpoints specific to Apple, Facebook, Google, and Steam.

On the client you can use the Nakama client for your language or engine to authenticate, refresh a session, and configure automatic session management. Check out the authentication examples to learn more.