1

I have an API communicating with my client, now I want to secure that API so that onlyu my client can use it. I am planning to do the following, since I have no experience in this I have gathered all this from reading up on the subject and I need advice, here is my flow:

  1. When a user signs in/registers, generate a token (ex: token = userId + date + radomvalue), save this token (hashed) in a DBtable together with userId.
  2. Send token (hashed) to client, save in preferences for later use.
  3. When calling API this token must be sent with the request, on server, we look through our token-table and see if we find the combination of userId+hashedToken, if we do, access is granted.

All communication is over SSL, here are my questions:

  1. What should I do about the TTL on my tokens? And what If I end up getting 3 000 000 users, that means that every call I make to the API it has to look through a table with 3 000 000 rows, is that ok?
  2. I obviously can't make my login/register endpoints require a token passed in the request to be accessed (since the client has not gotten it yet), is it okay to leave these "open"?
  3. Is it okay to send plain-text salt+password to api since it is SSL-protected, then hash it on server-side?

EDIT: 4. Thinking more on this, wouldn't someone just be able to grab their access token from the preference-file and make calls to my API from their own app, as long as they have the endpoint, and edit whatever they want on their own user?

Threat model: I am building a game. I have a database where I save ranking, experience, as well as what version of my game you have (free, no-ads, premium). After someone makes a purchase I call endpointService.setVersion("userId", "PREMIUM");. This is the only real high value asset for me, since I don't want people to edit that themselves. I just want to protect my endpoints, but especially that one.

  • It's not possible to make only your client able to connect. Users will be able to reverse-engineer anything you come up with to stop this. What's your actual threat model? – Joseph Sible Mar 13 '17 at 19:48
  • @JosephSible I am not protecting nuclear codes. I just want to know if this is an acceptable method to prevent most attacks. I do not store any sensitive data, you could change your ranking in my game worst-case... – Green_qaue Mar 13 '17 at 20:01
  • Remember, it only takes one good programmer to write a cheat app and release it for the masses to use. If you don't want users to be able to tamper with their ranks, then you need to calculate their ranks on your server instead of on their client devices. – Joseph Sible Mar 13 '17 at 20:03
  • @JosephSible I do calculate it on the server. For that exact situation I send boolean win and int rankDifference to the server. But do you have a suggestion? Just telling me it wont work is not a lot of help :) – Green_qaue Mar 13 '17 at 20:05
  • I think Joseph is trying to structure this effort for you a bit. You really should come up with a threat model against which these security mitigations can be evaluated; otherwise we are just shooting in the wind. – John Wu Mar 14 '17 at 3:16
1

Is it possible to re-use an authorization mechanism, such as OAuth2?

Your client get a valid access token upon challenge (userID, secret) which is cryptographically signed. Your server app can verify this token, and potentially take out any claims from it; so you don't need to look it up in a DB. Even if you want to look something up, you'd need to look at in-memory key-value stores/caching mechanisms such as Redis.

The on-boarding (signing up / logging in) would be performed by an IdP, an identity provider. See it as the system doing the actualy verification. It will reply a unique token to the client; encoded and signed. As long as your API makes sure that this is a valid token (signed by the right guy), then you should be good.

Is it okay to send plain-text salt+password to api since it is SSL-protected, then hash it on server-side?

If you salt your password client side, then it just substitutes the password. Unless someone does a MiTM (intercepting proxy, ...), and you don't log the request body, ... SSL would prevent you from eavesdroppers. Whether you use the password, or the hash of the password; an attacker who captures it, would just send the hash as well.

...Wouldn't someone just be able to grab their access token from the preference-file and make calls to my API from their own app

Yes, everything that's on the client cannot be trusted. You can try to obfuscate it a bit, but essentially, you can't be sure that it was your application sending it; and not another program (from someone who took the time and effort to reverse engineer it)

  • Thanks for your answer. How does my method differ from Oauth? What in my process is it thaat makes it not safe? – Green_qaue Mar 16 '17 at 8:13
  • You always send the userid and password (although you call it a token) with every request. OAuth would exchange this for an access token and doesn't have to look this up upon every request. – ndrix Mar 16 '17 at 18:26
  • I only send a token with every request. That token is then used to get the userId. Also, If they dont look up the token on every request, how do they know its valid? :) – Green_qaue Mar 16 '17 at 18:46
  • What if 2 users have the same token (collision). How do you know which user this is then? – ndrix Mar 16 '17 at 19:13
  • In OAuth, the token is a JWT string which is cryptographically signed. You check the signature (i.e: Facebook says you're user XYZ, so I believe them). But it's not encrypted; just signed. – ndrix Mar 16 '17 at 19:14
0

As JosephSible has mentioned, and you have alluded to in your edit, in your comment, you do not control the client endpoint, and they can do anything they want on their own system. Also, since they control the end point, SSL will not do anything, since they can just read the token from memory.

EDIT:

OK, I just saw your threat model edit. You are asking a different question than I believe you mean to be asking. My previous answer addresses your original question of "How do I build a system which only authorized clients can connect to." That is not possible. What I believe you mean to ask is "How do I prevent user who have not paid for X features from using them on the client?" There are a couple of approaches, some more effective than others. The best answer and the only 100% effective one is to do everything server-side. There are many different approaches to securing the client, but none of them are 100% effective. If the user can patch the client binary or create their own, they can get around it.

You may want to read this book: https://www.amazon.com/Game-Hacking-Developing-Autonomous-Online/dp/1593276699 It talks a fair amount about how games are broken from a security stand point.

  • Why did you post this as an answer? – Green_qaue Mar 14 '17 at 14:45
  • Your 3 questions were asked based on a flawed premise: that it is possible to create a client-server app where only approved clients are allowed to to be used. Unfortunately, it is the answer, even though it might not be the answer you had hoped for. – user52472 Mar 14 '17 at 15:35
  • So how do other apps do it? What am I missing? – Green_qaue Mar 14 '17 at 15:37
  • They don't. There are some that try to do what you have described, but it's always possible to reverse engineer the client, given enough time/resources. – user52472 Mar 14 '17 at 15:48
  • I updated by answer based on the edit to your original question. – user52472 Mar 14 '17 at 16:06

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.