This guide takes you through some of the things to think about when integrating a third-party
service into your SpatialOS game. For an example of what this looks like in
practice, see the Playfab integration guide.

Workers are just normal programs

In general, a worker is just a normal program that connects to SpatialOS at some point
of its lifecycle (usually when it starts). It then receives updates from SpatialOS, and
the worker can choose to do whatever it likes with those updates.

When creating a worker, or using one of the existing worker SDKs, you can choose when
the worker connects to SpatialOS, you can create other threads to perform other tasks,
you can make any HTTP requests you like and you can use any third-party SDK like normal.
SpatialOS doesn’t aim to restrict you to a closed ecosystem of services.

There are however, a couple of things you need to be careful about:

Don’t block on any SpatialOS callbacks

For example, you may want to trigger a RESTful
or gRPC API request when a component value
changes. You need to make sure that this request is asynchronous and does not block the
callback thread.

A good practice would be to add tasks to a queue in the callbacks, then have other
consumer tasks processing the queue, performing longer tasks with the data.

Not blocking on the callbacks can also help prevent any deadlocks appearing in the
callbacks. A deadlock could prevent the worker from processing updates from SpatialOS.

Managed workers should connect to SpatialOS as soon as they start

In order to load balance, SpatialOS can dynamically adjust the number of workers required
for a task. This means it needs to be able to spin up and tear down managed workers
quickly. To facilitate this, managed workers should connect to SpatialOS quickly
after starting.

External workers however, for example a client, can connect to SpatialOS whenever they
like. For instance, you may want to have an OAuth flow or a traditional game lobby
before you connect to SpatialOS.

Storing secret keys

Often a third-party service will have secret API keys that are sent with the requests from the server side.

It’s very important that the binaries you send to the players do not contain these secret
keys. For example, if you are using the Unity SDK, the UnityClient and the UnityWorker are
both compiled from the same codebase. This means that any string you have in that
codebase will be compiled in with both the UnityClient and the UnityWorker. Therefore,
if you store a secret key as a constant, a player could decompile the client and
retrieve this secret key.

Alternatively, you could use a compilation flag to only compile the secret key with
the managed worker codebase.

Authenticating players

Typically, a third-party service would have endpoints for the client to authenticate the player,
and possibly read player data, update some player state etc. The service would also have endpoints
for the server which has full authority to change state about the game, or state about any player.

The server will typically identify the player by some player ID which is obtained during the
authentication procedure. The server can then send this player ID when it makes requests to
the service.

In SpatialOS, the external worker can authenticate the player (for example, by logging in). Data
identifying the player can then be sent to the managed workers and can be kept in a component on
the player entity.

It is really important that the player ID in the player’s component is the correct player ID for
that player, as if they could change it, they can effectively play as a different player. There
are two ways a player could give the false player ID:

The client could modify the player ID component value

It is important to assume that the client can be hacked, and they can change any component
which they have authority over. For this reason, you need to have the managed workers authoritative
over any components identifying the player.

The client could send a false player ID to the managed workers initially

When the client logs in to the third-party service, it will receive data identifying the player.
This data can then be sent to the managed workers in order to identify the player when making
server side requests during the game.

Often, data such as the player ID can be easily fabricated or changed, they could even be
public for each user. This means a client could be hacked to send over a different player
ID when the player entity is spawned, allowing them to play as another user.

To prevent this, you need to send authentication data from the client to the managed
workers which cannot easily be fabricated. Many third-party services will have systems like
session tickets for this. The client can then send over a ticket generated at login, and
then the managed workers can use a server side endpoint to verify the given ticket and
get back the correct player data. This is the method used in the Playfab integration guide.