I've followed the guides on https://developers.google.com/ and I can get the Google ID token of the signed in user after the user signed in. But I noticed that the token will expire in 1 hour. I cannot find any official reference that tells me how to deal with expired Google ID token, so I can only ask the user to click the Google sign-in button again.
How can I refresh a valid Google ID token after the old one expires, without bothering user to manually sign in again and again?
You can refresh an Identity Platform ID token by issuing an HTTP POST request to the securetoken.googleapis.com endpoint. The refresh token's grant type, always "refresh_token".
To refresh your access token as well as an ID token, you send a token request with a grant_type of refresh_token . Be sure to include the openid scope when you want to refresh the ID token. If the refresh token is valid, then you get back a new access and the refresh token.
You can refresh access and ID tokens using the /token endpoint with the grant_type set to refresh_token . Before calling this endpoint, obtain the refresh token from the SDK and ensure that you have included offline_access as a scope in the SDK configurations.
When does a refresh token expire ? Refresh tokens do not expire, unless there are few special conditions : The user has removed your Google application. The refresh token has not been used for six months.
Yes, Google ID tokens are issued for one hour validity and will expire, you can simply use silentSignIn in your app to get a new one without any user interaction. If your existing token hasn't expired yet, you will get the (cached) version back (OptionalPendingResult
returned will have isDone() == true
); if it expired already, you will get a refreshed one (but it will take a little longer and thus OptionalPendingResult isDone()
will be false
).
Here is sample code (UI thread, see note below about a worker thread):
GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
.requestIdToken(getString(R.string.server_client_id))
mGoogleApiClient = new GoogleApiClient.Builder(this)
.enableAutoManage(this /* FragmentActivity */, this /* OnConnectionFailedListener */)
.addApi(Auth.GOOGLE_SIGN_IN_API, gso)
.build();
...
OptionalPendingResult<GoogleSignInResult> opr = Auth.GoogleSignInApi.silentSignIn(mGoogleApiClient);
if (opr.isDone()) {
// If the user's cached credentials are valid, the OptionalPendingResult will be "done"
// and the GoogleSignInResult will be available instantly.
Log.d(TAG, "Got cached sign-in");
GoogleSignInResult result = opr.get();
handleSignInResult(result); // result.getSignInAccount().getIdToken(), etc.
} else {
// If the user has not previously signed in on this device or the sign-in has expired,
// this asynchronous branch will attempt to sign in the user silently. Cross-device
// single sign-on will occur in this branch.
opr.setResultCallback(new ResultCallback<GoogleSignInResult>() {
@Override
public void onResult(GoogleSignInResult googleSignInResult) {
handleSignInResult(googleSignInResult); // result.getSignInAccount().getIdToken(), etc.
}
});
}
Keep in mind whether you call silentSignIn
on a UI thread or worker thread. If you call it on worker thread, take a look at this post with blockingConnect()
+ await()
which simplifies the code a lot:
Silent sign in to retrieve token with GoogleApiClient
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With