

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.


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.



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();


  • Mac: ~/.improbable/oauth2/oauth2_refresh_token


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, cloud 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 listDeploymentsRequest = new ListDeploymentsRequest
    ProjectName = ProjectName,
    Filters = {new Filter
        TagsPropertyFilter = new TagsPropertyFilter
            Tag = "player_auth_tag",
            Operator = TagsPropertyFilter.Types.Operator.Equal,

var suitableDeployment = _deploymentServiceClient.ListDeployments(listDeploymentsRequest).First();

The ListDeployments RPC returns a page that lists 20 deployments by default at a time, and the maximum size is 50 deployments. You can use the optional parameter PageSize in the ListDeploymentsRequest to decrease or increase the number of deployments returned on each page fetch.

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.ToString(),
        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