3

我正在使用 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,缺少参数 access_token

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

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

我从我的网站获得了一个带有 access_token 的不错的 JSON 响应。

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

4

4 回答 4

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

于 2013-08-21T16:42:16.550 回答
0

在我的情况下解决了。

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

例如: GitHubTokenResponse

 parameters = OAuthUtils.decodeForm(body);

解析表单 urlencoded 结果体

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

 parameters = JSONUtils.parseJSON(body);

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

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

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

于 2014-07-26T00:57:33.880 回答
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
于 2015-04-14T06:21:32.023 回答
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());
于 2019-07-15T08:25:55.193 回答