Saturday, October 24, 2015

security - How should multiplayer games handle authentication?


I've been lurking around to understand how an authentication system would work in games, but after many searches, it seems that working with ssl/certificates could be a little complicated for just a multiplayer game with a lot less capacity than an MMO.


I know that successful multiplayer games need this, but I'd like to check if other multiplayer games commonly take this precautions.


EDIT: I'll describe what I have in mind. The server not only handles game logic, but also authentication. So, in order to play on a specific server (that everyone could start), you first need to register an account on the server, and each time you want to play there, login as usual (password/name user).


My question is, would not providing a secure channel for logging in/registering an account be forgivable/understandable in this context? Also I'm interested to know how games with a similar architecture would handle this matter.




Answer



Specifically regarding the last bit of your question: No, it is never forgivable to have an insecure authentication system. Users are rarely enlightened when it comes to computer security. Users use the same password for your little game as they do for their Google account, Facebook account, bank account, and so on. Even if you can claim that it's their fault for using poor Internet security habits, you're the one who will be held responsible if your game is used as an attack vector to steal users' login credentials. As a developer who knows better, the only ethical options are to properly secure your authentication process or to not have one at all.


As some unsolicited but related advice, users don't want to be required to sign up for your game anyway. They might do so if they want to play your game badly enough, but having Yet Another Freaking Login to sign up for is going to just drive away many potential players. Users are sick to death of making a new account for every single site, service, and game out there, especially if they require any kind of email validation or the like. If you can, either avoid having a login at all, or use an existing third-party authentication service that users likely already have an account with. You will have more players that way. This goes triple if you plan on having any kind of in-app purchases.


Web Games


A popular option -- particularly for Web games, though it also works for traditional games -- is to use a Web-based third-party authentication service. Facebook and Google both have well-documented APIs (both based on standardized APIs, iirc) for authentication. They do require the ability to open a browser window and direct the user towards their services, but this is pretty easy to do on most non-console platforms, and of course trivial for Web games.


Those services take care of all the messy details of encrypting login traffic over the wire, securely storing login credentials, and validating user logins. Your game server then needs only implement the portion of the protocol that receives a cookie from the user and asks the authentication service if the cookie is valid or not, which can be done with a simple HTTP in most cases.


I won't claim most traditional multiplayer games do this, because they don't, but I will claim that most online casual Web games do this.


