Sign in to follow this  

Web API for a turn based game?

Recommended Posts

Posted (edited)

Hi,

Wow. I haven't been here in a long time, and it's crazy to see this forum still thriving and people like hplus still around helping people.

I am working on a prototype for a multiplayer mobile card game using Unity. I'm trying to finalize some architecture decisions. I was thinking of building the server as a Web API (using ASP.NET MVC) and having the client basically just GET and POST when needing to communicate with the server.

I was wondering if people are using WebAPIs in commercial games and how sane of an approach this seemed. Since the MVP will not even support interacting with other players in real-time, it seems like this is going to be the simplest solution rather than creating a state based game server.

Later, when we started adding features like 2 players being able to play against each other, I was thinking we could add a stateful game server at that time. Then, when players wanted to play against each other, the web server would do a hand off to the stateful game server 'players with ID x,y and session Id Z want to begin a match'. The game client would then connect to the stateful game server which would now be warmed up and ready to manage that interaction. This would accomplish 2 goals, 1) allow me to build only the bare minimum needed for the given requirements at a time 2) organically grow the server side as requirements are added 3) reduce the load and complexity on the servers so that they have a minimal amount of responsibilities. The service that does game logic doesn't need to manage friends lists and players news feeds.

Any feedback on this approach?

Thanks for the input!

Edited by graveyard filla

Share this post


Link to post
Share on other sites
Yes, there are games that use web APIs.

Games where this works really well are games like Farmville or Backyard Monsters or such, where the player really is only doing their own thing, and the only need for the back-end is to validate what the player has done, record the state of started work/timers, and such.
If you are doing interaction with other users, POST/GET is a little more iffy. You CAN build a reasonably real-time system based on long polling ("comet" style with AJAX) if you have the ability to suspend a current request on the server, and unblock/return it once there's data, or once enough time has passed (10 seconds or whatever.)
However, this is, shall we say, decidedly "ghetto" networking, and the crossbar to figure out "what is there for this user" and then getting that information to the appropriate server where the user's request is waiting to be unblocked is fragile, and full of race conditions.
If your game is small enough to only ever need one server, then the "A did a thing, so B needs to know about it" isn't so bad, but when you scale across multiple machines, HTTP gets in the way something fierce.
In fact, you're probably better off to just chuck the game state and outgoing messages into a database, and have the user poll every 5 seconds, and polling will return whatever was sent in the last 30 seconds, and purge anything older than that, from the database.
This is highly inefficient, and delays all incoming messages by 5 seconds, but at least it can be made robust.

If you have to run in a web browser, I would suggest perhaps web sockets (something like socket.io) because there at least you have a persistent connection to the server, and thus the mapping from "user id" to "server that currently knows how to send data to that user" can be somewhat less ephemeral.
You'd have some registry of where the connection for each user is, and some ability for processes on different machines (or just different processes on the same machine) to find each other.
Erlang is great for this, btw, but if you have to do it in C#, then that can be done.

If you're building a native client (PC game, console, or mobile,) then you're probably slightly better off just using TCP, or, if timing is super important, using UDP with some method to deal with unreliable messages.
The web stack makes it possible to build highly scalable infrastructure if your goals are de-centralized document editing/access, large document transfers, and high latency updates.
Games have different goals.

Share this post


Link to post
Share on other sites
Posted (edited)

hi hplus! I don't know if you remember me or not.. I was a big time user of this forum a decade ago and learned A LOT from you personally here in the multiplayer forum. I have since been a developer in the business space and am now finally returning to games. I just wanted to say thank you for all the help you gave me all those years ago. It truly made an impact in my life.

"Games where this works really well are games like Farmville or Backyard Monsters or such, where the player really is only doing their own thing, and the only need for the back-end is to validate what the player has done, record the state of started work/timers, and such."

This sounds very much like the requirements of the MVP of my game. The client just needs to have an authoritative server to tell it which cards it owns, which decks it has, send it the resources for those decks, social aspects (friends lists, news feed, eventually it would have messaging), etc.

Once the MVP is proven, we would add a 'VS' mode where 2 players could interact with each other in a turn-based way.

Back in the day when I was learning about the architecture for MMOs here, I remember what you had told me about how it worked at the game you were building at that time, I think it was Second Life? You had told me the best architecture is to have distributed services. I have found that to be true in the business world as well.

I was thinking that a good approach to tackling this problem is to start off with a simple web server, and then later, when 2 player VS mode was needed, expand into a TCP connection / stateful game server using some sort of methodology like RPCs or such. UDP wouldn't be needed here as the game is nowhere near real-time and there are no physics interactions in the game outside of animations and such which can be run client side as they don't impact the state of the game and so don't require server authorization.

This approach seems like it would allow me to organically grow the application as needed as well as distribute the work to separate services which would hand over sessions to each other behind the scenes. The Web API could tell the stateful game server a session was coming his way and the clients could then connect with their session ID's to a warmed up game server.

