Sites

Menu
These are the docs for 14.1, an old version of SpatialOS. The docs for this version are frozen: we do not correct, update or republish them. 14.3 is the newest →

Player authentication

The Player Authentication Service is in alpha and may have breaking changes before stabilizing. For more information on maturity stages see Maturity stages.

Introduction

You should authenticate players before allowing them to connect to your game. You can choose how to do this, and choose which deployments each player is allowed to join.

This scenario describes a simplified example of how to implement your own authentication backend server to grant players access to SpatialOS cloud deployments. It assumes that players are already authenticated in the system you’re using.

Find out how to download the Platform SDK from the setup guide.

You can find the full code example for this scenario on GitHub.

Note that the different stages of authentication are usually performed on different servers, but have been displayed together in the full code example to illustrate the authentication flow.

Example: granting players access to cloud deployments

1. Instantiate clients

Instantiate clients of the DeploymentServiceClient and PlayerAuthServiceClient types.

Use the Create method of the DeploymentServiceClient and PlayerAuthServiceClient.

private readonly DeploymentServiceClient _deploymentServiceClient = DeploymentServiceClient.Create();
private readonly PlayerAuthServiceClient _playerAuthServiceClient = PlayerAuthServiceClient.Create();

By default, it uses your refresh token saved locally by the SpatialOS CLI:

  • Windows: C:\Users\<username>\AppData\Local\.improbable\oauth2\oauth2_refresh_token\
  • Mac: ~/.improbable/oauth2/oauth2_refresh_token

If you want to provide a refresh token, you can instantiate a PlatformRefreshTokenCredential object and supply it to create:

var credentialsWithProvidedToken = new PlatformRefreshTokenCredential("my_refresh_token");
private readonly DeploymentServiceClient _deploymentServiceClient = DeploymentServiceClient.Create(credentials: credentialsWithProvidedToken);
private readonly PlayerAuthServiceClient _playerAuthServiceClient = PlayerAuthServiceClient.Create(credentials: credentialsWithProvidedToken);

Since the use case this scenario is describing is intended as part of your authentication server, we recommend using the refresh token of a service account. To create a service account, see Service account maintenance. You need to create one with at least read and write permissions on your project. See the permission page for details.

2. Create a player identity token (PIT) for a project

This assumes the player is already authenticated against your authentication system and has been given a player identifier. To create a PIT, you need to supply a provider, the player identifier, and the name of the SpatialOS project you want the player to be able to access. The returned response will contain an Improbable-trusted opaque token that must be sent to game clients for use when connecting to a deployment.

var playerIdentityTokenResponse = _playerAuthServiceClient.CreatePlayerIdentityToken(
    new CreatePlayerIdentityTokenRequest
    {
        Provider = "provider",
        PlayerIdentifier = "player_identifier",
        ProjectName = ProjectName
    });

3. Verify the player identity token (PIT)

You should perform checks to verify the details of the token before using it. Decoding a PIT validates that the token is signed by Improbable and returns the token’s provider, project name, time of expiry, time of issue, and player information. As a minimum, you should implement checks to ensure that the provider and project associated with the PIT match the expected values, and that the PIT has not expired.

var decodePlayerIdentityTokenResponse = _playerAuthServiceClient.DecodePlayerIdentityToken(
    new DecodePlayerIdentityTokenRequest
    {
        PlayerIdentityToken = playerIdentityTokenResponse.PlayerIdentityToken
    });
var playerIdentityToken = decodePlayerIdentityTokenResponse.PlayerIdentityToken;

if (playerIdentityToken.Provider != "provider") throw new Exception("Provider not recognised.");
if (playerIdentityToken.ProjectName != ProjectName) throw new Exception("Project not recognised.");
if (DateTime.Now.CompareTo(playerIdentityToken.ExpiryTime.ToDateTime()) > 0) throw new Exception("PlayerIdentityToken expired.");

4. Choose a deployment that the player is allowed to join

Next choose a deployment based on your selection criteria. For example, a player may be eligible for a public testing deployment. In this simplified scenario, we will just choose a deployment with a specific tag without checking the identity of the player.

var suitableDeployment = _deploymentServiceClient.ListDeployments(new ListDeploymentsRequest
{
    ProjectName = ProjectName,
    DeploymentName = DeploymentName
}).First(d => d.Tag.Contains("player_auth_tag"));

If you want to implement selection criteria specific to each player, you can use the decoded PIT and choose a deployment based on the player identifier contained within it.

5. Create a login token (LT) to grant access to a player to a given SpatialOS deployment

Now that you’ve chosen a deployment, you can create an LT for the game client to use to log in to the given deployment.

var createLoginTokenResponse = _playerAuthServiceClient.CreateLoginToken(
    new CreateLoginTokenRequest
    {
        PlayerIdentityToken = playerIdentityTokenResponse.PlayerIdentityToken,
        DeploymentId = suitableDeployment.Id,
        LifetimeDuration = Duration.FromTimeSpan(new TimeSpan(0, 0, 30, 0)),
        WorkerType = "UnityClient"
    });

6. Connect to the deployment using both PIT and LT

The game client requires both a PIT and an LT to log in to the SpatialOS deployment. In this step we are using functionality provided by the C# Worker SDK to log in.

var locatorParameters = new LocatorParameters
{
    PlayerIdentity = new PlayerIdentityCredentials
    {
        PlayerIdentityToken = playerIdentityTokenResponse.PlayerIdentityToken,
        LoginToken = createLoginTokenResponse.LoginToken
    }
};
var locator = new Locator(LocatorServerAddress, LocatorServerPort, locatorParameters);
using (var connectionFuture = locator.ConnectAsync(new ConnectionParameters
{
    WorkerType = ScenarioWorkerType,
    Network = {ConnectionType = NetworkConnectionType.Tcp, UseExternalIp = true}
}))
{
    var connFuture = connectionFuture.Get(Convert.ToUInt32(Defaults.ConnectionTimeoutMillis));
    if (!connFuture.HasValue || !connFuture.Value.IsConnected) throw new Exception("No connection or connection not established");
    Console.WriteLine($"Assigned worker ID: {connFuture.Value.GetWorkerId()}");
}

Search results

Was this page helpful?

Thanks for letting us know!

Thanks for your feedback

Need more help? Ask on the forums