For traditional (non-Web) games, facilitating this login procedure is possible by either embedding a browser (Awesomium, Chromium Embedded Framework, or straight up Webkit being popular choices) or by calling out to an external browser (this takes some more fanagling to get the auth cookie out of though, and isn't really any easier than embedding one of the aforementioned libraries).


A typical example of this approach is any Facebook game.


Traditional Games using HTTPS



Having a simple HTTPS service for login is increasingly normal. Many games use custom protocols, but most of these are incomplete (they have secure login, but no secure way to create/update an account, so they need the HTTPS service anyway) or are simply horrifically insecure.


You don't even need to go about getting a custom SSL cert. There are online app hosting providers that give you a subdomain and use a wildcard SSL cert. You can put your authentication service at mygame.someservice.com, which is covered by the *.someservice.com wildcard cert that Some Service maintains, and you're good to go.


The idea here is that the user logs in to your service, which generates a unique session cookie, which the user can then pass into your main game server. The server then asks the login system if the cookie is valid for the requested user. There's usually a very short timeout on the cookie, on the order of seconds (15-30, for example), and it's generally invalidated once used, making replay attacks impossible.


Note that HTTPS is my most recommended option if you plan on sending payment information over the wire from inside the client itself. However, it's significantly better to use a third-party for this. If you think securing something as simple as a password is too much work, you don't even want to even think about trying to meet the minimum (and honestly quite inadequate) PCI compliance rules for storing and processing credit card numbers. You'll have better sales uptake anyway if you have users use trusted third-party payment services that they're already on file with.


One strong advantage of separating your login service from the main game server is that it allows external functionality to be tied to user accounts independent of the game. You might have some account features (viewing avatars or such) on your website, or perhaps you allow linking Facebook accounts into your accounts, or perhaps you have multiple games sharing a single underlying account platform (e.g., the Galaxy at War features of Mass Effect 3).


A popular example game using HTTPS for authentication is Minecraft.


Third-Party Web Authentication with Native Client Games


It is possible to use third-party services like Facebook Connect or Google with a native client. Facebook for example has a native SDK for iOS and Android, as does Google. Some services likewise have native SDKs for traditional PC clients.


If the target service does not having a native SDK and requires the use of a Web browser, you could just embed a browser in your game. However, some users may be distrustful of using an embedded browser to enter login information.


You can also use an external browser. There are a few ways to pull this off. Some require a little bit more OS-integration than others. Some require you to have an external Web service running alongside (or at least reachable by) your main game server. Note that since Facebook and Google generally require a URL that is authenticated, you will need a public website landing page to use these protocols in (almost) all cases.



The most fool-proof and reliable, if not quite the easiest, is to bounce your login request from your client through your main website. Your client connects to the main game server as an authenticated guest user and receives a unique session token. The game server does not allow the client to actually do much while in this state; the game doesn't know who the player is, so the player cannot yet chat, start a match, or so on.


The client then launches the external browser pointing at the login URL of your game's domain, passing this session token as a parameter in the URL. The site then goes through the usual login handshake for Facebook/Google.


At this point, your webserver knows that the user has logged in, and can associate that with the session token it received from the client. This verification can then communicated to the game server, elevating the client's unauthenticated guest connection into an authenticated user session. This can be done by having the webserver directly communicate with the game server, if possible. Or the game server can periodically poll the webserver for authentication status of pending guest connections. Or the client can periodically poll the webserver to see if login is complete and, when it is, signal the game server to request verification from the webserver.


All of these require that your game server and webserver be able to communicate, but any third party authentication service will require your game server to be able to communicate with the outside world, so this shouldn't be a surprise.


This authentication method is found in some small-to-mid-sized MMOs.


Note that this all also works for making payment requests through an external service, like PayPal, Amazon Payments, Google Wallet, etc.


Direct TLS Connection


It is not too difficult to start a TLS session over a custom stream protocol. Libraries like OpenSSL, GnuTLS, NSS, and various OS-specific libraries provide a stream wrapper API that layers over a low-level transport/protocol. You generally just need to feed bytes through the wrapper API and it deals with the handshake and encryption.


The tricky parts here are ensuring your use of TLS is safe. Some of the common libraries for example will by default require a valid signed certificate from a trusted authority. Some of the common libraries require that, but by default don't trust any authorities. Some of them do not require that the cert be valid at all.


It is recommended that you always require a valid cert. Allowing invalid certs will not allow an attacker who is merely eavesdropping to steal a password, but it will still allow man-in-the-middle attacks.



This approach requires the absolute least in terms of external dependencies while still allowing maximum security.


Examples of games using this now include most big traditional MMOs.


Secure(ish) Traditional Games


Games that don't use a separate service and don't use TLS typically have to implement some kind of nonce-based login protocol in their main game protocol. With this method, the server generates a random number (a nonce) and sends that to the client. The client then hashes that nonce with the user's password (and username, possibly some other data) and sends that response to the server. The server then compares this hashed value with the credentials it has on file. This keeps the user's password secrete over the wire and ensures that you can't use a simple replay attack on the hashed password, like many other weak hash-based login schemes.


A problem is that the user has no way to submit a new password to the service over this protocol securely. Typical implementations also store the user's password in plaintext on the server, which is a horrible practice (if your server gets hacked, your user probably just had his email/facebook/bank password stolen, because he was using the same password for your game as everywhere else, because users tend to do that).


There are enhanced versions of that basic login scheme. The most basic -- though still not ideally secure -- is for the server to send the password hash salt with the nonce value during login. This allows the server to stored a hashed (and salted) password securely while allowing the client to generate the same hash during login. This does allow an attacker to get the salt for a particular user's password, but this is not particularly useful without also getting the original hashed password (which is not sent over the wire during login). During creation/updating of the password, the client sends the whole hashed password (with salt), which the attacker can sniff. If the hash function used is strong enough (say, sha-2/512) then pure brute forcing is not feasible, though the attacker can still easily brute-force weak passwords (which is why enforcing some minimum password length, minimum distribution of letters/numbers/symbols, and comparing to a dictionary of known/obvious/weak passwords is important). The fact that the attacker can still get the hashed password is why it still more secure to do the entire password exchange over a secured, encrypted channel.


A number of popular game networking libraries implement some optional form of this protocol. I believe SmartFox is one such example, though I haven't looked at it in depth (I generally ignore any such library auth system and use the HTTPS method, since it's dead simple to implement and significantly stronger). A number of early non-Web Internet games also used this approach, particularly before Steam, XBL, and so on came around.


Unsecure Traditional Games


A lot of games unfortunately just send a username/password in plaintext. Maybe they hash the password, which vaguely kind-of protects the users actual password (not nearly well enough) but a replay attack makes logging into the game service trivial.


Don't do this. It's irresponsible and lazy. The Internet naiveté of the 1990's that popularized these login methods is no longer a viable excuse.



Many early pre-Facebook Flash and web games took this approach. I don't know of any specific examples off the top of my head; I'd like to believe they're all long dead, but the world just isn't that lucky.


No Authentication


Most games just don't do authentication. The player connects, sends over some handle to uniquely identify himself, and a match starts. There is no global server that tries to validate that only one real human is ever allowed to claim to be "CaptainMisterDude". The local server just ensures that only one currently connected player has any particular handle, and that's the end of it. Local servers use name-based and IP-based blacklisting for trouble makers. This is common for FPS deathmatch style games even today.


If you don't need any permanent state for accounts, this is by far the easiest solution, and quite "secure" since there's nothing there to actually hack or steal. Obviously this doesn't work too well if you do need to store account information between game sessions.


Quake is an example of a game using this method of "authenticating" users.


No comments:

Post a Comment

Simple past, Present perfect Past perfect

Can you tell me which form of the following sentences is the correct one please? Imagine two friends discussing the gym... I was in a good s...