Do you think this approach would lead me to paint my self in a corner, or does it seem sane? I don't want to build a stateful game server from the beginning as it may be overkill. The MVP may not even take off, or it may take off in a different direction altogether and it seems easy enough to add stateful ness later. But, I've only been back in game development for 6 months now, and haven't done serious networking in a game yet since 10 years ago...

Thanks again man!

 

 

 

 

Yes, there are games that use web APIs.

Games where this works really well are games like Farmville or Backyard Monsters or such, where the player really is only doing their own thing, and the only need for the back-end is to validate what the player has done, record the state of started work/timers, and such.

If you are doing interaction with other users, POST/GET is a little more iffy. You CAN build a reasonably real-time system based on long polling ("comet" style with AJAX) if you have the ability to suspend a current request on the server, and unblock/return it once there's data, or once enough time has passed (10 seconds or whatever.)
However, this is, shall we say, decidedly "ghetto" networking, and the crossbar to figure out "what is there for this user" and then getting that information to the appropriate server where the user's request is waiting to be unblocked is fragile, and full of race conditions.
If your game is small enough to only ever need one server, then the "A did a thing, so B needs to know about it" isn't so bad, but when you scale across multiple machines, HTTP gets in the way something fierce.
In fact, you're probably better off to just chuck the game state and outgoing messages into a database, and have the user poll every 5 seconds, and polling will return whatever was sent in the last 30 seconds, and purge anything older than that, from the database.
This is highly inefficient, and delays all incoming messages by 5 seconds, but at least it can be made robust.

If you have to run in a web browser, I would suggest perhaps web sockets (something like socket.io) because there at least you have a persistent connection to the server, and thus the mapping from "user id" to "server that currently knows how to send data to that user" can be somewhat less ephemeral.
You'd have some registry of where the connection for each user is, and some ability for processes on different machines (or just different processes on the same machine) to find each other.
Erlang is great for this, btw, but if you have to do it in C#, then that can be done.

If you're building a native client (PC game, console, or mobile,) then you're probably slightly better off just using TCP, or, if timing is super important, using UDP with some method to deal with unreliable messages.
The web stack makes it possible to build highly scalable infrastructure if your goals are de-centralized document editing/access, large document transfers, and high latency updates.
Games have different goals.

Edited by graveyard filla

Share this post


Link to post
Share on other sites
Welcome back. Yes, I remember. Time flies :-)

If all you're doing is friends lists and deck management and such, then a web API seems totally fine.
Once you get to versus mode, the ability to notify other people quickly becomes more important, and traditional web APIs fall down. Websockets are still OK for this for many use cases.
If your game is popular, then the web API would presumably even let your players build their own helpful clients/tools. (You might want to use a well-tested oauth API plugin to enable this.)
Welcome back. Yes, I remember. Time flies :-)

If all you're doing is friends lists and deck management and such, then a web API seems totally fine.
Once you get to versus mode, the ability to notify other people quickly becomes more important, and traditional web APIs fall down. Websockets are still OK for this for many use cases.
If your game is popular, then the web API would presumably even let your players build their own helpful clients/tools. (You might want to use a well-tested oauth API plugin to enable this.)
Welcome back. Yes, I remember. Time flies :-)

If all you're doing is friends lists and deck management and such, then a web API seems totally fine.
Once you get to versus mode, the ability to notify other people quickly becomes more important, and traditional web APIs fall down. Websockets are still OK for this for many use cases.
If your game is popular, then the web API would presumably even let your players build their own helpful clients/tools. (You might want to use a well-tested oauth API plugin to enable this.)

Share this post


Link to post
Share on other sites

thanks for the response! BTW, MVP target is iPhone and eventually Android + PC and potentially consoles way down the road if it sticks. We won't be targeting Web in Unity most likely.


Do you see any holes in my idea of doing a 'hand off' from the web app to the stateful game server? Is there something obvious that I might be missing or does that transition seem viable?

Share this post


Link to post
Share on other sites

Do you see any holes in my idea of doing a 'hand off' from the web app to the stateful game server?


Well, there are many ways you could implement it wrong. Handing off with an authentication token that is hard-to-spoof and using TLS for the non-web connection is important, for example.
In general, all systems do "hand off" at some point, because the match-making side of the system isn't the same as the game-playing side.
Separately, if you don't use the "central server" mechanism, you would have to worry about NAT introduction, at which point hand-off becomes much harder, but it doesn't sound like that's something that you'll be doing, so don't worry about that.

One the user has established credentials through the web login (over HTTPS, I hope,) you should then be able to re-use this token for the duration of a session, and keep sufficient state on the back-end for what the player is supposed to be doing at a time (such as what match they are matched up into right now, and such.)
Thus, when the client connects (with TLS) to the non-HTTP server, and provides the player token, the game server ought to be able to pick apart who the player is, and do the right thing.

