【问题标题】:Obtaining an access token in OAuth2在 OAuth2 中获取访问令牌
【发布时间】:2013-07-29 20:23:29
【问题描述】:

我正在尝试使用 Java 在 android 设备上获取访问令牌。

首先,我在Google API Console 中为已安装的应用程序(Android)创建了客户端ID,并设置了将请求访问令牌的包,以及SHA1 fingerprint

正如我在OAuth2ForDevices 中读到的,要获得访问令牌,我首先必须获得一个用户代码。所以我尝试使用 Aquery 发送带有 client_id 和范围的 POST 请求,如下所示:

AQuery aq = new AQuery(activity);
         aq.ajax("https://accounts.google.com/o/oauth2/device/code?" +
                "scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.email+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.profile" +
                "client_id=xxxxxxxxxxxx-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.apps.googleusercontent.com",
            JSONObject.class,new AjaxCallback<JSONObject>(){

           @Override
           public void callback(String url, JSONObject traffic_flow, AjaxStatus status) {

               publishProgress(traffic_flow.toString());

           }
    });

问题是JSONObject traffic_flow 始终为空。我也尝试过使用它(但我不认为这是正确的方法):

authToken = GoogleAuthUtil.getToken(activity, mEmail,  "audience:server:client_id:xxxxxxxxxxxx-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.apps.googleusercontent.com");

其中 mEmail 是来自 android 设备的电子邮件,但我收到了 GoogleAuthException“未知”。如何正确获取用户码?

编辑:

我终于能够使用这个获得一个身份验证令牌:

String scope = "audience:server:client_id:xxxxxxxxxxxx.apps.googleusercontent.com";
String token = GoogleAuthUtil.getToken(activity, client.getAccountName(), scope);

其中 scope 是在 Google API Console 中生成的 Web 应用程序的客户端 ID(之后我将令牌发送到我的网站并对其进行验证),客户端是 PlusClient(更多信息在 Getting started with Google+ 中)。

我已经在我的测试应用程序中获得了令牌,现在的问题是当我想将代码包含到我的新应用程序中时,我又遇到了那个丑陋的异常:

com.google.android.gms.auth.GoogleAuthException: Unknown at com.google.android.gms.auth.GoogleAuthUtil.getToken(Unknown Source)

这些应用程序的所有客户端 ID 都在同一个项目中,清单中的权限应该没问题 (GET_ACCOUNTS,USE_CREDENTIALS,AUTHENTICATE_ACCOUNTS,INTERNET,ACCESS_NETWORK_STATE)。我在新应用程序中所做的唯一更改是在创建 PlusClient 时设置范围,因为没有它它就无法工作(不知道为什么它在我的测试应用程序中没有它工作)

mPlusClient = new PlusClient.Builder(this, this, this)
            .setVisibleActivities("http://schemas.google.com/AddActivity")
            .setScopes(Scopes.PLUS_LOGIN, Scopes.PLUS_PROFILE)
            .build()

我错过了什么?

【问题讨论】:

  • 大约 2 周前,我花了一天时间让 Google Coordinate API 工作,遗憾的是,我的代码在我的工作笔记本电脑上,直到星期四我才能使用。我似乎记得这篇文章让我朝着正确的方向前进; blog.tomtasche.at/2013/05/google-oauth-on-android-using.html 祝你好运!我会喜欢这个问题,以便在我可以访问代码时提醒我签到。
  • @Robadob 谢谢你的文章,我试试看:)
  • 确保您的范围字符串采用oauth2:https://www.googleapis.com/auth/glass.timeline https://www.googleapis.com/auth/userinfo.profile 的形式,我记得这是我的问题之一。
  • 您不会通过这种方式获得访问令牌,而是获得用户代码和设备代码。此流程适用于输入能力有限的设备。你能确认这是否是你的要求吗?
  • 该文档适用于资源/输入受限的设备,例如键盘受限的控制台等。如果您只想使用 OAuth2 并在用户进行 OAuth 流程后获取访问令牌,则应使用标准 Google 登录developers.google.com/+/mobile/android/getting-started

