我正在使用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的调用失败,我的手动命令行成功了?
答案 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());