Share this post


Link to post
Share on other sites

thanks. I have to think about that hand-off more. I was thinking that the Web Server would generate a session ID (GUID) and encrypt that session ID. Then it could send it to the game server via a normal TCP message, and back to the client in as part of the response to a GET.

Share this post


Link to post
Share on other sites
The problem with sending unencrypted tokens is that anyone on an open WiFi (such as Starbucks) is then vulnerable to session hijacking.
Check out the "firesheep" extension from a number of years ago, that finally shamed Facebook and such to move everything to HTTPS.
A randomly generated GUID is probably fine as a token, with the caveat that it has to be random, which then means it has less than 128 bits of entropy (because other parts of the GUID space are reserved for less-random unique identifiers.)
You might be better off with a long fully random number -- 128 bits is probably fine, 256 bits is plenty.
Another option is to use a predictable session id or game id or whatever, but issue a "ticket" that consists of (userid:gameid:issuetime:hash(userid+gameid+issuetime+secret_key))
"hash" might mean "sha256" these days -- sha1 is at this point broken-ish! The benefit of this kind of ticket is that you can detect whether the ticket has expired without a database lookup, assuming your servers are in sync on time (ntp is required.)
You can then go look up the appropriate player and game data based on the identifiers provided, rather than having to indirect through a GUID.
Something to think about.

Share this post


Link to post
Share on other sites

The problem with sending unencrypted tokens is that anyone on an open WiFi (such as Starbucks) is then vulnerable to session hijacking.
Check out the "firesheep" extension from a number of years ago, that finally shamed Facebook and such to move everything to HTTPS.
A randomly generated GUID is probably fine as a token, with the caveat that it has to be random, which then means it has less than 128 bits of entropy (because other parts of the GUID space are reserved for less-random unique identifiers.)
You might be better off with a long fully random number -- 128 bits is probably fine, 256 bits is plenty.
Another option is to use a predictable session id or game id or whatever, but issue a "ticket" that consists of (userid:gameid:issuetime:hash(userid+gameid+issuetime+secret_key))
"hash" might mean "sha256" these days -- sha1 is at this point broken-ish! The benefit of this kind of ticket is that you can detect whether the ticket has expired without a database lookup, assuming your servers are in sync on time (ntp is required.)
You can then go look up the appropriate player and game data based on the identifiers provided, rather than having to indirect through a GUID.
Something to think about.

What about generating an encryption key on account creation be rather effective method?
For example when a player signs up for the game, the server generates an ecryption key for further communication.
If the client loses the key, resinstalling the client or whatever, the player would have to linked their account to an email address to verify and generate a new encryption key.

This would mean that keys has to be spoofed at the rare occasions of account creation or key regeneration.

Share this post


Link to post
Share on other sites
The security of that is approximately slightly less than the security of a password.
Without the key, you can't communicate, which is the same as a password.
If you have a hack and lose the player/key table, then other people can impostor the player -- this is worse than strongly hashed password tables.
If you use the key as a "second factor" authentication, and still use a password, then this is a slightly improvement in security, but really no different from just storing a unique token on the client.
The actual encryption set-up should not depend on a fixed shared key -- that has many attack points.
Instead, you might want to ship a public key with the client, and keep the private key on the server, and for each new session, generate a per-session random symmetric key, and send it encrypted with your private key and the password as key material.
Note that you temporarily have the cleartext password on the server when the user logs in, because that's what the user provides for you to hash and check against your table.

It turns out, it's easier to use well-defined well-tested protocol implementations; TLS for TCP and DTLS for UDP.
And for two-factor, you really want a YubiKey or a Google Authenticator or perhaps the european "Bank ID" approach.

Share this post


Link to post
Share on other sites
Posted (edited)

The problem with sending unencrypted tokens is that anyone on an open WiFi (such as Starbucks) is then vulnerable to session hijacking.
Check out the "firesheep" extension from a number of years ago, that finally shamed Facebook and such to move everything to HTTPS.
A randomly generated GUID is probably fine as a token, with the caveat that it has to be random, which then means it has less than 128 bits of entropy (because other parts of the GUID space are reserved for less-random unique identifiers.)
You might be better off with a long fully random number -- 128 bits is probably fine, 256 bits is plenty.
Another option is to use a predictable session id or game id or whatever, but issue a "ticket" that consists of (userid:gameid:issuetime:hash(userid+gameid+issuetime+secret_key))
"hash" might mean "sha256" these days -- sha1 is at this point broken-ish! The benefit of this kind of ticket is that you can detect whether the ticket has expired without a database lookup, assuming your servers are in sync on time (ntp is required.)
You can then go look up the appropriate player and game data based on the identifiers provided, rather than having to indirect through a GUID.
Something to think about.

 

