6

I am facing an API with a token refresh system implemented. I am using Retrofit for the API requests and I have set an Authenticator to detect when an Error 401 is given and make new request to refresh the token.

The problem is that if the app has multiple requests at the same time (for instance, to fill multiple pages in a ViewPager or in an API request in a Service while user is using the app and cause another API request), the API is responding with 401 multiple times and, because of that, the application is requesting the Authenticator multiple times.

How do you manage to fix that? I'm thinking about a Singleton with a boolean to detect if the application is doing a token refresh call but it doesn't seems to me the best way to achieve it.

Sebastian
  • 2,896
  • 23
  • 36
antonicg
  • 934
  • 10
  • 24
  • take a look to this article from Ian Lake https://medium.com/google-developers/making-loading-data-on-android-lifecycle-aware-897e12760832#.llikp8avi – marco Mar 22 '16 at 08:15
  • I'll check that, thanks! – antonicg Mar 22 '16 at 10:10
  • Are you using OAuth? How often do you need to refresh access token? If it's not so often you may check on application start if current user has valid token, by trying to access a "test" endpoint. If you recieve 200 proceed with content screens and further requests, if not try to get new access token, if it's still not valid than you need new refresh token -> show login screen. – rafakob Mar 22 '16 at 22:07
  • @rafakob this is actually a workaround, you don't know when user close or start app, app may still in the background for a long time, and when user brings it back it should show the previous screen user was using. so using Interceptor or Authenticator is the way to go, but the how is the problem :) – Mohamed Ibrahim Apr 19 '17 at 11:46
  • 1
    Possible duplicate of [Okhttp Authenticator multithreading](https://stackoverflow.com/questions/32354098/okhttp-authenticator-multithreading) – Sebastian Jan 18 '19 at 14:43
  • Take a look at my answer here https://stackoverflow.com/a/60130868/2391964 – Tartar Feb 08 '20 at 21:23

1 Answers1

0

I would say Singleton is a good idea, but by Singleton I mean having a credentials object inside api client object - it would be singleton in object scope instead of whole application scope. You'd recommend doing something similar to this answer

I would introduce new object to be used as a semafore - it would be blocked every time when 'credentials are being refreshed'. To make sure that you'll make only one 'refresh credentials' call, you need to call it in block of code which is synchronized with object.

Community
  • 1
  • 1
Krzysztof Skrzynecki
  • 2,345
  • 27
  • 39
  • Yes, I solved the problem months ago that way, moreless. I'm using a singleton with a synchronized function where I check if the token of the request is the same than the token saved. If it is the same, means that the token has not been refreshed yet, so I execute the refresh. If not, the next requests, execute the request again with the refreshed token. – antonicg Oct 21 '16 at 07:32
  • Great you solved it - I didn't know that. So actually the same approach as I proposed, the only difference is that you block singleton method and I block block of code, which of course can be extracted to method, so they are the same – Krzysztof Skrzynecki Oct 21 '16 at 12:42