Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Refresh a token in OkHttp Interceptor

I'm writing an interceptor such that when I get 401 I'm using the refresh tokens to get a new access token in the background and then add that token to the request.

Code example:

    @Override
    public Response intercept(final Chain chain) throws IOException {
        Request request = chain.request();
        Response response = chain.proceed(request);

        if (response.code() != 200) {
            try {
                new TokenRequestTask(tokenRequest, request, OkHttpresponse, chain).execute().get(5000, TimeUnit.MILLISECONDS);
                response = chain.proceed(request);
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            } catch (TimeoutException e) {
                e.printStackTrace();
            }
        }
        return response;
    }

In the async task In postExecution, I'm changing the header of the request by adding received fresh auth token. But the problem is that the output is not as per intended. The function is returning the old response as the result of the async task comes after that. Ideally, it should wait for async task result and then return but is not happening. How to achieve this?

like image 768
s k Avatar asked Oct 16 '16 08:10

s k


People also ask

How do I trigger a refresh token?

To use the refresh token, make a POST request to the service's token endpoint with grant_type=refresh_token , and include the refresh token as well as the client credentials if required.

How do I get access and refresh token?

Request an access token by redeeming the code returned after the user granted consent. Get the access_token, refresh_token, and expires_in values from the JSON response stream. When you received an access token, the value of expires_in represents the maximum time in seconds, until the access token will expire.

What is Android interceptor?

Interceptors, according to the documentation, are a powerful mechanism that can monitor, rewrite, and retry the API call. So, when we make an API call, we can either monitor it or perform some tasks. In a nutshell, Interceptors function similarly to airport security personnel during the security check process.

Why use OAuth?

OAuth 2.0 is a secure, open data sharing standard that should be built into every app. This authentication and authorization standard protects user data by providing access to the data without revealing the user's identity or credentials.


1 Answers

i am using Protocol Buffer on another thread for getRefreshToken and successfully do it! this my code:

public class IgapRetrofitInterceptor implements Interceptor {

private boolean isRefreshing;

private TokenContainer tokenContainer = TokenContainer.getInstance();

@NotNull
@Override
public Response intercept(Chain chain) throws IOException {
    Request original = chain.request();
    Request request = chain.request();

    Request.Builder builder = request.newBuilder();
    builder.header("Authorization", tokenContainer.getToken());
    builder.header("Content-Type", "application/json");
    builder.method(original.method(), original.body());

    String token = tokenContainer.getToken();

    request = builder.build();
    Response response = chain.proceed(request);

    if (response.code() == 401) {
        synchronized (this) {
            Log.e("refreshToken", "Failed " + request.toString() + " with token -> " + tokenContainer.getToken());

            String currentToken = tokenContainer.getToken();

            if (currentToken != null && currentToken.equals(token)) {
                try {
                    getRefreshToken(); //aysnc
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

            if (tokenContainer.getToken() != null) {
                builder.header("Authorization", tokenContainer.getToken());
                request = builder.build();
                Log.e("refreshToken", "Send " + request.toString() + " again with new token -> " + tokenContainer.getToken());
                Log.e("refreshToken", "--------------------------------------------------------------------------------");
                return chain.proceed(request);
            }
        }
    }

    Log.i("refreshToken", "req 200 with token -> " + tokenContainer.getToken());

    return response;
}

public synchronized void getRefreshToken() throws InterruptedException {
    if (!isRefreshing) {

        isRefreshing = true;

        Log.e("refreshToken", "Refreshing token...");
        tokenContainer.getRefreshToken(() -> {
            synchronized (IgapRetrofitInterceptor.this) {
                isRefreshing = false;
                Log.e("refreshToken", "Proto response on success and token updated with token -> " + tokenContainer.getToken());
                IgapRetrofitInterceptor.this.notifyAll();
            }
        });
    }

    Log.e("refreshToken", "lock thread -> " + android.os.Process.getThreadPriority(android.os.Process.myTid()) + this.toString());
    this.wait();
    Log.e("refreshToken", "unlock thread -> " + android.os.Process.getThreadPriority(android.os.Process.myTid()) + this.toString());

 }
}
like image 172
Abolfazl Abbasi Avatar answered Oct 15 '22 00:10

Abolfazl Abbasi