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:
Use Authorisation Code flow:
- Direct user to login screen. User logs in.
- Login screen calls back to Restful API endpoint that deals with the authorisation code.
- Endpoint obtains refresh/access token and generates its own session token.
- 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.
- Serve the SPA only if the request contains a cookie with a valid session token.
- 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.
Use Implicit flow with a landing page:
- Direct user to login screen. User logs in.
- 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.
- The landing page uses the access token to make a Restful API request. The API endpoint generates and sets a HTTP Only, secure cookie.
- The landing page receives the cookie and redirects to the protected SPA.
- Serve the SPA only if the request contains a valid cookie.
- 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.
Use Implicit flow with lazy-loaded app assets:
- Direct user to login screen. User logs in.
- Login screen calls back to protected SPA. The non-sensitive part of the SPA is publicly accessible.
- The SPA parses the access token and makes a Restful API request. The endpoint generates and sets a HTTP Only, secure cookie.
- The SPA retrieves the cookie and lazy-loads the rest of the app.
- 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?