标签: java android oauth-2.0 access-token google-oauth


【解决方案1】:

这是我用于获取 OAuth 2.0 令牌以与 Google Coordinate api 一起使用的代码,我在 ASyncTask 中运行它。我没有包含生成 DESIRED_USER 的部分,因为它在某些 AccountManager 意图上使用 startActivityForResult()。希望你可以使用它。

你应该用你的替换SCOPE,我认为应该是oauth2:https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/userinfo.profile

import android.accounts.Account;
import android.accounts.AccountManager;

final String SCOPE = "oauth2:https://www.googleapis.com/auth/coordinate";
AccountManager accountManager = AccountManager.get(context);
//Kill Current token
accountManager.invalidateAuthToken("com.google",authManager.getToken());
//Fetch userAccount
Account userAccount = null;
for(Account account : accountManager.getAccounts())
    if(account.name.equals(DESIRED_USER))
    {
        try {
            return accountManager.blockingGetAuthToken(userAccount, SCOPE, false);
        } catch (Exception e) {
            System.out.println("Error: "+e.toString());
            e.printStackTrace();
        }
    }
return null;

【讨论】:

  • 感谢您的回复,很遗憾我无法通过这种方式获取令牌 - 使用 accountManager.blockingGetAuthToken(account, "oauth2:https://www.googleapis.com/auth/userinfo.email", false); 时收到 null
  • 文档说,返回此帐户的指定类型的身份验证令牌,如果身份验证失败或无法获取任何内容,则返回 null。也许您使用的帐户没有 G+?否则我会期望它抛出一个异常。 "developer.android.com/reference/android/accounts/…, java.lang.String, boolean)
  • 从什么时候开始,GoogleAuthUtil.getToken() 方法开始为未在设备上注册的电子邮件抛出带有消息“BadUsername”的 GoogleAuthException,而不是之前带有消息“Non existing account”的异常 IllegalArgumentException '电子邮件地址'” ? developer.android.com/reference/com/google/android/gms/auth/…, java.lang.String, java.lang.String)
  • 嘿@Robadob,这曾经对我有用,但就在几天前它停止工作,现在它抛出这个错误com.google.android.gms.auth.GoogleAuthException: Unknown. 知道为什么吗?我的瞄准镜有问题吗? gist.github.com/lawloretienne/7351151
  • 你能帮我解决这个错误吗stackoverflow.com/questions/21445265/…
【解决方案2】:

如果您使用此 API,那么您应该使用 POST 版本的 AQuery 并正确传递 POST 参数,如下所示。此 API OAuth2ForDevices 适用于资源受限的设备,用户可以通过另一种方式授权您的应用程序。

params.put("scope", "your scopes");
params.put("client_id", "your client id");

AQuery aq = new AQuery(activity);
aq.ajax("https://accounts.google.com/o/oauth2/device/code", params, JSONObject.class, 
  new AjaxCallback<JSONObject>() {
           @Override
           public void callback(String url, JSONObject traffic_flow, AjaxStatus status) {
               publishProgress(traffic_flow.toString());
           }
});

但是,如果您的要求是在具有常规输入功能的 Android 手机上使用常规 OAuth2,那么 Android 的标准 OAuth 机制是 this

【讨论】:

  • 我要做的是使用访问令牌向我的网站发送请求,然后我可以使用谷歌公钥验证它,然后发回响应。我用你的方法试过了,即使OAuth2InstalledApp 有一些额外的参数,但我总是得到空响应的网络错误。我可以使用您编写的链接登录,但是可以使用它获取访问代码吗?
  • 你能帮我解决这个错误吗stackoverflow.com/questions/21445265/…
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-04-05
  • 1970-01-01
  • 1970-01-01
  • 2012-01-17
  • 2021-10-10
  • 2022-11-28
相关资源
最近更新 更多