I currently work on an legacy app which somewhat loosely implements an OAuth2 flow. In short, when the user logs in with username/password, he receives an access/refresh token pair. The access token expires after 20 minutes whereas the refresh token has a lifetime of 180 days.
Now when the client gets a HTTP 401 Unauthorized due to an expired access token, it will use the refresh token to obtain a new access/refresh token pair. At the same time, we invalidate the old token pair in our backends database (we simply delete the entry).
This has some major issues since our clients are mobile apps and it sometimes can happen that a response from our server is not received by the client. So after our backend saves the new token pair, which the client doesn't receive due to for example network problems, the client no longer can get a new token pair because he still only knows about the old - now invalid - refresh token.
I was wondering if what we are doing is correct or whether we actually should never remove old refresh tokens from the DB as long as they are not expired. Or should we for example remember the last 1 or 2 refresh tokens for a user so even if a new one was created, if the client doesn't receive the response from our server, he can still try one or two times again with the old refresh token.
Or should we simply never send out new refresh tokens when obtaining a new access token and always use the same refresh token?
Is there any best practice to follow or is this all personal taste? I mean we can't be the first ones to run into this issue of mobile clients loosing responses due to network issues, right? :)