【问题标题】:Missing parameter access_token on OAuth2 requestOAuth2 请求中缺少参数 access_token
【发布时间】:2012-08-29 14:52:14
【问题描述】:

我正在使用 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 的调用失败,而我的手动命令行却成功了?

【问题讨论】:

  • 更多信息:如果我在 Android 中滚动我自己的 HTTP POST 请求,我也会得到一个不错的 JSON 响应。我知道 Amber 库尚未正式发布,但这似乎是一个错误。我使用的是 0.31 版本。
  • 您确定要将GitHubTokenResponse 而不是OAuthJSONAccessTokenResponse 用于不是GitHub 的通用网站吗?
  • 没关系,只要我能把访问令牌转成字符串就行。事实上,我尝试使用 ...JSON... 方法,我的应用程序崩溃了。
  • 使用 .buildQueryMessage();
  • @Paul Steckler - 快速入门页面现已删除。任何备用网址?

标签: android oauth-2.0


【解决方案1】:

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

首先你有验证码请求(有效):

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()

【讨论】:

    【解决方案2】:

    在我的情况下解决了。

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

    例如: GitHubTokenResponse

     parameters = OAuthUtils.decodeForm(body);
    

    解析一个表单编码的结果体

    ...和OAuthJSONAccessTokenResponse有下一个解析函数

     parameters = JSONUtils.parseJSON(body);
    

    此 JSONUtils.parseJSON 是一个自定义 JSON 解析器,它不允许我使用来自 GOOGLE+ 的 JSON 响应正文并引发 JSONError(未记录控制台),

    解析此参数时抛出的每个错误,控制台不可见,然后总是抛出注定“缺少参数:access_token”或另一个“缺少参数”错误。

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

    【讨论】:

      【解决方案3】:

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

      我很快整理了一个类似的例子: 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
      

      【讨论】:

        【解决方案4】:

        我在尝试从 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());
        

        【讨论】:

          猜你喜欢
          • 2021-12-13
          • 2012-04-30
          • 2020-10-12
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2023-03-03
          • 2019-04-04
          • 2011-08-27
          相关资源
          最近更新 更多