How to secure a REST api between a single page app and a server?

Michael picture Michael · May 1, 2013 · Viewed 8.1k times · Source

I have 2 servers in place, one is responsible for the front-end application and the user authentication. This server is rendering a single page application coded in javascript. This javascript app is rendering data from a second server through a REST api hosted on this second server.

I would like to secure this second server. I would like to have only the frontend application being able to call the backend server.

At the moment anyone can call the rest api from the browser to query the data.

Thanks for your help.

Answer

dthorpe picture dthorpe · May 1, 2013

Anything that the javascript app can do in the browser client can be seen by and done by somebody else to access your back-end REST API server outside your app.

Actually, the fact that the client app is implemented in JavaScript is insignificant - any application that executes on a machine outside of your control cannot be fully trusted. It's a little bit more difficult to reverse engineer native code exectuable than to ViewSource on a javascript app, but not impossible. Never rely on security by obscurity.

Your best option is to have the browser app require the end user to log in and obtain an auth token from a trusted identity provider, and present that auth token in every request the browser app makes to the REST API. The REST API can then validate the auth token to see if it came from a trusted provider and whether the user named inside the token is authorized to use the REST API.

This ties the authorization of the REST API calls to the user instead of to the app, and makes use of secrets (user credentials) that do not reside in the browser app for all the world to see.

With this in place, you can restrict access to your REST API based on which user is making the call. You can still also filter access based on which app is making the request, but this should be a minor point, not the primary security factor, because it is easier for the application description to be copied than the user credentials.

Another option might be to have your web server act as a proxy to your REST API service so that the browser app must go through the web server to get data from the REST API. This might be viable if the browser app maintains session state that the web server can verify to determine that the request is from the bona-fide app and not from somebody else. While this may allow you to keep your REST API off the public network, it doesn't really change your authorization problem - you've just moved it to the web server where you might have more session context to distinguish an in-app request from an interloper request. Tenuous at best, not recommended unless you're really confident in your app session state.

Regardless of what solution you choose, the fact remains that if your REST API is accessible from a client-side application (browser or otherwise), it is a public REST API and should be treated (and fortified) as such. There is no such thing as a private web API that can be accessed from a client machine.