s k
s k

Reputation: 101

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?

Upvotes: 8

Views: 3876

Answers (1)

Abolfazl Abbasi
Abolfazl Abbasi

Reputation: 355

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());

 }
}

Upvotes: 3

Related Questions