Introduction

There are various different authentication requests available with GameSparks but some of the most commonly used requests are the basic DeviceAuthenticationRequest, RegistrationRequest and AuthenticationRequest (username/password). We will be focusing on these basic authentication requests in this topic.

Note - This topic doesn't cover 3rd party and social authentication. There is another topic here which covers that.

Device Authentication

Device-auth is most often used as anonymous authentication where the player is not required to submit any credentials before gaining access to the game. With GameSparks, this request still uses device and OS settings for authentication so the device can be identified, so there is some identification needed but they are provided programmatically.

If the platform does not have an alternative, but does have username & password, you can use some hashed device details like the appId or mac address as a unique Id instead.

Registration

Registration allows a player to be created with a username and password for their account so they can log in on multiple devices.

Authentication Request

The basic auth-request just uses username & password. It requires registration before the details are valid, unlike device authentication which automatically signs you in and creates the player’s account.

Note - Not all destination platforms will have the same kinds of authentication requests as GameSparks has so we will try to cover these 3 forms of auth as best we can for each platform. For frontend examples and code-snippets, we will also be focusing on Unity C# examples as it is the most popular engine used with GameSparks.

Beamable

Beamable handles authentication a bit differently to other platforms. When a new session is created, there is automatically an auth-token issued to the user and the same auth-token can be used in subsequent sessions for frictionless authentication. This is basically the Beamable equivalent to device authentication.

In relation to a GameSparks login alternative we will be focusing on the login APIs in C# here. However, Beamable also has prefab elements that can be imported into your project to have auth setup automatically. You can read more about that feature here.

Authentication & Registration

Since every new session starts anonymously, we don't really authenticate or register player accounts directly.

Instead you can attach emails or other credentials to the access token granted to you upon the first session. This is how you would authenticate using another device or retrieve the token after it expired on your device.

/// <summary>
/// Adds a username and password context to the current player's account for later authentication
/// <param name="userName">Player's User name</param>
/// <param name="password">Password</param>
/// </summary>
public async void ConvertAccount(string userName, string password)
{
    var beamable = await Beamable.API.Instance; // We need a reference back to the Beamable instance
    Debug.Log("Registering user [" + beamable.User.id + "]...");
    try
    {
        var user = await beamable.AuthService.RegisterDBCredentials(userName, password);
        Debug.Log("Username & Password Set!...");
    }
    catch (PlatformRequesterException e) when (e.Status == 400 && e.Error.service == "accounts")
    {
        // the email has either already been taken by another account, or the current account already has an email.
        Debug.LogException(e);
    }
}

Now that you have a username and password attached to the account, you will need to switch accounts when you go to another device because, remember, Beamable will automatically log you into a new session on the new device.

/// <summary>
/// Logs the player with the given username and password in
/// <param name="userName">Player's User name</param>
/// <param name="password">Password</param>
/// <returns>User</returns>
/// </summary>
async User Login(string userName, string password)
{
    var beamable = await Beamable.API.Instance; // We need a reference back to the Beamable instance
    Debug.Log("Logging player in | userName: [" + userName + "], password: [" + password + "]...");

    var token = await beamable.AuthService.Login(userName, password, false);
    await beamable.ApplyToken(token);
    return beamable.User;
}

AccelByte

Accelbyte has a similar flow to GameSparks in that a user must first be registered before you can log the user in.

Registration

New users need more details than you would be used to with GameSparks. New users also need their email, country and date of birth. This is detailed here and in their Unity Sample guide. Although these details are needed for registration, you could add dummy data.

Requests from the client SDK are similar to the GameSparks with a list of parameters being passed into an SDK function, which also raises a callback when the login response comes back from Accelbyte.

private static void OnRegister(Result<UserData> result)
{
    if (result.IsError)
    {
        Debug.Log("Register failed:", result.Error.Message);
    }
    else
    {
        Debug.Log("Register successful.");
    }
}
public static void Main(string[] args)
{
    var user = AccelBytePlugin.GetUser();
    string email = "useremail@example.com";
    string username = "JohnDoe";
    string password = "password";
    string displayName = "displayed";
    string country = "US";
    string dateOfBirth = "1995-12-30";
    user.Registerv2(email, username, password, displayName, OnRegister, country, dateOfBirth);
}

Authentication

Once a user has been registered, it is very easy to log them in using their username and password. Their docs here show how to create a new user object and log them in with only a couple of lines of code in Unity.

User user = AccelBytePlugin.GetUser();
user.LoginWithUserName(email, password, (Result result) => { });

Device Authentication

Accelbyte also has a very simple replacement for device-authentication here. These accounts are called “headless” accounts by Accelbyte as they have no username until the username has been set.

User user = AccelBytePlugin.GetUser();
user.LoginWithDeviceId((Result result)=>{ });

Nakama

Nakama has alternatives to all of the standard authentication routes we mentioned in the introduction. We will cover this in brief in this topic as they are very simple to set up and work similarly to what you would expect from GameSparks.

Script Setup

As this will be the first topic many developers will check for feature parity with GameSparks, we will briefly mention how the Nakama client and SDK are set up in Unity. Before adding this code you will need to have an instance of the Nakama server running somewhere. In the case of this example we are running it locally for testing. You can check out a guide here on how to get the server running locally.

