Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Oauth2; How to solve the issue with expired AccessToken during multiple async api calls , made concurrently?

I'm using Spring Security Oauth2 as a security layer in my application. Everything worked well until concurrently async calls appeared .

Can someone tell me how to handle the next case :
1. The client has an accessToken which already has expired.
2. The client makes two concurrent async api calls to my api ( for example : Thread1, Thread2).
3. The Thread1 receives an error : "accessToken expired", before Thread2 .
4. By using the refreshToken Thread1 receives a new accessToken = qqqqq.
5. The Thread2 receives an error : "accessToken expired", before Thread1 makes a new call to server with the new accessToken = qqqqq .
6. By using the refreshToken Thread2 receives a new accessToken = wwwww and removes the accessToken = qqqqq .
7. Here , the Thread1 makes a call to server with accessToken = qqqqq which is not active.
8. Theoretically, it is quite possible to loop both Threads by invalidating each other.

I will appreciate any help , thanks.

like image 436
Devin Konny Avatar asked May 28 '15 12:05

Devin Konny


1 Answers

If you've got control over the client then you can attach a version number to the access token - if a thread attempts to refresh the access token using an old version number then the current (recently refreshed) access token is returned instead.

public class AccessToken {
  private int currentVersion;
  private String accessToken;

  private static AccessToken currentToken;

  public static synchronized AccessToken refresh(AccessToken token) {
    if(token.currentVersion == currentToken.currentVersion) {
      AccessToken newToken = // refresh token
      newToken.currentVersion = currentToken.currentVersion + 1;
      currentToken = newToken;
    }
    return currentToken;
  }
}

If you don't have any control over the client and/or would prefer to fix this server-side, then a few options are:

  1. Allow the client to use one access token per thread instead of requiring them to share one global access token across threads.
  2. Forbid refreshing the access token more than once every, say, 5 seconds. This way even if the client runs into a refresh loop they ought to still be able to make some progress.
  3. Expose a method that will only refresh the token if the correct current token is provided so that the client can conditionally update its access token (you'll still need to expose the current method to absolutely refresh the token in case the client forgets the old access token).
like image 164
Zim-Zam O'Pootertoot Avatar answered Nov 15 '22 08:11

Zim-Zam O'Pootertoot