4

What is the best way to have a valid IdToken in every request?

My first bet would be an okhttpclient interceptor which adds the token to every request. But I dont know how to get a valid token inside the interceptor.

The documentation of GoogleApiClient suggest to call silentSignIn(GoogleApiClient) before every request to obtain a valid token. The problem is that I don't have access to the current connected googleapiclient inside the interceptor.

Linda Lawton - DaImTo
  • 106,405
  • 32
  • 180
  • 449
Codingmonkey
  • 43
  • 1
  • 6

2 Answers2

0

I recently faced a similar problem and i found a not very beautiful, but working solution. You can use a static variable.

  public class SessionData {

        private static String sessionId;

    public static String getSessionId() {
        return sessionId;
    }

    public static void setSessionId(String sessionId) {
        SessionData.sessionId = sessionId;
    }
    }

Then you can set the IdToken, after you get it from the Google SDK (e.g. after the user logged in).

SessionData.setSessionId(yourCurrentToken);

In the class where you declare the Retrofit.Builder, you should use the following imports (as you said, the okhttp interceptor).

import com.squareup.okhttp.Interceptor;
import com.squareup.okhttp.OkHttpClient;
import com.squareup.okhttp.Request;
import com.squareup.okhttp.Response;

And the content of the class should look like the following.

public class RestClient implements Interceptor {

    public RestClient() {

        OkHttpClient httpClient = new OkHttpClient();
        // add your other interceptors …
        // add logging as last interceptor

        httpClient.interceptors().add(this);  // <-- this adds the header with the sessionId to every request

        Retrofit restAdapter = new Retrofit.Builder()
                .baseUrl(RestConstants.BASE_URL)
                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                .addConverterFactory(GsonConverterFactory.create())
                .client(httpClient)
                .build();
    }

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

        if (SessionData.getSessionId() != null) {
            Request newRequest = originalRequest.newBuilder()
                    .header("sessionId", SessionData.getSessionId())
                    .build();
            return chain.proceed(newRequest);
        }
        return chain.proceed(originalRequest);

    }
}
Philipp Hellmayr
  • 312
  • 2
  • 11
0

GoogleApiClient simply helps you connect to Auth.GOOGLE_SIGN_IN_API and you can create multiple GoogleApiClient as long as you connect / disconnect them appropriately. In Google's sample, autoManage is configured to save you boiler plate code when using GoogleApiClient in a FragmentActivity. When you need to use it in non-UI code, assuming you are on a working thread. You can do below:

private static final GoogleSignInOptions sGso =
   new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
        .requestIdToken(SERVER_CLIENT_ID)
        .requestEmail()
        .build();

// In your interceptor code:
GoogleApiClient apiClient = new GoogleApiClient.Builder(mContext)
    .addApi(Auth.GOOGLE_SIGN_IN_API, sGso)
    .build();

try {
    ConnectionResult result = apiClient.blockingConnect();
    if (result.isSuccess()) {
        GoogleSignInResult googleSignInResult =
            Auth.GoogleSignInApi.silentSignIn(apiClient).await();
        if (googleSignInResult.isSuccess) {
            String idToken = googleSignInResult.getIdToken();
            // set to header and pass to your server
        }
        ...
    }
} finally {
    apiClient.disconnect();
}
Isabella Chen
  • 2,421
  • 13
  • 25