【问题标题】:Migration from OAuth1 3L to OAuth2:从 OAuth1 3L 迁移到 OAuth2:
【发布时间】:2014-04-25 03:27:00
【问题描述】:

我正在尝试将现有的 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 标头(并且工作正常),显然除了签名、nonce 和时间戳之外,它们看起来与此迁移调用发送的相同。

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

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

【问题讨论】:

    标签: google-oauth google-oauth-java-client


    【解决方案1】:

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

    在构建基本字符串以签署迁移请求时,请确保该字符串使用 POST 方法(而不是 GET,因为在访问许多 Google API 时会使用这种方法)并且它根据migration documentation 包含所有相关的迁移参数

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

    POST&HTTPS://accounts.google.com/o/oauth2/token&client_id=YOUR_CLIENT_ID&client_secret=YOUR_CLIENT_SECRET&grant_type=urn:IETF:PARAMS:OAuth的:授予型:迁移:您好!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 spec 了解更多示例)。

    【讨论】:

    • 你能贴一个你使用的源代码的链接吗?因为我遇到了同样的错误,所以我正在使用 POST 构造字符串
    【解决方案2】:

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

    根据sign OAuth 1.0 requests 的 oAuth 文档,基本字符串由 3 个组件组成

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

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

    • 确保 HTTP 请求方法为 POST
    • 对基本 URL 进行 URL 编码
    • 确保三个 POST 正文参数 [client_id、client_secret、grant_type] 包含在规范化的请求参数中
    • 确保每个参数都单独进行 URL 编码,然后对完整的规范化请求参数字符串进行 URL 编码。所以实际上,一些参数是双 URL 编码的。在 oauth_token 的 Using OAuth with the Google Data APIs#Signing Requests 中提到了这种双重 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
    

    【讨论】:

      【解决方案3】:

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

      Authorization: Bearer 0b79bab50daca910b000d4f1a2b675d604257e42
      

      【讨论】:

      • developers.google.com/accounts/docs/OAuth_ref 的教程明确指出授权标头必须使用 OAuth 1.0。毕竟,我们从 OAuth 1.0 凭据开始。它明确显示了 Auth 标头应该是什么样子,它是 Authorization: OAuth
      • 我的错误。我以为你已经完成了迁移步骤。您问题中的授权类型看起来很奇怪。这是发送的,还是 SO 编辑打乱的?
      • 好发现,不,实际上是 grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Amigration%3Aoauth1 根据教程的示例。形式编码。但我不确定问题出在请求有效负载中......错误消息是“无效的授权标头”所以我认为它更多的是关于那个标头?但你永远不知道...
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-01-26
      • 1970-01-01
      • 1970-01-01
      • 2013-12-29
      • 1970-01-01
      相关资源
      最近更新 更多