Yasin Kaçmaz Yasin Kaçmaz - 1 year ago 258
Android Question

Android Retrofit2 Refresh Oauth 2 Token

I am using

So i have
which authanticate user if gets 401 response.

is like that :

compile 'com.squareup.retrofit2:retrofit:2.0.0-beta4'
compile 'com.squareup.retrofit2:converter-gson:2.0.0-beta4'
compile 'com.squareup.okhttp3:okhttp:3.1.2'

And my custom
is here :

import java.io.IOException;
import okhttp3.Authenticator;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.Route;

public class CustomAuthanticator implements Authenticator {
public Request authenticate(Route route, Response response) throws IOException {

//refresh access token via refreshtoken

Retrofit client = new Retrofit.Builder()
APIService service = client.create(APIService.class);
Call<RefreshTokenResult> refreshTokenResult=service.refreshUserToken("application/json", "application/json", "refresh_token",client_id,client_secret,refresh_token);
//this is syncronous retrofit request
RefreshTokenResult refreshResult= refreshTokenResult.execute().body();
//check if response equals 400 , mean empty response
if(refreshResult!=null) {
//save new access and refresh token
// than create a new request and modify it accordingly using the new token
return response.request().newBuilder()
.header("Authorization", newaccesstoken)

//we got empty response and return null
//if we dont return null this method is trying to make so many request
//to get new access token
return null;



This is my APIService class

import retrofit2.Call;
import retrofit2.http.Body;
import retrofit2.http.Field;
import retrofit2.http.FormUrlEncoded;
import retrofit2.http.GET;
import retrofit2.http.Header;
import retrofit2.http.Headers;
import retrofit2.http.POST;
import retrofit2.http.Query;

public interface APIService {

@Headers("Cache-Control: no-cache")
public Call<RefreshTokenResult> refreshUserToken(@Header("Accept") String accept, @Header("Content-Type") String contentType, @Field("grant_type") String grantType,
@Field("client_id") String clientId, @Field("client_secret") String clientSecret, @Field("refresh_token") String refreshToken);}

I am using authanticator like that

CustomAuthanticator customAuthanticator=new CustomAuthanticator();
OkHttpClient okClient = new OkHttpClient.Builder()
Gson gson = new GsonBuilder()
Retrofit client = new Retrofit.Builder()

//then make retrofit request

So my question is : Sometimes i get new access token and continue work, requests . But sometimes i get 400 response which means empty response. So my old refresh token invalid and i cant get new token. Normally our refresh token expires in 1 year. So how i can do this. Please help me !

Answer Source

I will explain how solved this problem.

First of all the refresh token process is critical process. In my application and most of applications doing this : If refresh token fails logout current user and warn user to login .(Maybe you can retry refresh token process by 2-3-4 times by depending you)

I recreated my refresh token using HttpUrlConnection which simplest connection method. No cache , no retries , only try connection and get answer .

So this is my new refresh token process :

My refresh method

public boolean refreshToken(String url,String refresh,String cid,String csecret) throws IOException
    URL refreshUrl=new URL(url+"token");
    HttpURLConnection urlConnection = (HttpURLConnection) refreshUrl.openConnection();
    urlConnection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
    String urlParameters  = "grant_type=refresh_token&client_id="+cid+"&client_secret="+csecret+"&refresh_token="+refresh;
    // Send post request
    DataOutputStream wr = new DataOutputStream(urlConnection.getOutputStream());
    int responseCode = urlConnection.getResponseCode();
    Log.v("refresh http url","Post parameters : " + urlParameters);
    Log.v("refresh http url","Response Code : " + responseCode);
    BufferedReader in = new BufferedReader(
            new InputStreamReader(urlConnection.getInputStream()));
    String inputLine;
    StringBuffer response = new StringBuffer();

    while ((inputLine = in.readLine()) != null) {
   // handle response like retrofit, put response to POJO class by using Gson
   // you can find RefreshTokenResult class in my question

    Gson gson = new Gson();
    RefreshTokenResult refreshTokenResult=gson.fromJson(response.toString(),RefreshTokenResult.class);
        //handle new token ...
        return true;
        //cannot refresh
        Log.v("refreshtoken", "cannot refresh , response code : "+responseCode);
        return false;

In authenticate method

public Request authenticate(Route route, Response response) throws IOException {

    String userRefreshToken="your refresh token";
    String cid="your client id";
    String csecret="your client secret";
    String baseUrl="your base url"
        //refresh is successful
        String newaccess="your new access";
        return response.request().newBuilder()
                .header("Authorization", newaccess)
    else {
        //refresh failed , maybe you can logout user
        return null;
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download