1

I've made a simple REST client-server system using JWT tokens.

On my mobile app, you can exchange your Facebook/Google access token for a JWT with the server and then make calls with it, for ex. fetch your friends/data in the app.

Now, I want to limit this so the server will accept only responses posted through the android app, not the classic web browser.

This scenario can happen, when for example user posts his POST request through an app like Postman for Chrome.

How do you handle this kind of things?

3

It sounds like what you are trying to do is to identify the software being used to access your API. The way I look at this, it is independent of user authentication. User authentication tells you who is using your API, you are interested in what is being used to access your API.

The fundamental problem you face is that you can't trust 100% the code that is running on the client. You have no control over it and a malicious user can modify it or reverse engineer it or as you suggested use something like Postman to send synthetic requests.

You have a number of options of how to proceed:

Remove the problem

It may be that you can re-architect your app and server so that you no longer care what is being used to access your API. It is difficult to trust code that you don't control so if possible it is good to move as much of the functionality to the server.

User-Agent String

A basic method of attempting to identify the source of a request is to look at the user-agent string that is included in the headers of the requests coming to your API. You could filter out requests coming from things that are not your android app. The problem is that it is just a header and is really straightforward to fake. So it doesn't do much in practice.

API Key (and Secret)

Another thing that you could do would be to use an API key. This is an identifier that you use to let your server know that the client accessing it is genuine. To prevent it being stolen by just observing the connection with a proxy, you have to use TLS which encrypts the connection between the the client and server so third parties can't easily eavesdrop. You may still be vulnerable to a man-in-the-middle attack though (look at pinning if this is a concern).

You can enhance this scheme by combining or replacing your key with a secret that you store in the app and never transmit. Instead you sign the traffic you send to the API using an HMAC. If anyone alters the message you send, the signature will not match and you can reject the request. Because your app is the only thing with the secret, another app will not be able to access your API.

This holds true as long as your secret remains hidden, but if you have released your app into the wild, someone malicious can still potentially get access to the app and try to look inside it to retrieve the secret. How hard this is depends on how hard you hide it. You can obfuscate your secret or embed it in native code but a sufficiently motivated individual will probably be able to find it given enough time.

In conclusion

None of the options for identifying the source of an API call are perfect, people will rightly tell you that they can all be cracked. The decision you have to make is how important is whatever you have behind your API and how much do you want to protect it. Only you can can answer that one.

I work at a place that does this sort of stuff and one of my colleagues has just started writing a series of articles that go into a bit more detail about mobile API security. If you want some more detail it might be of interest.

1

There are few ways that how you can achieve this. I hope your objective is accept requests only from known clients?

Preshared Key

A PSK in its simplest form is a key that is exchanged between two parties out-of-band with the sender using the shared key as is in the messages as the credential. For this reason, HTTPS generally is a must for PSKs. Without help from transport security, it is easier for a malicious user to get the PSK and use it in a malicious request, just like a legitimate request.

Time Stamp to prevent replay attacks

Suppose we design our security mechanism to transmit the credentials not in plain text but encrypted using the PSK. The encrypted credential is sent in the message, typically in the HTTP request header. A malicious user cannot decrypt the header and extract the credentials but can replay the earlier request as is. Worse, a malicious user can frame a new request and use only the header value containing the valid credentials from the previous successful request.

A timestamp can be added to the message and encrypted along with the rest of the message content. The service can retrieve the timestamp after decrypting the message and fail the request if the timestamp is too old for the threshold that is already agreed on. This cuts down on the window of opportunity to replay a request.

Downside is , both server and client need to in sync with time.

An alternative to a timestamp is a counter such as the nonce counter that we saw with digest authentication. With a counter, we don’t need to be concerned about the skew between the clocks. However, clients must implement a counter to ensure the count sent in a request is greater than the count in the previous request at least by one, and the server must keep a record of the last received counter. Of course, the message has to be signed so that a malicious user does not increment the counter and replay the rest of the request.

Prevent Identifier Misuse

In its simplest form, a PSK is both the user identifier and the credential. For this reason, PSKs must be unique. Given a key, an application must be able to identify the corresponding user without any ambiguity. The basic premise that we are working on is the avoidance of HTTPS. For this reason, the PSK cannot be transmitted as is.We need to have two keys: one acting as the identity of the user and the other acting as the credential.

However, these keys are not mathematically linked. Also, the same key used to sign on the sender’s end is used to validate the signature on the receiver’s end; hence, this is just a symmetric shared key. But similar to public key cryptography, only the private key must be guarded.

Prevent MIM attacks (for non HTTPS communication)

With no HTTPS, a man-in-the-middle (MITM) attack is one of the most significant threats. The primary mechanism to ensure data integrity of messages is a Hash-Based Message Authentication Code (HMAC). HMAC is just a piece of data created through a cryptographic hashing algorithm and a shared secret key. In this section, I show you how to create an HMAC using the SHA256 algorithm. However, if the message needs to be encrypted for confidentiality, you can easily add that functionality using the same private key we use for HMAC or you can introduce a new key specifically for encryption.

The Request should contain following params

  • The public key, which is the key associated with the user.
  • The counter
  • The timestamp

In addition to the parameters, the request includes a signature that ensures that none of the parameters are tampered with. It is possible to create the signature based not only on the three parameters but also on the entire body of the request if the objective is to make sure nothing in the request gets modified.

To make sure no one tampers with the parameters, we can include an HMAC-SHA256 of all three values plus the request URI and HTTP method. Listing 9-1 shows an HTTP request secured by the PSK mechanism. Figure 9-2 shows the PSK design.

0

If you need to reliably identify the client application (not the user, nor the device), then you are getting into some of the techniques used by DRM (Digital Rights Management). None of them are robust, and is generally through obscurity. So I agree, if you can rearchitect to not care which application is calling you, you'll be in better position.

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.