2014-03-19 52 views
1

我试图将现有的OAuth1.0 3L令牌迁移到OAuth2.0以获取Web应用程序。 我按照https://developers.google.com/accounts/docs/OAuth_ref 的说明尽管我尽了最大的努力,但我一直在收到此回复: “授权标头无效。”从OAuth1 3L迁移到OAuth2:

要创建授权标头,我使用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请求中的授权头(并且工作正常),显然除了签名,随机数和时间戳以外,它们看起来与通过此迁移调用发送的相同。

我甚至尝试过一个测试迁移请求,它失败了,然后使用一个调试器来运行旧代码并注入迁移调用使用的方法,URL,nonce和timestamp,并且由旧代码计算的签名是相同的,给予相同的参数。

为什么授权标头仍然报告为无效的任何线索?

回答

1

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

当构建一个基本字符串签署迁移请求,请确保该字符串使用POST方法(而不是GET,因为它访问许多谷歌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: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 spec)。

+0

你可以发布一个链接到你使用的源代码吗?因为我得到相同的错误艰难,我使用POST构造字符串 – walid

0

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

Authorization: Bearer 0b79bab50daca910b000d4f1a2b675d604257e42 
+0

https://developers.google.com/accounts/docs/OAuth_ref上的教程明确指出授权标头必须使用OAuth 1.0。毕竟,我们从OAuth 1.0凭证开始。它明确显示了Auth头文件应该是什么样子,它是授权:OAuth – SimonM

+0

我的错误。我以为你已经完成了迁移步骤。您问题中的授权类型看起来很奇怪。这是被发送的,还是被SO编辑搅乱的? – pinoyyid

+0

好点,不,实际上是 grant_type = urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Amigration%3Aoauth1根据教程的例子。表格编码。 但我不确定问题在于请求有效载荷...错误消息是“无效的授权标题”,所以我认为它更多关于该标题?但你永远不知道... – SimonM

1

生成基本字符串时,您需要确保每个单独的参数在构建基本字符串之前都经过了URL编码。

作为每OAUTH文档sign OAuth 1.0 requests基底线是由3个组件

  • HTTP请求方法
  • 基URL的请求被发送到
  • 的归一化的字符串的向上请求中的参数

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

  • 确保HTTP请求方法是POST
  • URL编码的基本URL
  • 确保三个POST身体参数[CLIENT_ID,client_secret,grant_type]被包括在归一化的请求参数
  • 确保每个参数是单独URL编码,然后URL编码完整的规范化请求参数字符串。所以实际上,一些参数是双重URL编码的。这种双重URL编码在Using OAuth with the Google Data APIs#Signing Requests提到的组oauth_token

只有做所有这些步骤之后,我才拿到了迁移请求工作,我收到一个有效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