HTML5 Zone is brought to you in partnership with:

Austin Hallock is a co-founder of clay.io, an app store for HTML5 games and a developer API for tedious features like payment processing, social integration, leaderboards, achievements, and more. He has worked on 4 games (thus far) using HTML5: three of them can be found here, and the fourth on his blog. Austin has posted 3 posts at DZone. You can read more from them at their website. View Full User Profile

Developing a Cross-Platform HTML5 Game: Part 3

05.31.2012
| 6936 views |
  • submit to reddit
This is the final part of a 3 part series on HTML5 game development tips. Part 1 covered visual and performance tips, part 2 was about input methods, and now I’m going to wrap it up with some tips for making your game secure.


Part 1: Getting the game to look great and run well across all platforms
Part 2: Handling the various input types of each platform
Part 3: Dealing with security for your game


Part 3 covers:

  • Obfuscation
  • Anonymous wrapper function
  • A backend for your game
  • Is it really necessary?


Since your JavaScript source code can be viewed by anyone, you’ll never be 100% secure with just a client-side solution. With that said, there are a couple things you can do to make hacking the game a bit harder.

Depending on the type of game you’re developing, there are various things you don’t want touched. These range from falsified leaderboard scores, to unlocking new levels, even playing the game if they haven’t paid for it.

Here are a few ways you can try to counter hackers:


Obfuscation

If you’re not familiar with it, obfuscating your code, basically just takes what you have, and make it hard to understand what the source means. Most tools do this by compressing the code, changing variable names to one-letter names.

As an example, this:
(function() {

var text = 'Hello World!';

console.log( text );
})();

Becomes:
(function(){var a="Hello World!";console.log(a)})()

With much more code, it makes it very difficult to read and understand what the program is trying to do. Understanding is the first step in hacking, so this helps prevent it a bit.

Unfortunately, this process can be reversed, and the result looks something like:
(function() {

var a = "Hello World!";

console.log(a);
})();

As you can see, the only difference between that and our original code is the variable name remains a instead of test. Obfuscation helps a little with security, but certainly not enough.

The process of obfuscation your code is fairly easy. We use UglifyJS and a Ruby rakefile to both compile all of our JavaScript files together, and compress/obfuscate them.

If you’re interested in using the system we have in place, use Ruby and this rakefile (here’s the coffeescript compiling version).

You’ll need Ruby installed, as well as RubyGems and the gems: rake, uglifier, and fssm. The Rake uses a manifest file formatted like so (just change it up to be all the file names you’re requiring):
//= require 'md5.js'
//= require 'core.js'
//= require 'tiles.js'
//= require 'input.js'
//= require 'main.js'
//= require 'timer.js'

Once all that is setup you can just use the rake watch command when in the main directory of your game, and any time a source file is saved, it will recompile the minified/obfuscated JavaScript file for you.

Have a look at our Slime Volley source code (where this is used) if you’re still confused.

There are many other ways to do this. Here’s a way to use UglifyJS online, and you can alternatively use YUI Compressor or Google’s Closure Compiler.

Anonymous Wrapper Functions

An easy way to manipulate an HTML5 game is by running some JavaScript code either by putting javascript: doSomething(); in the address bar, or running JavaScript from the console. If you have a client-side global variable that keeps track of the user’s score, all I have to do is put in score = 10000000; and I’m set...

By wrapping all of your code in a self-executing anonymous function, you’re able to prevent simple global variable altering (though, again, there are still ways around it).

(function() {
    // Your code goes here...
})();

In fact, that’s good practice to do regardless of if you care about your variables being edited (CoffeeScript compiles like this by default). It’s a good way to prevent your code from interfering with code from other libraries.

If you need to access global variables from within the anonymous function, just use window.variableName.


A Backend For Your Game

While the first two techniques can help make your game more secure, the only way to guarantee security (though security never really is guaranteed...) is by using some sort of back-end, server side to your game. Even if your game is a single player game, if you want things like high scores to not be falsified, you’ll need a backend.

For our games, we use a combination of node.js and Socket.IO. nowjs is another good option (it’s an abstraction layer above Socket.IO). You can use other languages like PHP or Ruby, but it just makes sense to have everything use JavaScript.

The purpose of a backend is to handle logic for the game. Typically this involves simulating the game (which again makes node.js the best choice), and using the scores the server produces rather than the client.

You might have to come up with some unique techniques in combination with the backend, so the best strategy is to sit and think about the optimal solution for a while before getting started...

As an example, for Word Wars we need the client-side to have all the possible words for the current board (so it can check against them and give points if it’s a valid word), however, if the client-side has all the words, it’s pretty easy for anyone to access them and easily cheat the game. One option would be to not send the list of words to the client, and instead send every entered word to the server to check if it’s valid. That’s very unnecessary and produces lag in the gameplay.

Our solution was to instead send the list of words, however, each word is encrypted (well, hashed...) with md5. With each new game we generate a new salt to hash the words with, and send both the salt and array of hashed words to the client. Then, whenever a new word is entered, we validate it by hashing the word they entered (using the salt we passed), and check it against the array of hashed words -- if it’s there, it’s valid. At the end of the game, we send the server all the words that were entered and check those against the possible words (again) just to verify the score.

In Action

Word Wars

Word Wars was initially called Worldle and was developed in 24 hours for a hackathon at the University of Texas by a couple of other students. Because of the time constraints for development, it was not secure at all.

The game got some buzz on HackerNews and almost immediately there was a greasemonkey script to hack the game (in addition to some crazy HTML & CSS injections since they weren’t escaping high scores).

They’re creators are some friends of ours, so we offered to polish up the game for them in addition to making it more secure. Since then we haven’t had issues with cheating (though, since the game is similar to Boggle, it isn’t immune to a Boggle-cheater where you enter the grid and it generates all possible words)

On Clay.io

We were posed with some interesting challenges when first developing Clay.io (an API that takes care of various game features like leaderboards & achievements): “What’s the best way to ensure secure transmission of data like game scores and achievements?”

Our solution was to use a similar approach to what Google uses for Google Wallet. Developers can generate a JSON Web Token (JWT) on their server, and send that to us from the client-side. Basically a JWT is a JavaScript Object that’s encrypted with a unique salt (in our case, the developer’s secret key).

This approach allowed us to keep the format for posting high scores and achievements relatively the same for games regardless of if they have a backend. Rather than use ( new Clay.Leaderboard( { id: 1 } ).post( { score: 50 } );, one would use ( new Clay.Leaderboard( { id: 1 } ).post( { jwt: jwt } );
You can read our full documentation on encryption here, and an example of our implementation in Slime Volley here.


Is this all really necessary?

Not exactly, but you’ll need it sooner or later. Less than an hour after the HTML5 version of Angry Birds was released, there was already a hack for getting all the levels.

On the other hand, if you’re in a rush to complete the game, you *might* be able to leave it out for the time being. As an example, I didn’t implement a backend at all for a game I released a little over a week ago. The game has received a pretty good response (including over 30,000 unique visitors and even a post on Kotaku), but to this point hasn’t had falsified scores submitted by anyone.


That’s it for this series on HTML5 game development tips, I hope this was helpful! You can follow what we’re doing at Clay.io on our blog, there’s a good chance we’ll have some more game development tutorials and tips there. If you’re developing a game and don’t want the hassle of developing features like achievements, leaderboards and payment processing, have a look at our API. Even if you’d rather do those on our own, consider adding your game to our cross-platform marketplace, it’s free and extremely easy! Our main goal is to help developers, so if you have any ideas for how we can improve, let us know!
Published at DZone with permission of its author, Austin Hallock.

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)