【问题标题】:Android AccountManager, Oauth, getAccessToken() does nothing except ask for passwordAndroid AccountManager, Oauth, getAccessToken() 除了询问密码什么都不做
【发布时间】:2012-06-13 03:47:30
【问题描述】:

在这上面花了大约两天时间后,我有点慌了。虽然到目前为止,我选择了 OAuth2 而不是 OpenID,但我非常精通 Authenticate 和 Authorize 之间的区别。

我希望我的 android 应用程序提供多种方式来验证用户身份,其中之一是 google 帐户,后来还有 facebook 和 twitter 帐户。我正在尝试使用 AccountManager 类来获取 OAuth 访问令牌(目前)只需验证用户的电子邮件地址。目标是,如果用户已经在 android 设备上保存了一个 google 帐户,他们可以授权我的应用一次,甚至无需输入密码,并且永远不必从他们的 android 再次登录。

我决定使用 Google 自己的 AccountManager,因为它承诺在 Android 框架中本地处理大部分此类问题,甚至无需打开浏览器窗口。我正在使用 google API 版本 7 (Android 2.1) 的库/构建目标,这是支持 AccountManager 的第一个级别。

我已经尝试了这两种不同的方法,一种是使用 AccountManager.getAuthTokenByFeatures() 来不指定 Account 对象,另一种是使用 getAuthToken() 来指定这样的对象。

在每种情况下,调用都会完成(正如我所期望的那样),应用程序会显示一个授权对话框,询问我是否要授权该应用程序。到目前为止,一切都很好。如果我拒绝,程序会抛出我期望的异常。如果我接受,则会出现一个“Google 登录”对话框,要求我输入帐户密码。请注意,当我将帐户添加到设备时,我已经输入了密码。如果我在对话框中输入密码,则会出现“授权”等待屏幕,然后再次出现相同的对话框。奇怪的是,如果我输入正确的密码,“授权”等待屏幕似乎需要更长的时间。所以看来我无法进入我成功获取令牌的代码路径。

尽管发泄 google 不清楚 AUTH_TOKEN_TYPE 是什么或 userinfo.email URL 未记录的事实很诱人,但我真的很想了解我在这里做错了什么,然后再过去。

这是我的代码,我会对此进行监控,当然很乐意回答任何问题。现在,我将着手捕获网络流量,看看是否可以进一步了解问题所在。

这是显示身份验证屏幕 (ok) 和密码对话框 (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");
}

【问题讨论】:

  • 您使用的是 Google Api Java 客户端吗?
  • 我正在使用 google API 版本 7 (Android 2.1) 的库/构建目标,这是支持 AccountManager 的第一级。此设置与仅使用没有 google API 的 Android 2.1 是互斥的。我会更新问题。

标签: android oauth google-api


【解决方案1】:

您的问题很可能在于您传递给 getAuthTokenByFeatures 的身份验证令牌类型。由于您使用的是 oauth2,因此您需要将其添加到您的身份验证类型的开头:

String AUTH_TOKEN_TYPE = "oauth2:https://www.googleapis.com/auth/userinfo.email"

但是,我不确定您尝试使用的身份验证令牌类型是否有效。我自己只处理过日历和任务。希望这能解决,如果没有,请告诉我,我会为您找到正确的身份验证类型

【讨论】:

  • 我刚插上它就可以了。你是我的英雄。我记得在其他地方看到过 oauth2: 符号,但即使我去“Oauth2 Playground”(一个不错的工具)code.google.com/oauthplayground 唯一的问题是这种 Auth 类型没有正确的“别名”,它也没有以这种方式列出也就是说,用户被逐字询问他是否要允许应用程序“oauth2:https://...”。你碰巧知道这个有别名吗?即,如果您插入“管理您的任务”,它适用于任务 API
  • 据我所知,你不能。我相信我在某处读到他们正在努力更新此内容。
  • 你们是我的英雄,我一直在努力解决这个问题,但谷歌并不容易。不过,我确实有一个后续问题。有没有办法在“访问请求”窗口中设置对用户更友好的消息,而不是请求访问 oauth2:googleapis.com/auth/userinfo.email 或在我的情况下为 oauth2:googleapis.com/auth/calendar 的权限,您可以将其设置为显示类似“您的日历”?
猜你喜欢
  • 1970-01-01
  • 2016-08-02
  • 2011-02-12
  • 2013-08-14
  • 2012-09-11
  • 2011-10-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多