Some networking questions about authentication and authorization


#1

Hi fellow monkeys,

After some years of experimenting with single player game development I’m now taking my first steps in multiplayer and networking game development. I will be using spider monkey and pspeed SimEthereal libraries, where I also have some questions about the ZoneManager but I’ll ask them in a different thread.

My first question starts at the beginning, how should a client safely authenticate to the server and how can the server maintain a link between the client’s connection and the account/player information.

I thought of implementing it like this:
Account creation
The player creates an account on my registration website, the username and hashed password are stored in a db over an HTTPS connection. This way I don’t have to implement the account management, forget password flows, … etc myself.

Log in

  • The client connects to the server, the server sends back a random generated string.
  • The client sends the username and a hash of the hashed password concatenated with the random generated string (eg. username, hash(hash(password) + generated string) )
  • The server compares the received hash with it’s own hash of the stored hash password and the generated string.

After this I’m a bit uncertain on how to proceed. Should the server then generate a token and should this token be added on the connection for security reasons? The server can check for duplicate tokens for example… If so, how should this token be added? Should this be included in every message to the server?
Or is it sufficient that after the client is authenticated, I just store some account/player info on the connection using the setAttribute method? I’m not planning on adding account management or transaction management in the game. So only game related info will be passed on.

Another question I have is about the backing database on the server. Should I keep 2 separate databases, one for account information (mysql, postgres, …) and a file db for game entities, components, … (h2, sql, derby, sqlite, …)? Or is it ok to just have one backing database and mix this? If so, for what type of db should I be looking at? I’m mainly asking this question because I have some concerns about the speed and performance. Every time a component of an entity is changed it should be persisted, this can become heavy for the position components for example of the players, they will probably be constantly updated.

thanks in advance!


#2

please note Java can connect to DB too, with secure method too.

about database, IMO i would just use mysql and from time to time save some of Server memory data into DB.

Big files(assets) should just be on server to load if server also require them. Typically only client should have assets.

you need to have quick access to a lot of data(like player position / etc), so you need have them in memory. Saving is important and loading too, but you can save some of this memory data for example each 1 hour.

user accounts and other data that is required after longer time, can connect to DB directly.

btw see:


#3

Assets will be on the client and server in the assets folder and not in a database.

I know about Zay-ES and I will sure use the SqlEntityData in combination with the PersistentComponent. As far as my understanding goes, this automatically stores PersistentComponents in the backing database and only loads the needed components from the database when they are requested.

I was more wondering if I should use a database running in the JVM on the game server like hsqldb that persists to a file for the entity system and use a different database for account and other (game) stuff. Or can I just save this all in the hsqldb. Or shouldn’t I use a database running in the JVM and use a mysql for the account and entity stuff…


#4

I also use SqlEntityData backed with an embeded HSQLDB.
It will automatically persist PersistentComponent in db and update them when change.
(I believe Zay-ES + JME RMI will make Networking game development super easy and fast)
I am doing accounting in ES, for each player I create an account entity which holds components about player name, user name, cash , login state, party id, … . But I do not save passwords on db for this I am considering to use

So will relay logging in to a third party like Google, Yahoo, Twitter, Discord.
Probably I will chose Discord because I want to use it for chat.


#5

I’d suggest keeping everything in the same DB - this will simplify your management and make transitioning to multiple servers much easier in the future if desired. Using connection attributes for the server to track which user is on which connection is perfectly fine.

Note that the login process should really happen over TLS - salting the password hash like that makes it much harder to attack, but it can still be attacked if sent in plaintext. If you don’t want to mess with encrypted connections, you can use other schemes for authentication that don’t involve sending the password in any form - for example, you can randomly generate a one-time key, encrypt it on the server with the user’s stored password hash, send that encrypted info in plaintext, decrypt it client side with the user’s password hash, and then send it back to the server. If the decryption matches the server’s generated plaintext, the user had the right password. This gives an attacker no information about the password at all, so an offline attack is truly impossible. Doing this myself, this is what I would use, although I’d still run all reliable traffic over TLS. Encryption adds negligible overhead, and there’s no question about anyone gaining anything by sniffing traffic.


#6

I’m going to differ a bit. Having worked in J2EE environments and so on, I recommend keeping your access and authentication code as completely separate as possible. This is the piece that you will likely want to change and switch out the most often for different server environments, different distribution mechanisms (Steam, EA store, whatever), and so on. Leave it out of the game.

For example, the first time someone figures out how to exploit your login system (decades of industry experience figuring out how to do this and you’re just starting so it’s nearly guaranteed) you’ll probably consider switching to something “real” like oauth2 or something similar. Best not to have all of that embedded in your game or anywhere near your game’s database.

In fact, think of it like that… imagine you are using google of facebook to manage your user login and then design around that. The auth server keeps track of that kind of account stuff and identifies the user for you. The game database only keeps game-specific stuff about the user.

So during login you will get some kind of access token associated with that login. At that point, the server and the client can use that access token to agree on who the player is and let them in, etc. through whatever communication mechanism the auth server provides.

Note: you can of course roll your own account management. I did this for the initial version of Mythruna (the one people can still play). With even a few hundred active players at any given time, having to reset passwords and debug login issues for them, etc. was this constant tiny annoying drain on my time. My local server’s database has like 10,000 accounts in it now, too… of which 90% were active only once.

So it may seem like a pain but if you can find an easy way to offload that work then it will pay dividends.


#7

Thanks for the great replies.
I’ll be using a third party authorization system separated from the game logic based on tokens as @pspeed suggested. This can just run somewhere else, decoupled from the server but I’ll handle that later on in development.

For this stage in development I’ll have my AccountService interface use a token to talk about accounts. How this token is obtained (google login, oauth2, …) I’ll tackle later on.

When the client connects to the game server and identifies itself using this token, this should be send over TLS I guess? I mean the authentication process can and should happen over an https connection, but when you have your token, this should also be communicated securely. If anyone steals the token it can be reused, even if it’s only valid for a specified amount of time?


#8

Yep, the token must be kept secure or an attacking third party can use it.


#9

Client sends it to the server one-way hashed. Server uses the same one-way hash on the token it obtained to compare them.


#10

So the auth server should send the token to both the client and server?


#11

That works if the auth server sends the token to the main server. For uses like JWT where the server typically has no pre-knowledge of the token (i.e., stateless servers) this won’t work and you have to rely on the token being secret.


#12

We’re talking about a game, though… which presumably has a persistent connection to the server.

There has to be some way for the server to know that “random string of characters” sent by the client is a valid token.

So you just have to work within whatever protocol you are using to support that. And it’s always best of you can avoid two-way hashing if possible… TLS, SSL, or whatever. (Never mind that cert based communication is its own pain.)


#13

mhm…
I guess I’ll buy a certificate and put it on my webserver so the client can authenticate with plain java. This way I don’t have to struggle with the keystore stuff and is the account management seperated from the game:
new URL("https://host/login?user=abc&pass=def")
if response code == 200, login ok and receive auth token

open ‘unsecure’ persistent tcp/udp connection with the gameserver/SpiderMonkey and send the auth token. Once the token is used it’s discarded on the game server and cannot be used again.

I guess this is probably more then ‘ok’ (please correct me if I’m wrong) for an indie online game that has, statistically speaking, a very low chance of ever being released and if it ever gets released, having more then 5 players…


#14

Do you know about https://letsencrypt.org/ ?

These parameters in the query string are sent via GET and will show up as plaintext in the webserver’s access logs.
You can send them as POST data instead.

Otherwise, yeah I think that will work. But you should know that it won’t secure your auth against man-in-the-middle attacks (which I think you don’t have to care about just yet).