hi hplus,

I'm struggling to find much information about creating TLS connection in Unity. I'm now doubting that games implemented in Unity (at least in general) are using TLS at all. Maybe I have the wrong keyword, but googling around for 'TLS connections with Unity3d' brings up almost nothing.

I want to make sure that my game is as secure as possible within reason. So my plan is to not do authentication on the actual Master Server or Game Servers, but instead create an HTTPS based 'AuthenticationService' for authenticating users in a completely seperate web application.

My plan is to expose an endpoint on an ASP.NET MVC app which will accept the username/password, as well as allow users to create new accounts.

Any time a user logs in, he will send in plain text his username/password to my AuthService, the AuthService will validate the user using Hashed/Salted PW (or maybe Scrypt, although need to learn more abbout that - as the Scrypt examples I saw did not expose the salt).

AuthService will then Generate a 128bit unique number and send it to the client.

Client will then drop connect and connect to the Master Server using his 128bit number. The MasterServer will call out to the AuthService to validate the 128bit number is valid. Once user is matched up to a game and connects to the GameServer, the same tokenID will be used to ensure the GameServer this is a valid connection.

Anytime a user connections to another server (chat server, game server, disconnect from MasterServer and reconnects) he will continue to send that 128bit number on the initial handshake and those servers will each call out to the AuthService to make sure the ID is valid and not expired passed reasonable timeframe (still TBD..).

Does this sound like a sane approach to you? Since I don't want to implement TLS on my game code, I think this should work OK.. The altnerative to using the AuthService in this manner is to I guess use the 'ticket' system you mentioned. I'm still not sure how that works though....

(userid:gameid:issuetime:hash(userid+gameid+issuetime+secret_key))

What is 'gameid' here? the unique ID of the game as in application title? or is a session ID that the auth service generates and stores?

What is secret key? Do you have a good keyword for this scheme for me to google and learn more about? 

Or should I juse use the system I described above? Do you think there will be any issues when I add new auth providers such as Facebook?

Thank you again for your time!

Edited by graveyard filla

Share this post


Link to post
Share on other sites
If you're limited to Unity, you're limited to the security features they have built in, unless you literally impement well-known encryption protocols on top.
If you use HTTPS with the Web interface in Unity, that will use proper TLS, but the Unity low-level networking does not.
Then again, the low-level networking typically just does user agent movement, which typically is less interesting from a session hijacking point of voew.
Make your servers such that they use HTTPS for anything that affects the account (dollars, password changes, perhaps friends requests and messaging) and use the Unity networking for entities/movement, and you'll probably be fine.

Share this post


Link to post
Share on other sites

thanks hplus.. Is it OK from a security standpoint to re-authenticate for every single action when calling the HTTPS service for these actions? (e.g., no caching auth). I will probably use basic auth so that user can just use his username/password.

Share this post


Link to post
Share on other sites

Is it OK from a security standpoint to re-authenticate for every single action when calling the HTTPS service for these actions? (e.g., no caching auth). I will probably use basic auth so that user can just use his username/password.


As long as you trust HTTPS, that's OK-ish.
Note that passwords in flight on the server or client are more susceptible to interception by people who have access on the end points.
For example, if you log each web request payload, that log might include the password.

Also, basic-auth is kind-of dumb, because you HAVE to go through the ugly web browser name/password dialog box.
An alternative is to have a field in your payload, something like:

...
  "auth":{"username":"bobo","password":"correct horse battery staple"},
...
Then you can later add auth:{token:...} if you want to support session-based authorization.

Share this post


Link to post
Share on other sites
Posted (edited)

Does basic auth imply UI? I thought basic auth just meant header based, where as your example the creds are POSTed in the body. The advantage to using headers is that you can GET and POST, where as with body based, you would need to include auth inside whatever you were POSTing, so if you did want to POST actual data, you'd need a slightly more complciated body.. No?

Edited by graveyard filla

Share this post


Link to post
Share on other sites

Does basic auth imply UI?


Well, not strictly necessarily, but usually.
What typically happens is that a web browser makes a request, that needs auth.
The server returns with 401 and WWW-Authenticate header.
The browser then shows a dialog box with the realm from WWW-Authenticate and a username/password field, and tries again.

If you make sure that every web request already has the appropriate username and password, then that UI is unlikely to be shown.
If you build a "single-page app" that prompts for this information, and then provides it in each XMLHttpRequest, and doesn't reload so it would forget about it, then that could work.

Share this post


Link to post
Share on other sites

Thanks man.. I'm still going to build the UI using Unity so I will be sure to include the credentials in each header by default. The Auth Service will manage the account related tasks as well as generate unique, 1 time use 128bit tokens for the Master Server to use to 'hand off' authentication to the game/chat/matchmaking services.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this