1

我正在尝试将现有的 OAuth1.0 3L 令牌迁移到 Web 应用程序的 OAuth2.0。我正在按照https://developers.google.com/accounts/docs/OAuth_ref上的说明进行操作, 尽管我尽了最大努力,但我仍然收到以下回复:“授权标头无效。”

为了创建 Authorization 标头,我使用了 Google 的 Java 客户端库 1.0,我在应用程序中使用它来与 google 日历对话。我正在使用访问令牌进行测试。可以正常工作的令牌秘密、消费者密钥和消费者秘密(即我可以使用这些凭据来调用 Google 日历等)。

这是我使用的代码:

    OAuthParameters oauthParameters = new OAuthParameters();
    oauthParameters.setOAuthConsumerKey("www.mywebsite.com"); // this is the same consumer key used by my app normally, without problem. mywebsite is an example, the real name is different
    oauthParameters.setOAuthConsumerSecret("XXXXX");
    oauthParameters.setOAuthToken("YYYYY");
    oauthParameters.setOAuthTokenSecret("ZZZZZZ");

    OAuthHmacSha1Signer signer = new OAuthHmacSha1Signer();
    OAuthHelper oauthHelper = new GoogleOAuthHelper(signer);
    String requestUrl = "https://accounts.google.com/o/oauth2/token";
    String header = oauthHelper.getAuthorizationHeader(requestUrl, "POST", oauthParameters);
    String payload = "grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Amigration%3Aoauth1&client_id="+clientId+"&client_secret="+clientSecret;

    HttpClient httpClient = new DefaultHttpClient();

    HttpPost httpPost = new HttpPost(requestUrl);
    httpPost.addHeader("Authorization", header);
    httpPost.addHeader("Content-Type", "application/x-www-form-urlencoded");
    httpPost.setEntity(new ByteArrayEntity(payload.getBytes()));
    String response = httpClient.execute(httpPost, new BasicResponseHandler());

这是 HttpClient 生成的线路跟踪:

>> "POST /o/oauth2/token HTTP/1.1[\r][\n]"
>> "Authorization: OAuth realm="", oauth_signature="ixVbjINI6pgPU2RqXGiQRbPGY%3D", oauth_nonce="486642280771700", oauth_signature_method="HMAC-SHA1", oauth_consumer_key="www.mywebsite.com", oauth_token="YYYYY", oauth_timestamp="1395127834"[\r][\n]"
>> "Content-Type: application/x-www-form-urlencoded[\r][\n]"
>> "Content-Length: 193[\r][\n]"
>> "Host: accounts.google.com[\r][\n]"
>> "Connection: Keep-Alive[\r][\n]"
>> "User-Agent: Apache-HttpClient/4.3.2 (java 1.5)[\r][\n]"
>> "[\r][\n]"
>> "grant_type=urn%ietf%params%oauth%grant-type%migration%oauth1&client_id=12345&client_secret=ABCDE"
<< "HTTP/1.1 400 Bad Request[\r][\n]"
<< "Cache-Control: no-cache, no-store, max-age=0, must-revalidate[\r][\n]"
<< "Pragma: no-cache[\r][\n]"
<< "Expires: Fri, 01 Jan 1990 00:00:00 GMT[\r][\n]"
<< "Date: Tue, 18 Mar 2014 07:30:39 GMT[\r][\n]"
<< "Content-Type: application/json[\r][\n]"
<< "X-Content-Type-Options: nosniff[\r][\n]"
<< "X-Frame-Options: SAMEORIGIN[\r][\n]"
<< "X-XSS-Protection: 1; mode=block[\r][\n]"
<< "Server: GSE[\r][\n]"
<< "Alternate-Protocol: 443:quic[\r][\n]"
<< "Transfer-Encoding: chunked[\r][\n]"
<< "[\r][\n]"
<< "5a[\r][\n]"
<< "{[\n]"
<< "  "error" : "invalid_request",[\n]"
<< "  "error_description" : "Invalid authorization header."[\n]"
<< "}"
<< "[\r][\n]"
<< "0[\r][\n]"
<< "[\r][\n]"

