I am working with authenticating via Google+ according to the following: https://developers.google.com/+/mobile/android/sign-in
Most of this process seems fine. The problem I'm having is that we need to get a "one-time authorization code" so that our backend servers can perform certain requests on behalf of the user, with their permission. This is covered in the section "Enable server-side api access for your app". However, for a number of reasons, our servers can cause the login to fail, even if the authorization code is valid (e.g. the user doesn't have an account corresponding to the google+ account on our servers yet, in which case they can make one).
If this happens, we might need them to login again at a later time. What I'm finding, though, is that when I perform the second login with google+, it gives me the same authorization code, even if it's already been used by our servers. I've tried disconnecting and reconnecting to the google client api, and calling GoogleApiClient.clearDefaultAccountAndReconnect()
, but no matter what I do, I seem to end up with the same authorization code. This, of course, is rejected by the server when it tries to use it, since it's already been used.
I'm wondering what I'm doing wrong here. I have the following method, which is called during the initial authentication process, and then again if a response status of 500
is detected from our server (indicating the previous call failed, presumably because the code has already been used):
private void dispatchGooglePlusAuthCodeAcquisition() {
AsyncTask<Void, Void, String> authAcquisition = new AsyncTask<Void, Void, String>() {
@Override
protected String doInBackground(Void... params) {
Bundle authPreferences = new Bundle();
mUserPermissionNeededForAuthCode = false;
authPreferences.putString(GoogleAuthUtil.KEY_REQUEST_VISIBLE_ACTIVITIES,
"");
String scopesString = Scopes.PROFILE;
WhenIWorkApplication app = (WhenIWorkApplication)WhenIWorkApplication.getInstance();
String serverClientID = app.getGoogleOAuthClientIDForPersonalServer();
String scope = "oauth2:server:client_id:" + serverClientID + ":api_scope:" + scopesString;
String code = null;
authPreferences.putBoolean(GoogleAuthUtil.KEY_SUPPRESS_PROGRESS_SCREEN, true);
try {
code = GoogleAuthUtil.getToken(
mActivity,
Plus.AccountApi.getAccountName(mGoogleApiClient),
scope,
authPreferences
);
} catch (IOException transientEx) {
// network or server error, the call is expected to succeed if you try again later.
// Don't attempt to call again immediately - the request is likely to
// fail, you'll hit quotas or back-off.
Log.d(LOGTAG, "Encountered an IOException while trying to login to Google+."
+ " We'll need to try again at a later time.");
} catch (UserRecoverableAuthException e) {
mUserPermissionNeededForAuthCode = true;
// Requesting an authorization code will always throw
// UserRecoverableAuthException on the first call to GoogleAuthUtil.getToken
// because the user must consent to offline access to their data. After
// consent is granted control is returned to your activity in onActivityResult
// and the second call to GoogleAuthUtil.getToken will succeed.
if (!mGooglePlusPermissionActivityStarted) {
mGooglePlusPermissionActivityStarted = true;
mActivity.startActivityForResult(e.getIntent(), RESULT_CODE_AUTH_CODE);
}
} catch (GoogleAuthException authEx) {
// Failure. The call is not expected to ever succeed so it should not be
// retried.
Log.e(LOGTAG, "Unable to authenticate to Google+. Call will likely never"
+ " succeed, so bailing.", authEx);
}
return code;
}
@Override
protected void onPostExecute(String aResult) {
if (aResult != null) {
// We retrieved an authorization code successfully.
if (mAPIAccessListener != null) {
mAPIAccessListener.onAuthorizationCodeGranted(aResult);
}
} else if (!mUserPermissionNeededForAuthCode) {
// If this is the case, then we didn't get authorization from the user, or something
// else happened.
if (mAPIAccessListener != null) {
mAPIAccessListener.onAuthorizationFailed();
}
Log.d(LOGTAG, "Unable to login because authorization code retrieved was null");
}
}
};
authAcquisition.execute();
So, the answer to this was a lot simpler than I imagined. Apparently, there is aclearToken()
method on the GoogleAuthUtil
class:
http://developer.android.com/reference/com/google/android/gms/auth/GoogleAuthUtil.html#clearToken%28android.content.Context,%20java.lang.String%29
public static void clearToken (Context context, String token)
Clear the specified token in local cache with respect to the Context. Note that the context must be the same as that used to initialize the token in a previous call to getToken(Context, String, String) or getToken(Context, String, String, Bundle).
Parameters
context
Context of the token.token
The token to clear.Throws
GooglePlayServicesAvailabilityException
GoogleAuthException
IOException
Calling this method before attempting to re-authenticate causes Google to generate a new one-time authorization token.
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