Search code examples
authenticationoauth-2.0access-tokenopenid-connectrefresh-token

Authentication - proper way of handling session with tokens


I have a ReactJS SPA application which connects to the ASP.NET Core WebAPI. The API is also an authorization server thanks to OpenIddict. I am using PasswordFlow and RefreshTokenFlow to handle authentication, which means that the server returns an AccessToken and optionally a RefreshToken. At this moment I struggle with handling Remember me functionality properly. When a user wants to rememebered it is no big deal - the server returns an AccessToken and a RefreshToken which the client stores is LocalStorage, so it can refresh the AccessToken when it's about to expire or is expired by using RefreshToken and it is fine - there is a lot of articles and other helpful resources on the Web. The problem comes when the user does not want to be remembered. How to handle authentication is this scenario? The two solutions I see are:

  • the server only issues an AccessToken, which the client stores in SessionStorage. If it expires - the client forces the user to re-enter his credentials to get a new AccessToken. AccessTokens should be short-lived (according to what I've learned so far, it can be from one up to several hours, but the more hours it is valid, the less secure it is in a situation when it gets stolen. If it lasts for an hour and after that time the user still uses the application, it seems a bit odd to force him/her to login again.
  • the server returns an AccessToken and a RefreshToken and the client stores it in SessionStorage. During the session, if the AccessToken is about to expire, the client can get a new one by using the RefreshToken. This is risky as well as the server will never know that the user closed his browser and that his/hers RefreshToken should be revoked. Assuming that RefreshTokens have a way longer lifetime, this seems really risky.

I will be grateful for any thoughts, suggestions and insights on this topic. Thank you!


Solution

  • If you are new this stuff is tricky to understand, but most implementations work like this:

    • The SPA uses the Open Id Connect Implicit Flow via a 3rd party library
    • Users are redirected from the SPA to a 3rd party Authorization Server to login
    • The Login Process is completely externalized from your app
    • After login the Authorization Server returns a token to your SPA
    • The SPA calls the API with an access token

    PS: I have a code sample and some written guidance that you might find useful.

    Further posts describe how silent token renewal works for an SPA, and as John points out above, an SPA does not use refresh tokens.