For this example we created a C# script and attached it to a GameObject in Unity. This is going to be our “NakamaManager” script. Unlike GameSparks, all of the attributes of the Nakama SDK are set in this script, rather than through editor settings.

We will go through each of the components needed for this setup below.

public class NakamaManager : MonoBehaviour
{
   /// <summary>
   /// This is either http or https.
   /// https requires TLS setup
   /// </summary>
   private static string commProtocol = "http";

   /// <summary>
   /// The address where the Nakama instance is running (local is 127.0.0.1)
   /// </summary>
   private static string serverIp = "127.0.0.1";

   /// <summary>
   /// This is the port used to create the config backend instance (the portal)
   /// </summary>
   private static int serverPort = 7350;

   /// <summary>
   /// Like the GS "server secret". Can be set from the config portal
   /// </summary>
   private static string serverKey = "defaultkey";

   /// <summary>
   /// This is our Nakama client.
   /// </summary>
   private readonly IClient nakamaClient = new Client(commProtocol, serverIp, serverPort, serverKey);
}

Device Authentication

Device authentication is simple, and like GameSparks, there is a method in the client API specifically for device authentication. However, we do need to remember that we are using asynchronous methods with Nakama so instead of using a callback to determine when the player has been logged in, we will use the “await” command from within an asynchronous method.

As with GameSparks, you can assign a name to a player which is logging in with a device ID. However, this becomes the “userName” of the player and not the “displayName” as you would be familiar with in GameSparks. Usernames must be unique.

/// <summary>
/// Logs the player in using a deviceId
/// </summary>
/// <param name="userName"></param>
private async void DeviceAuthentication(string userName)
{
   Debug.Log("Attempting device auth...");
   Debug.Log($"User Name {userName}...");
   // We'll get the same deviceId that GameSparks uses //
   string deviceId = SystemInfo.deviceUniqueIdentifier.ToString ();
   Debug.Log($"New deviceId: {deviceId}");

   ISession session = await nakamaClient.AuthenticateDeviceAsync(deviceId, userName);
   // Now we can log out the session details //
   Debug.Log($"UserId: {session.UserId}");
   Debug.Log($"AuthToken: {session.AuthToken}");
}

In the Unity console we should see the following logs.

We can confirm the player has been created by going to your Developer Console which can be found at http://127.0.0.1:7351 if you are running the server locally.

Choose the “Accounts” option from the left-hand side menu and you should see your player with the user ID we set from Unity.

You can see here that there is a field for display name if you would like to set it, so let us take a look at how we can set that up. You may need to delete this player so that we can create them again with the display name set.

To set and edit additional player settings we can use the UpdateAccountAsync()method. This method allows us to update different fields on the player account like display name, location, timezone and avatar URL.

ISession session = await nakamaClient.AuthenticateDeviceAsync(deviceId, userName);
// Now we can log out the session details //
Debug.Log($"UserId: {session.UserId}");
Debug.Log($"AuthToken: {session.AuthToken}");
// add displayName to the player's account //
await nakamaClient.UpdateAccountAsync(session, userName, displayName);

And we can check if this added the display name to our player using the accounts window of the Developer Console.

Registration

Next we will take a look at registration. Basic registration and authentication actually use the same method from the Nakama client API, however there are some settings that let this authentication method act like a GameSparks RegistrationRequest.

There is unfortunately no basic-authentication request in Nakama for username and password. To replicate this functionality we are going to modify the AuthenticateEmailAsync() method so that we can log in with a username and password. We will do this by appending an email to the username when we register the account.

This will let it pass the email parameter validation check, and create the account. We can also add the actual username and display name to the user’s account as the username field is different from the email used to login.

This may seem like a round-about way achieve login but if your game currently uses username/password it will allow you to migrate your accounts and your players won't know they are logging in with a fake email instead of their usernames.

/// <summary>
/// Registers a new user with the given username and password
/// </summary>
/// <param name="userName"></param>
/// <param name="password"></param>
/// <param name="displayName"></param>
private async void UserRegistration(string userName, string password, string displayName)
{
   Debug.Log("Attempting user registration...");
   Debug.Log($"Username: {userName}, password: {password}");

   ISession session = await nakamaClient.AuthenticateEmailAsync(userName+"@mygame.com", password, userName, true);
   // Now we can log out the session details //
   Debug.Log($"UserId: {session.UserId}");
   Debug.Log($"AuthToken: {session.AuthToken}");
   // add displayName to the player's account //
   await nakamaClient.UpdateAccountAsync(session, userName, displayName);
}

The important parameter here is the ‘create’ parameter passed in last to the AuthenticateEmailSync() method.

Setting this to ‘true’ lets us create an account on login, so we can use this same method for login without registration by setting this value to ‘false’.

/// <summary>
///  Logs a new user in given the username and password
/// </summary>
/// <param name="userName"></param>
/// <param name="password"></param>
private async void UserAuthentication(string userName, string password)
{
   Debug.Log("Attempting user authentication...");
   Debug.Log($"Username: {userName}, password: {password}");

   ISession session = await nakamaClient.AuthenticateEmailAsync(userName+"@mygame.com", password, null, false);
   // Now we can log out the session details //
   Debug.Log($"UserId: {session.UserId}");
   Debug.Log($"AuthToken: {session.AuthToken}");
}

We won't cover 3rd Party Authentication such as Facebook, Apple and Google in this topic, but you can check out our topic on those forms of authentication using Nakama here