• caglararli@hotmail.com
  • 05386281520

Best practises regarding authentication in SPA/API solutions with SSO

Çağlar Arlı      -    15 Views

Best practises regarding authentication in SPA/API solutions with SSO

There is really not that great information on what the best practices are for auth in SPA/API solutions. Most of them just say use JWTs and auth code flow in the SPA. There is a ton of information regarding auth in a SPA where you are requesting third party APIs like MS Graph or Google Calendar, but NOT API's that are your own. Most solutions I see today in the real world consists of a 1 to 1 mapping between a SPA and a API. So what are the best practises for these types of solutions? IETF has a draft, recommending BFFs, but I don't see the point of that if you own the API yourself.

I have a React SPA and a .NET API, where the user will login using AD FS. It is currently using Implicit Flow, which I am swapping out for Auth Code Flow.

I am exchanging the auth code for the tokens in the backend (using client secret as well), but sending back a cookie to the SPA and completely discarding the tokens that came from AD FS. I see no point of keeping the tokens for now. The flow goes like this:

  1. User opens SPA, generate code verifier + state, gets redirected to the sign in page /oauth/authorize from AD FS with a code challenge.
  2. User signs in and is redirected back to the frontend.
  3. Frontend checks URL for auth code + state, verifies and calls the backend /api/authenticate, with the auth code + the code verifier.
  4. Backend calls the /oauth/token endpoint with auth code, code verifier and the client secret (stored only in backend) and is returned the token. I then get the claims from the token, and use that as ClaimsIdentity and sign the user in with a cookie (basically map the JWT claims to be used as claims in the cookie). Discarding the tokens at this point, as I have no need for them.
  5. SPA sends all requests to the API with cookies, no tokens in the browser.

Cookie is same site=lax, httponly and secure. Also have CORS rules setup.

When signing in the user, I also create a "custom token" which is saved to the db to have session management. I save an initial expire time (20 minutes in the future, can be extended), and absolute expire time (8 hours). On every authenticated request, if the expire time is halfway through, I will extend it up to 20 minutes or up to the absolute expire time if that is closer. If the absolute time is reached, the user is redirected back to AD FS to sign in.

I think this is the best approach for SPAs/APIs. However, I could store the refresh token from AD FS, and on every extension of the expire time I could do a refresh token request to AD FS, to handle any claims changes. Other than that, think this solution is better than having access/refresh tokens in the browser. Any thoughts on this? Or is there a better way? This of course requires more custom code in both SPA and API, at least more than just using libraries like MSAL. However, I don't think in SPA/API solutions where you own both, using JWT's should be recommended. Also setting up a BFF seems pointless.