13

I have an API written in nodejs and I have a frontendapp written in angularjs. I want my API to be called only through my frontendapp and not from any other source.

e.g. I have an endpoint called myhost.com/posts/id and when the method is delete it deletes the posts. I dont want an attacker to access this end point and deletes my posts. How can I prevent it?

8

I believe that this is not possible in a failsafe way, unfortunately. Let me explain why.

You want your frontend app to have a way to identify itself to the API. In other words, you want authentication.

But authentication requires the existence of some kind of unique, secret data that the frontend app can use to distinguish itself from other applications. This can be a shared secret (password, "API key"), a private asymmetric crypto key, or something else yet. But whatever it is, it has to remain a secret, since if another app can copy it, it can pass as your frontend app.

So the question is, where are you going to store that secret?

If it is stored inside of the application code itself, or directly accessible to it, then it is vulnerable to reverse engineering or exploits on your front-end app, no matter how many layers of cryptographic indirection you use to hide it. This is the fundamental security flaw that led to the failure of almost all DRM schemes devised to date.

If it is stored on some tamper-proof location of the client machine (e.g. TPM chip, trusted OS key management facility), then the question becomes, how does it get there initially? And how are you going to access it from Javascript code, which has limited low-level OS access capabilities?

If it is stored remotely, then you are only shifting the issue of app authentication elsewhere: how is your front-end app going to authenticate on the remote server? Or in other words, what is preventing another app from accessing that remote server in exactly the same way?

My conclusion is that there is no truly secure way to authenticate a piece of JS software. You'll have to design your API in a fashion that is secure from malicious client input and, if you do want a way to ban compromised clients anyway, provide clients with revocable "API keys" that you can easily ban on the server side, the way most web services (and newer DRMs) do it.

4

A good way to start is to prevent connections to the API application from anything except valid client addresses, in your case, your angularjs server.

Additional security would be gained by implementing a revocable shared API key between each angularjs instance and your API, so you can revoke permissions from compromised instances.

Also, it's good to confirm your traffic between the frontend app and the API server is encrypted, even if it's only on your internal network.

1
  • This wouldn't work, as the IPs of clients aren't known when it's a frontend app.
    – Lasse Bunk
    Aug 26 '16 at 18:58
1

If your front-end can use the API, anyone can use the API. In this case, your front-end/browser is only an abstraction layer to call your API, nothing stops someone from getting rid of that abstraction layer and call the API on their own.

You cannot reliably ask "is this API call coming from my front-end", because anyone can lie in the API call and say that it comes from your front-end.

One might think they can make the web server give you some kind of key when you first open the page, store the key on the browser and then send that key with each API call. But what's stopping someone from getting that key once from your web server and then using the API maliciously? If the browser can request the key, then anyone can request the key.

In order to limit access, you require some form of authorization. So your API must say "is this person who wants to delete posts allowed to do so?". In this case it doesn't and shouldn't matter where the API call came from, only if the person calling this API has the right authorization to do so.

One way to do this is by implementing some kind of login feature and on a successful login, make the server retrieve a unique key. The server should know one way or the other that this key was given by the server to this user. You could do this by remembering that this key belongs to that user on the server or by using something like a JSON Web Token. Ideally you would use some kind of library or framework to perform this authentication. With every API call, you can send this key and the server will know that you are allowed to perform this action, whether you clicked on the right front-end button or whether you use some other program to make the call.

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.