OAuth2请求中缺少参数access_token

时间:2012-09-04 22:14:22

标签: android oauth-2.0

我正在使用Apache Amber库尝试从我控制下的网站检索OAuth2访问令牌。我的客户端代码在Android下运行。

我的代码在以下示例中进行了图案化:

https://cwiki.apache.org/confluence/display/AMBER/OAuth+2.0+Client+Quickstart

在第一步中,我可以通过使用WebView浏览器提交GET请求来检索“代码”:

OAuthClientRequest request = OAuthClientRequest
 .authorizationLocation(AUTHORIZE_URL)
 .setClientId(CLIENT_ID)
 .setRedirectURI(REDIR_URL)
 .setResponseType(CODE_RESPONSE)
 .buildQueryMessage();

 webview.loadUrl(request.getLocationUri());

我使用WebViewClient回调来捕获带有“code”参数的重定向URL。到目前为止,非常好。

使用该代码,我尝试检索我的访问令牌:

OAuthClient oAuthClient = new OAuthClient(new URLConnectionClient());

OAuthClientRequest request = OAuthClientRequest
  .tokenLocation(ACCESS_TOKEN_URL)
  .setGrantType(GrantType.AUTHORIZATION_CODE)
  .setClientId(CLIENT_ID)
  .setClientSecret(CLIENT_SECRET)
  .setRedirectURI(REDIR_URL)
  .setCode(code)
  .buildBodyMessage();

GitHubTokenResponse oAuthResponse = 
  oAuthClient.accessToken(request, GitHubTokenResponse.class);

每次运行我的代码时,都会收到OAuthProblemException,其中的消息是由于缺少参数access_token而导致请求无效。

另一个StackOverflow帖子从类似的OAuth2请求中提到了此异常,在这种情况下,该请求是由跨OAuth请求的不同重定向URI引起的。但我通过使用命名常量确保我的重定向URI是相同的。这是该帖子的链接:

OAuthProblem, missing parameter access_token

现在,我可以打印出第一个请求返回的代码,并将其粘贴到从我的桌面计算机运行的curl命令中:

curl -d“code = ...& client_id = ...& client_secret = ...& grant_type = ...& redirect_uri = ...”http://my_website.com

我通过access_token从我的网站获得了一个很好的JSON响应。

为什么来自Java的调用失败,我的手动命令行成功了?

4 个答案:

答案 0 :(得分:3)

我在实现客户端和服务器时遇到了同样的问题,问题是Apache Amber(Oltu)项目中客户端示例中的一个错误:

首先你有Auth代码请求(哪个有效):

OAuthClientRequest request = OAuthClientRequest
    .authorizationLocation(AUTHORIZE_URL)
    .setClientId(CLIENT_ID)
    .setRedirectURI(REDIR_URL)
    .setResponseType(CODE_RESPONSE)
    .**buildQueryMessage**();

第二个关于访问令牌的请求(不起作用):

OAuthClientRequest request = OAuthClientRequest
    .tokenLocation(ACCESS_TOKEN_URL)
    .setGrantType(GrantType.AUTHORIZATION_CODE)
    .setClientId(CLIENT_ID)
    .setClientSecret(CLIENT_SECRET)
    .setRedirectURI(REDIR_URL)
    .setCode(code)
    .**buildBodyMessage**();

错误在于第二个请求中的buildBodyMessage()。按buildQueryMessage()更改。

答案 1 :(得分:0)

解决了我的问题。

Amber / Oltu"缺少参数access_token"错误可能意味着GitHubTokenResponse或OAuthJSONAccessTokenResponse无法以任何理由翻译响应正文。在我的情况下(使用Google+ oAuth2身份验证),响应正文未正确解析为内部参数映射。

例如: GitHubTokenResponse

 parameters = OAuthUtils.decodeForm(body);

解析form-urlencoded结果体

... OAuthJSONAccessTokenResponse 具有下一个解析功能

 parameters = JSONUtils.parseJSON(body);

这个JSONUtils.parseJSON是一个自定义的JSON解析器,它不允许来自GOOGLE +的JSON响应体并抛出JSONError(控制台未记录),

每个错误抛出解析这些参数,不是控制台可见,然后总是被抛出注定"缺少参数:access_token"或另一个"缺少参数"错误。

如果您编写自定义OAuthAccessTokenResponse,则可以查看响应正文,并编写适用于您的响应的解析器。

答案 2 :(得分:0)

这就是我遇到的以及我为使其工作所做的工作:

我很快将一个类似的例子放在一起描述: https://cwiki.apache.org/confluence/display/OLTU/OAuth+2.0+Client+Quickstart 和: svn.apache.org/repos/asf/oltu/trunk/oauth-2.0/client/src/test/java/org/apache/oltu/oauth2/client/OAuthClientTest.java

这是我执行它的命令:

java -cp .:./org.apache.oltu.oauth2.client-1.0.1-20150221.171248-36.jar OAuthClientTest

我还得到了上面提到的错误,其中包含了access_token。我最终在intellij中调试并使用if条件跟踪异常,该条件检查字符串是否以" {"字符。

在这样做时,我还将以下jar添加到我的类路径中,以便我可以更深入地调试跟踪。 ./java-json.jar (从http://www.java2s.com/Code/Jar/j/Downloadjavajsonjar.htm下载)

在下一个调试会话期间,代码实际上已开始工作。我的配偶和我最终发现根本原因是由于没有包含JSON jar。

这是有效的命令:

java -cp .:./java-json.jar:./org.apache.oltu.oauth2.client-1.0.1-20150221.171248-36.jar OAuthClientTest

答案 3 :(得分:0)

当尝试从fitbit OAuth2获取访问令牌时,我遇到了同样的问题。 buildBodyMessage()buildQueryMessage()都给了我missing parameter, access_token

我认为这与apache oauth2客户端库有关。我最终使用spring的RestTemplate发出了简单的发帖请求,并且工作正常。

HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
headers.set("Authorization", "Basic " + "MjI5TkRZOjAwNDBhNDBkMjRmZTA0OTJhNTE5NzU5NmQ1N2ZmZGEw");

MultiValueMap<String, String> map = new LinkedMultiValueMap<>();
map.add("client_id", FITBIT_CLIENT_ID);
map.add("grant_type", "authorization_code");
map.add("redirect_uri", Constants.RESTFUL_PATH + "/fitbit/fitbitredirect");
map.add("code", code);

HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<>(map, headers);

RestTemplate restTemplate = new RestTemplate();
ResponseEntity<String> response = restTemplate.postForEntity(FITBIT_TOKEN_URI, request, String.class);

log.debug("response.body: " + response.getBody());