Mitigate the risk of abuse of your game service
To defend your game system from bad actors, use the techniques described in this topic. These techniques can help you mitigate the risk of bad actors injecting bad data or overloading the system.
This topic describes the following:
- The two powerful API functions that you can use to apply restrictions to any service.
- How you can use these functions to mitigate abuse of leaderboards and challenges.
Spark.setScriptError() and Spark.exit()
In this section, you'll learn how to block an abusive use case by calling:
Spark.setScriptError()
to block a GameSparks operation from continuing.Spark.exit()
to stop the rest of your script from running.
For example, to block a user from creating a new player with a userName
of "bad-actor"
, you can implement these API calls in your RegistrationRequest Cloud Code script:
var userName = Spark.getData().userName
// If this is an abuse use case...
if(userName === "bad-actor") {
// Block creation of the new player and return an error message
Spark.setScriptError("error", "The attempt to create 'bad-actor' player was blocked.")
// Warn that some "importantData" was not loaded
Spark.setScriptData("importantData", "Warning: 'bad-actor'!")
// Stop running this script
Spark.exit()
}
// Store our "importantData"
Spark.setScriptData("importantData", "Our game rocks; try it!")
// More of your custom code runs after here
// ...
Try it!
To see the above code in action:
In the GameSparks console in your web browser, move your mouse pointer over Configurator in the left navigation panel, and then choose Cloud Code.
In the Scripts panel, expand the Requests folder, and then choose the RegistrationRequest Cloud Code script.
Copy and paste the above example into the Cloud Code editor, and then choose to save and close.
In the navigation panel, choose Test Harness, and then choose Authentication -> RegistrationRequest.
Copy the following code into the JSON box, and then choose Send Request.
{ "@class": ".RegistrationRequest", "displayName":"Bad Actor", "password":"", "userName": "bad-actor" }
The response demonstrates that you blocked the attempt to abuse this service.
{
"@class": ".RegistrationResponse",
"error": {
"error": "The attempt to create 'bad-actor' player was blocked."
},
"newPlayer": false,
"scriptData": {
"importantData": "Warning: 'bad-actor'!"
}
}
Explanation
Spark.setScriptError()
is typically used to communicate an error to the player when something goes wrong or when they try to do something unsupported in the game.
In the case of a bad actor attempting to abuse your game service, you can use the function to block the operation.
Spark.Exit()
is handy for terminating your script when fatal errors occur.
In this case, you call the function to block a bad actor from executing subsequent lines of code in your Cloud Code script.
Prevent Abuse of Leaderboards
In this section you'll learn how to check and block invalid scores from being posted to your leaderboard.
Create an Event to Submit a Score
In the GameSparks console in your web browser, point to Configurator, and then choose Events.
On the Events page, choose Add, and then define the
postScore
event:- Short Code:
postScore
- Name:
postScore
Description:
postScore
Choose Save.
- Short Code:
On the right side of the Attributes panel, choose Add, and then define the
score
attribute:- Short Code:
score
- Name:
score
- Data Type:
Number
- Default Value (leave it empty)
- Default Aggregation Type:
Maximum
- Short Code:
Choose Save and Close.
Create a Leaderboard
Point to Configurator, and then choose Leaderboards.
On the right side of the Leaderboard page, choose Add, and then define the
leaderboard
leaderboard:- Short Code:
leaderboard
- Name:
leaderboard
- Description:
leaderboard
High Score Notification: ON
(Leave all other options on their default settings.)
- Short Code:
In the Fields panel, choose Add to add a new running total to your leaderboard. Specify the options:
- Running Total:
postScore
- Collector:
postScore.score-all
- Filter Type:
*
- Filter Value: (leave it empty)
- Sort:
DESC
- Running Total:
Choose Save and Close.
Block Invalid Score Updates
To assert, for example, that leaderboard scores over 1,000
are invalid, add a LogEventRequest
Cloud Code script:
In the GameSparks console, point to Configurator, and then choose Cloud Code.
Expand the Requests folder, and then choose LogEventRequest.
Copy and paste the code below into the script, and then save and close.
// LogEventRequest
// Block scores over 999
if(Spark.getData().eventKey == "postScore" && Spark.getData().score > 1000 ) {
// block the invalid leaderboard update and return an error to the client
Spark.setScriptError("error", "Score cannot be higher than 1,000!")
// block the invalid update from causing any other operations to occur
Spark.exit()
}
Try it out!
To test your leaderboard validation script and see it in action, choose Test Harness.
Authenticate as a player:
{
"@class": ".DeviceAuthenticationRequest",
"deviceId": "test",
"deviceOS": "",
"displayName": "testUser"
}
Post a valid score update:
{
"@class": ".LogEventRequest",
"eventKey": "postScore",
"score": 100
}
The system returns a NewHighScoreMessage
.
Now try posting an invalid score update:
{
"@class": ".LogEventRequest",
"eventKey": "postScore",
"score": 1500
}
The system blocks the leaderboard update and returns your error message.
Note The
LogEventRequest
Cloud Code script will be executed for every custom event that the game sends.
You can check which event is currently being executed with Spark.getData().eventKey
.
Knowing this you can place validation logic for multiple custom events in this one script.
Prevent Abuse of Challenges
Challenges can make your game more fun by giving players some control over how they compete in your game. To block bad actors from abusing this capability, add Cloud Code scripts to enforce reasonable boundaries on how and when challenges can be created.
We recommend that you add code to CreateChallengeRequest
to block abusive behavior such as:
- Overloading the system with too many challenges at one time.
- Creating challenges with too many players.
- Running a challenge for too long.
Configure the Challenge
Begin by configuring the challenge.
Point to Configurator, and then choose Challenges.
On the right side of the Challenges page, choose Add, and then define the
testChallenge
challenge:- Short Code:
testChallenge
- Name:
testChallenge
Description:
testChallenge
(Leave all other options on their default settings.)
- Short Code:
Choose Save and Close.
Limit How Frequently a Player can Issue a Challenge
For example, you want to block each player from issuing a challenge more often than once per minute.
In the GameSparks console, point to Configurator, and then choose Cloud Code.
Expand the Requests folder, and then choose CreateChallengeRequest.
Copy and paste the code below into the script, and then save and close.
// CreateChallengeRequest
// check for the last time the player created a challenge
var lastCreatedChallengeTime =
Spark.getPlayer().getPrivateData("lastCreatedChallenge");
var now = new Date().getTime();
if (lastCreatedChallengeTime !== null) {
var lastCreatedChallengeDif = now - lastCreatedChallengeTime
// if the player created a challenge in the last 60 seconds, block the
// new challenge creation.
if(lastCreatedChallengeDif <= 60000) {
var waitTime = (60000 - lastCreatedChallengeDif) / 1000
Spark.setScriptError("error", "challenge creation limit reached. please
try again in "+ Math.round(waitTime) +" seconds");
Spark.exit();
}
}
// Additional challenge creation validation checks go here!
// on successful challenge creation set the current time to the players privateData
Spark.getPlayer().setPrivateData("lastCreatedChallenge", new Date().getTime());
Try it out!
To test your challenge frequency limitation script and see it in action, choose Test Harness.
Authenticate as a player:
{
"@class": ".DeviceAuthenticationRequest",
"deviceId": "test",
"deviceOS": "",
"displayName": "testUser"
}
Issue a challenge by sending this request:
{
"@class": ".CreateChallengeRequest",
"accessType": "PUBLIC",
"challengeShortCode": "testChallenge",
"endTime": "2020-09-17T00:00Z",
"maxPlayers": 32,
"minPlayers": 2,
"startTime": "2020-09-16T00:00Z"
}
The system responds with a challengeInstanceId
, indicating that you you successfully issued a challenge
{
"@class": ".CreateChallengeResponse",
"challengeInstanceId": "5f60c3195801912d385dae96"
}
Before 1 minute passes, issue another challenge by sending the above request again. This time the response is something like:
{
"@class": ".CreateChallengeResponse",
"error": {
"error": "challenge creation limit reached. please try again in 50 seconds"
}
}
Limit the Number of Players in a Challenge
For example, you want to limit challenges to no more than 32 players:
// CreateChallengeRequest
// maxPlayer check
var maxPlayers = Spark.getData().maxPlayers
if(maxPlayers > 32) {
Spark.setScriptError("error", "maxPlayers must be 32 or less");
Spark.exit();
}
Limit the Length of a Challenge
For example, you want to block players from issuing challenges that last longer than 30 days:
// CreateChallengeRequest
// challenge time length check
var startTime = new Date(Spark.getData().startTime).getTime();
var endTime = new Date(Spark.getData().endTime).getTime();
var startEndDif = endTime - startTime
if (startEndDif > 2592000000) {
Spark.setScriptError("error", "endTime must be within 30 days of
startTime");
Spark.exit();
}
More Tips & Tricks
For more tips and tricks to build robust and scalable games, see this.