GMCloud and GameMaker Part 3: Linking Player Accounts/Player Logins

Yuan Gao (Meseta)
6 min readJan 9, 2019

--

Thus far the tutorial has covered how to set up your game to be able to connect to GMCloud in Part 1; and how to get game configs in Part 2. The next step is to allow players to log into your game. Only when a player is logged in can they access features such as cloud saves.

Privacy is a big deal on the internet, and not all of us use unique usernames/emails and passwords for all the accounts that we own. This has given rise to the underground trade of leaked usernames and passwords from insecure sites, which nefarious individuals can then try to re-use with high-risk sites like email accounts and bank logins to try and see if someone has made the unfortunate choice of re-using the same password everywhere.

As a result, to avoid the risk of leaked emails/passwords, GMCloud does not require a game developer to actually store or ever handle their players usernames and emails. Instead, GMCloud uses a token system.

How GMCloud’s token system works for logins

Instruct your player to sign up for an account on GMCloud’s website, and create an access token:

Clicking on the big “Create a new access token” button generates a 6-character token:

This access token is a single-use, time-limited pass that the player can hand out, which says “I trust the recipient of this token to link to my account”. It can only be used once, and it expires after a few hours.

Next, the player types these 6 characters into the game (we assume for now that the game developer has already followed this tutorial and has provided the facility to do so).

The game now has the player’s access token as a symbol of trust and friendship. It can approach GMCloud server, along with its own API key, and say to GMCloud “By the power of this token, I have gained a player’s trust and friendship, please o wise one, link me to the player’s account”. (It’s worth noting at this point the game doesn’t actually know which player has just tried to log in, it only has the 6-character access token)

GMCloud checks the token is ok, and generates a new random link ID and random link secret and attaches it to the player’s account. GMCloud now replies to the Game “come, worthy one, I acknowledge that you have indeed gained the trust of a player, take this as a symbol of your everlasting friendship”, and sends the new link Id and link Secret.

The Game now stores this link Id and link Secret in a file. As you may realise, this link ID and link Secret is in the same format is in the same format as the game’s API token ID and Secret, and works similarly to a username and password. But importantly, this is not the user’s personal email and password, and it can only be used to access the user’s data for this specific game. (It’s worth noting that at this point the game still doesn’t know which player has been linked. It needs to use the link Id and Secret to fetch the player’s profile to see the user’s display name)

Now that the Game has the player’s link ID and Secret stored, at any point, it may use it, together with its own API token ID and Secret, to interact with the player’s data. And the player can at any time revoke the link and secret from their account. If the game approaches GMCloud with a revoked link, GMCloud will deny access.

The player may register as many tokens with the server as they like, this is necessary when playing on multiple devices as each device needs its own link.

This tutorial describes how to link player accounts to your game so that they can log in and access their game saves and other features of GMCloud. It assumes you’ve set up your secrets and the gmcloud_handler in Part 1; and read and understood the methods described in Part 2.

Step 1: Collect access token from player

Use some method of your devising to collect the 6-character access token from the player. The simplest way to do this is to use:

var token = get_string("Enter access token", "");

There are issues with using this function (see the documentation pages), but for the purpose of demonstration and testing, this will be fine.

Step 2: Make the request for a link

As with all GMCloud interactions, sending the request is as simple as calling the function and storing the request uid, making sure not to repeatedly call this function unnecessarily.

uuid = gmcloud_link_account(token);

(See Part 2 to understand the details of how this works)

Step 3: Check for and fetch the result

As with in Part 2, check and fetch the result, using whichever method suits your game.

if (gmcloud_result_exists(uuid)) {
var result = gmcloud_result_pop(uuid);
// ... do something with result
}

Step 4: Parse the result

The result from the server is JSON encoded, and will have the keys “linkSecret” and “linkId” for use later. The easiest way to deal with this is to simply json_decode it, and send that map straight to ds_map_secure_save

if (gmcloud_result_exists(uuid)) {
var result = gmcloud_result_pop(uuid);

var data = json_decode(result);
// ... optionally store data[? "linkId"]
// and data[? "linkSecret"]

ds_map_secure_save(data, "link.data");
ds_map_destroy(data)
}

Important note on ds_map_secure_save: this function doesn’t provide any encryption, so the stored data file on the user’s computer is relatively easy for someone to read. Ideally a more secure way of storing this information is used, however bearing in mind that the link ID and link Secret does is not useful for any purpose other than accessing the player’s game data.

That’s it! Once you have the linkId and linkSecret from the server, and have saved it for later use, they can be used to access player data like cloud saves, or grabbing the user’s profile.

By saving the details, the player won’t have to go through this linking process every time they want to log in — the game is effectively logged in permanently until either the game deletes the saved linkId or linkSecret; or the player revokes the link from their account from the website. Consider the act of storing and later restoring the linkId and linkSecret as an “autologin” mechanism. You can additionally save multiple links to support multiple players using the same computer, you would need to build your own profile selection system.

Take a look at the demo object included in the GMCloud marketplace asset for some additional examples of the implementation.

In Part 4, we’ll use this newly acquired link to grab a user’s profile, including their displayName

Tips for error-checking the result

Ideally do not trust results that you get back from the server. There are all sorts of conditions, whether just due to the weird way the internet fails sometimes, or because of bugs, where the result is not what we expect. In the above example, the result data goes straight into a json_decode, and then we immediately assume that succeeded and we can access the data.

A few ways to do this are:

Always check json_decode succeeded

json_decode returns -1 if it fails, this is an easy way to make sure the incoming data was valid JSON, which will account for most issues — the chance of the return data being valid JSON by accident is extremely low

var data = json_decode(result)
if (data != -1) {
// ... do stuff
}
else {
// there was an error
}

Check the decoded map has the right keys

To protect against errors caused by keys being missing, it’s wise to check for them explicitly before trying to use them:

if (ds_map_exists(data, "linkId"))

It’s also acceptable to test for an undefined value when accessing

if (data[? "linkId"] != undefined)

On to Part 4!

--

--

Yuan Gao (Meseta)
Yuan Gao (Meseta)

Written by Yuan Gao (Meseta)

🤖 Build robots, code in python. Former Electrical Engineer 👨‍💻 Programmer, Chief Technology Officer 🏆 Forbes 30 Under 30 in Enterprise Technology

No responses yet