After spending roughly two days on this, I’m getting a little rattled. Although by now, having chosen OAuth2 over OpenID, I’m pretty well versed on the difference between Authenticate and Authorize.
I want my android app to provide several ways to authenticate users, one of them is google accounts, and later also facebook and twitter accounts. I’m trying to use the AccountManager class to get an OAuth access token to (for now) just verify the user’s email address. The goal is that if the user already has a google account saved on the android device, they can authorize my app once, MAYBE even without typing a password, and never have to login again from their android.
I decided to use Google’s own AccountManager as it promised to handle much of this natively in the Android framework, without even opening a browser window. I am using the library / build target for google APIs version 7 (Android 2.1), the first level that supports AccountManager.
I have tried this two different ways, one using AccountManager.getAuthTokenByFeatures() where you do not specify an Account object, and the other using getAuthToken() where you do specify such an object.
In each case, the call completes (as I expect it to) and the application displays an authorization dialog asking if I want to authorize the app. So far, so good. If I refuse, the program throws the exception that I expect. If I accept, a “Google sign-in” dialog appears asking me for the password to the account. Note that I already entered the password when I added the account to the device. If I type the password in the dialog, there is an “Authorizing” wait screen and then the same dialog re-appears. Oddly enough, the “Authorizing” wait screen seems to take a little bit longer if I type the CORRECT password. So it appears that I cannot get to the code path where I successfully obtain the token.
As tempting as it is to vent about google not being clear about what AUTH_TOKEN_TYPE is or the fact that the userinfo.email URL is undocumented, I would really just like to learn what I am doing wrong here and move past this.
Here is my code, I will monitor this and of course be happy to answer any questions. Right now I am going to work on getting a capture of the network traffic, to see if that provides any further insight into what is going wrong.
Here are images showing the auth screen (ok) and the password dialog (less ok)
http://imageshack.us/g/707/device20120609020618.png/
public void loginToGoogle() {
System.out.println("Starting");
AccountManagerFuture<Bundle> bundleFuture =
AccountManager.get(_activity).getAuthTokenByFeatures(
"com.google",
"https://www.googleapis.com/auth/userinfo.email",
null,
_activity,
null,
null,
new AccountManagerCallback<Bundle>() {
public void run(AccountManagerFuture<Bundle> future) {
Bundle bundle;
try {
bundle = future.getResult();
for (String s : bundle.keySet()) {
System.out.println("Found key: "+ s);
}
System.out.println(bundle.getString(AccountManager.KEY_ACCOUNT_NAME));
System.out.println(bundle.getString(AccountManager.KEY_AUTHTOKEN));
//Use Token
} catch (OperationCanceledException e) {
Log.e("e", e.getMessage(), e);
System.out.println("User appears to have denied auth request");
} catch (AuthenticatorException e) {
Log.e("e", e.getMessage(), e);
} catch (IOException e) {
Log.e("e", e.getMessage(), e);
}
}
},
null);
System.out.println("Done with AccountManager call");
}
Your issue most likely lies in the Auth Token Type you pass into the getAuthTokenByFeatures. Since you’re using oauth2, you need to add it to beginning of your auth type:
However, I’m not positive that the Auth Token Type you are trying to use is valid. I’ve only dealt with calendars and tasks myself. Hope this works out, if not, just let me know and I’ll find you the right Auth type