其中 12345 和 ABCDE 显然是真正的 OAuth2 应用程序凭据的占位符。

我已经两次和三次检查 OAuthParameters 中设置的所有参数是否与当前使用 OAuth1 工作的普通代码相同(即使使用分步调试器来验证 OAuthHmacSha1Signer 计算签名时的值.getSignature())。

我查看了当前使用 OAuth1 的 Google 客户端 API 发送的 HTTP 请求中的 Authorization 标头(并且工作正常),显然除了签名、随机数和时间戳之外,它们看起来与此迁移调用发送的相同。

我什至尝试了一个测试迁移请求,但失败了,然后使用调试器运行旧代码并注入迁移调用使用的方法、URL、nonce 和时间戳,并且旧代码计算的签名是相同的,给定相同的参数。

为什么 Authorization 标头仍被报告为无效的任何线索?

4

3 回答 3

1

生成基本字符串时,您需要确保在构造基本字符串之前对每个单独的参数进行 URL 编码。

根据签署 OAuth 1.0 请求的 oAuth 文档,基本字符串由 3 个组件组成

  • HTTP 请求方法
  • 请求发送到的基本 URL
  • 请求中参数的规范化字符串

构建基本字符串时,您需要执行以下操作

  • 确保 HTTP 请求方法是 POST
  • URL 对基本 URL 进行编码
  • 确保三个 POST 正文参数 [client_id, client_secret, grant_type] 包含在规范化的请求参数中
  • 确保每个参数都单独进行 URL 编码,然后对完整的规范化请求参数字符串进行 URL 编码。所以实际上,一些参数是双 URL 编码的。将 OAuth 与 Google 数据 API 一起使用#Signing Requests for the oauth_token中提到了这种双 URL 编码

只有在完成所有这些步骤之后,我才使迁移请求生效并且我收到了有效的 refresh_token

下面是一个示例基本字符串

POST&https%3A%2F%2Faccounts.google.com%2Fo%2Foauth2%2Ftoken&client_id%3Dxxxxxxxxxx-xxxxxxxxxxxxxxxxxxxxxxxxxx.apps.googleusercontent.com%26client_secret%3Dxxxxxxxxxxxx%26grant_type%3Durn%253Aietf%253Aparams%253Aoauth%253Agrant-type%253Amigration%253Aoauth1%26oauth_consumer_key%3Dxxxxxxxxx%26oauth_nonce%3D4106001%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1400779530%26oauth_token%3D1%252FkklP1YPy_AULt7j_tttttt_tterwerkj_dfj45dflk
于 2014-05-22T17:30:43.910 回答
1

在跟进 SimonM 之后,发现问题与用于签署迁移请求的基本字符串有关。

在构建基本字符串来签署您的迁移请求时,请确保该字符串使用POST方法(而不是 GET,因为在访问许多 Google API 时就是这种情况),并且它包含迁移文档中的所有相关迁移参数

根据OAuth1 规范,迁移请求的有效基本字符串应如下所示:

POST&https://accounts.google.com/o/oauth2/token&client_id=YOUR_CLIENT_ID&client_secret=YOUR_CLIENT_SECRET&grant_type=urn:ietf:params:oauth:grant-type:migration:oauth1&oauth_consumer_key=YOUR_CONSUMER_KEY&oauth_nonce=NONCE&oauth_signature_method=HMAC-SHA1&oauth_timestamp=1396414006&oauth_token=THE_TOKEN_TO_MIGRATE

请注意,出于可读性目的,以上是基本字符串的解码版本(查看OAuth1 规范以获取更多示例)。

于 2014-04-06T18:51:13.677 回答
0

OAuth2 中的 auth 标头是不记名令牌。它应该看起来像

Authorization: Bearer 0b79bab50daca910b000d4f1a2b675d604257e42
于 2014-03-20T12:36:41.360 回答