2

I've got an Angular 1 SPA with a Restful API that I'd like to restrict access to. As I understand, typically the OIDC Implicit flow is designed just for this. However, I consider the frontend SPA code sensitive as well and would like to restrict access to that. A vanilla implementation of Implicit flow assumes the frontend client is public and so that won't do.

The only practical way I can think of protecting the app assets is via a cookie. The way I think of it there are a few possible solutions:

  1. Use Authorisation Code flow:

    1. Direct user to login screen. User logs in.
    2. Login screen calls back to Restful API endpoint that deals with the authorisation code.
    3. Endpoint obtains refresh/access token and generates its own session token.
    4. Endpoint redirects the browser to the SPA, sending it the session token in the hash portion of the URL. In the same response set a HTTP Only, secure cookie containing the session token as well.
    5. Serve the SPA only if the request contains a cookie with a valid session token.
    6. Once in the SPA, parse the session token from the hash and use it in the Authorization header for Restful API requests.
      • Pros: It appears to me a legit way to use the Auth code flow
      • Cons: It feels over-complicated. I also have to manage server-side session state like traditional web apps.
  2. Use Implicit flow with a landing page:

    1. Direct user to login screen. User logs in.
    2. Login screen calls back to a landing page (an SPA), which parses the access token from the hash and stores it in localStorage. The landing page has the same domain as the protected SPA.
    3. The landing page uses the access token to make a Restful API request. The API endpoint generates and sets a HTTP Only, secure cookie.
    4. The landing page receives the cookie and redirects to the protected SPA.
    5. Serve the SPA only if the request contains a valid cookie.
    6. Once in the SPA, use the access token from localStorage to make Restful API requests.
      • Pros: No server state required
      • Cons: Still feels a bit complicated - I now need two SPAs.
  3. Use Implicit flow with lazy-loaded app assets:

    1. Direct user to login screen. User logs in.
    2. Login screen calls back to protected SPA. The non-sensitive part of the SPA is publicly accessible.
    3. The SPA parses the access token and makes a Restful API request. The endpoint generates and sets a HTTP Only, secure cookie.
    4. The SPA retrieves the cookie and lazy-loads the rest of the app.
    5. The rest of the app assets are only loaded if the requests contained a valid cookie.
      • Pros: Feels more like a typical use of Implicit flow, so easier to reason about its security.
      • Cons: SPA itself is more complicated due to the lazy-loading requirement (but perhaps less complicated than the other two solutions)

Are these reasonable solutions? Are there any simpler solutions still?

  • All of the solutions sort of work, and personally I'm partial to the first one. It keeps the token on the Api side and uses a cookie for the session. But are you sure that you need to keep the frontend code secure? What is keeping a logged in user from saving it away? – Geir Emblemsvag Mar 6 '18 at 7:24
  • Yea - whether it's frontend code or an API, a logged in user can always copy any sensitive data/IP and misuse it, sure. I think of that as a different issue. I'd like to keep the frontend code for the same reason that people want to keep their backend APIs secure. For auth code flow, I don't really need the access token for anything - what if instead of generating my own token, I just pass the access token to the client to use for API authentication, like the implicit flow. What's the worst that can happen? – hhp Mar 6 '18 at 9:37
  • My point is that it is usually better to protect your data, while accepting that the code is accessible. In an Angular/REST world it will be mostly open source anyway. So protecting access to APIs is important, but the code itself less so. – Geir Emblemsvag Mar 6 '18 at 9:52

Your Answer

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

Browse other questions tagged or ask your own question.