6

The situation

  1. I am writing a Single-Page-Web App (using Angular). Lets call it SPA
  2. Another team-mate is writing some APIs (using Node.js). Lets call is Server
  3. My SPA is to Login to the Server using login/passwd, and do some stuff

My team-mate has decided to use cookies to track the session. Hence, upon a successful login, a http-only cookie is to be set in the web-browser the SPA is loaded in.

The problem

If we put the SPA in the Server's public_html dir, all works well. This, however, makes the SPA as a part of the API code. This breaks our build process, since every version upgrade to the SPA now requires upgrading the API too.

If we host the SPA in a seperate webserver that only serves the static SPA files, I run into CORS issues. Since the SPA comes from a different origin than the APIs it is trying to access, the browser blocks the ajax calls. To overcome this, we will have to set Access-Control-Allow-Origin on the server side appropriately. I also understand that Access-Control-Allow-Credentials:true needs to be set, to instruct the browser to set/send the cookies.

Possible solutions

  1. We create a build process which does a git-pull to the Server's public_html dir every time the SPA gets upgraded. I am trying to avoid this to keep the client and server upgrades separate.

  2. We create a proxy kind of situation, where the Server doesnt store the SPA files, but collects them on-demand from another server that hosts the SPA files. In this case, the web-browser will see the SPA files and subsequent ajax calls from the same origin.

  3. We code the server to set Access-Control-Allow-Origin:* in its responses. Firstly, this is too open and looks insecure. Is it really insecure, or is it just my perception? Also, since we are setting Access-Control-Allow-Credentials:true, Chrome complains Cannot use wildcard in Access-Control-Allow-Origin when credentials flag is true.. To overcome this, we will have to put exact origins (perhaps using a regex) in the Access-Control-Allow-Origin. This may seriously restrict us from distributing our SPA to users in unknown domains.

  4. For a Server API designer, is Cookie based authentication the recommended way to handle Authentication for SPAs? OAuth2.0 and JWT based Authentication seems to suggest that Cookies based Authentication is not right for SPAs. Any pros/cons?

Kindly comment on the above options, or suggest any others that you may have used. Thanks in advance.

sideshowbarker
  • 81,827
  • 26
  • 193
  • 197
Amarsh
  • 11,214
  • 18
  • 53
  • 78

2 Answers2

3

I think the issue is that your terminology is confusing. API is not an server, its an application that lives on a machine that can also be a server. If you make a NodeJS API, I suggest you use a Nginx server as a reverse proxy before it. Assuming you want the Nginx server, API and SPA files all on same machine, you can deploy your API to a directory and your SPA to another directory and have Nginx route the requests accordingly.

So I believe solution 2 is way to go. From there you can easily scale by increasing number of instances(if you use AWS) and load balance them or separate your API into its own application server.

As far as authentication. I have always preferred using Header Authorization with access tokens over cookies for SPA or API request. The idea that each request is self contained and does not require a persistent string kept on the browser is more appealing to me, though you can save access token via local storage.

Dan
  • 506
  • 5
  • 18
  • Thanks Dan. So, the solution 2 that you are favouring perhaps doesnt have the limitation of the both the SPA and the Node.js App living on the same machine. It will work as long as the machine that has the SPA is accesible from the machine that holds the Node.js App (or Server, in my client-server terminology). Correct? – Amarsh Aug 29 '16 at 03:01
  • Its really as long as your endpoint terminates to a machine/server that have access to both your Node API and SPA files. If anything, I would recommend putting your SPA files on a Nginx Server and have ur URL point to that. Then from here, have Nginx direct the request to your Node API on a separate application server. – Dan Aug 29 '16 at 03:06
  • Thanks again. Lets wait for some more comments. Any literature you can point me to for Header Authorization with access tokens? is it the same as http://self-issued.info/docs/draft-ietf-oauth-v2-bearer.html? – Amarsh Aug 29 '16 at 03:07
  • You can use OAuth if you want to, good thing about that is there is probably already libraries you can use. But if your API is simple and you dont need to use `token_type` which is like permissions, you can do your own token with hashes and keeping recording in the DB that maps to a user record – Dan Aug 29 '16 at 03:11
3

I would go with either solution 2 or 3.

2: you could set both (webpage and API) on the same server (or use reverse proxies) so that from an outside perspective they share the same origins.

3: in the case of an API, the same origin policy becomes less important. The API is to be consumed by clients that are not part of your web application anyways, no? I would not see any issue in setting a more lax allow origin header. And by more lax I don't mean wildcard, just add the origin of your webpage. Why do you want to wildcard it?

daniel f.
  • 1,421
  • 1
  • 13
  • 24