Google oauth java 客户端获取访问令牌失败,并显示“400 Bad Request {“error”:“invalid_request”}”
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/13638758/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Google oauth java client to get an access token fails with "400 Bad Request { "error" : "invalid_request" }"
提问by Sap
I am using "web server applications" example shown here. In my callback servlet I want to retrieve an access token but I am not able to successfully do it. Following is my code
我正在使用此处显示的“Web 服务器应用程序”示例。在我的回调 servlet 中,我想检索访问令牌,但我无法成功完成。以下是我的代码
@Override
protected String getUserId(HttpServletRequest req) throws ServletException, IOException {
// return user ID
Iterator<String> iterator = req.getParameterMap().keySet().iterator();
while (iterator.hasNext()) {
String string = iterator.next();
System.out.println(string+"---++--"+req.getParameter(string));
}
GoogleAuthorizationCodeTokenRequest newTokenRequest = new GoogleAuthorizationCodeFlow.Builder(new NetHttpTransport(), new HymansonFactory(),
"2XXXXXX7218.apps.googleusercontent.com", "KugD_XXX_7vqnGZVXXXXX1M",
Collections.singleton("https://gdata.youtube.com"))
.build().newTokenRequest(req.getParameter("code"));
//GoogleAuth
GoogleTokenResponse token = newTokenRequest.setRedirectUri("/").execute();
String accessToken = token.getAccessToken();
System.out.println("accesstoken:"+accessToken);
return "";
}
After running this code I am getting following error
运行此代码后,我收到以下错误
com.google.api.client.auth.oauth2.TokenResponseException: 400 Bad Request
{
"error" : "invalid_request"
}
In a nutshell I am getting the "code" parameter(request code) I am not sure how to convert it to Access token. I have already seen Google API - request for token from Oauth2 returns "invalid_request"Google OAuth 2: response_type error on token requestbut there wan't much I could use in my code
简而言之,我得到了“代码”参数(请求代码),我不确定如何将其转换为访问令牌。我已经看到了 Google API - 来自 Oauth2 的令牌请求返回“invalid_request” Google OAuth 2: response_type error on token request但是我可以在我的代码中使用的东西不多
EDIT
编辑
The google API did not work for me so I wrote following code without using any library
谷歌 API 对我不起作用,所以我在不使用任何库的情况下编写了以下代码
URL url = new URL("https://accounts.google.com/o/oauth2/token");
connection = (HttpURLConnection) url.openConnection();
String urlParameters = "code=" + req.getParameter("code") + "&client_id=29852.apps.googleusercontent.com&client_secret=KugD_LVi_7vqnssssxxxNRBz1M"+
"&redirect_uri=https://flixomnia.com/oauth2callback&grant_type=authorization_code&scope=https://gdata.youtube.com&response_type=token";
connection.setDoOutput(true);
connection.setDoInput(true);
connection.setInstanceFollowRedirects(true);
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
connection.setRequestProperty("Authorization", "Bearer 4/q3Xh_pJI458XXXXXXXkh-lxe3-8.cmaD6o7V5BkQXE-XXXXX-edgI");
connection.setRequestProperty("Content-Length", "" + Integer.toString(urlParameters.getBytes().length));
connection.setRequestProperty("X-GData-Key", "key=AI39siXXXXXXM7tyHBvXEM1lLcORetit6QSArQ3sjelBxXXXXXXtgLSPdZPxvsF_vkntOQMnAEYAuVFqhN7oUw");
connection.setRequestProperty("GData-Version", "2");
connection.setUseCaches(false);
//com.google.gdata.client.youtube.YouTubeService service = new com.google.gdata.client.youtube.YouTubeService("","");
//YouTubeMediaGroup g = new YouTubeMediaGroup();
DataOutputStream wr = new DataOutputStream(connection.getOutputStream());
wr.writeBytes(urlParameters);
wr.flush();
InputStream inputStream = connection.getInputStream();
byte[] b = new byte[1024];
while (inputStream.read(b) != -1) {
System.out.print(new String(b));
}
System.out.println("");
wr.close();
connection.disconnect();
But still I get following error
但我仍然收到以下错误
{ "error" : "invalid_request"}
java.io.IOException: Server returned HTTP response code: 400 for URL: https://accounts.google.com/o/oauth2/token
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1615)
at sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:254)
at com.broadcastr.servlets.YouTubeCallbackService.getUserId(YouTubeCallbackService.java:168)
at com.google.api.client.extensions.servlet.auth.oauth2.AbstractAuthorizationCodeCallbackServlet.doGet(AbstractAuthorizationCodeCallbackServlet.java:130)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:621)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:225)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:168)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:98)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:927)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:407)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1001)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:579)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:312)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
at java.lang.Thread.run(Thread.java:722)
回答by Vars
In the
setRedirectUri
method in the initial code above to get the access token, theredirect_uri
is not set correctly. Theredirect_uri
that is specified at the time of client registration should be used.In the EDIT code, while sending the required parameters to the access token end-point, an unsupported parameter
response_type
is also being sent along with the request. Removing theresponse_type
parameter should solve the purpose.Also, according to the OAuth2 RFC draft, the access token end-point might also error out
invalid_request
if the request utilizes more than one mechanism to authenticate the client. So, removing theAuthorization
header to theURLConnection
should also solve the purpose.
在
setRedirectUri
上面初始代码中获取访问令牌的方法中,redirect_uri
没有正确设置。的redirect_uri
是在客户机登记时指定应该被使用。在 EDIT 代码中,在向访问令牌端点发送所需参数的同时,不支持的参数
response_type
也随请求一起发送。删除response_type
参数应该可以解决目的。此外,根据OAuth2 RFC 草案,
invalid_request
如果请求使用一种以上的机制来验证客户端,访问令牌端点也可能出错。因此,将Authorization
标题删除到URLConnection
也应该可以解决目的。
回答by Deepika
I also wasted my 2 days solving this issue. I was not able to post token request using HttpUrlConnection
. HttpClient
worked for me.
我也浪费了我 2 天的时间来解决这个问题。我无法使用HttpUrlConnection
. HttpClient
对我来说有效。
Following is working code:
以下是工作代码:
1) Value passed:
1) 传递的值:
String url = "https://accounts.google.com/o/oauth2/token";
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(1);
nameValuePairs.add(new BasicNameValuePair("grant_type", "authorization_code"));
nameValuePairs.add(new BasicNameValuePair("client_id",client_id));
nameValuePairs.add(new BasicNameValuePair("client_secret", client_secret));
nameValuePairs.add(new BasicNameValuePair("redirect_uri", "http://example.com/bin/showcase/servlet/googlecallback"));
nameValuePairs.add(new BasicNameValuePair("code", code));
StringBuffer postResult = sendPost(url, nameValuePairs);
2) Method
2) 方法
private StringBuffer sendPost(String url, List<NameValuePair> postParams)
throws Exception {
HttpPost post = new HttpPost(url);
HttpClient client = new DefaultHttpClient();
// add header
post.setHeader("Host", "accounts.google.com");
post.setHeader("Accept",
"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
post.setHeader("Accept-Language", "en-US,en;q=0.5");
post.setHeader("Connection", "keep-alive");
post.setHeader("Referer", "https://accounts.google.com/o/oauth2/token");
post.setHeader("Content-Type", "application/x-www-form-urlencoded");
post.setEntity(new UrlEncodedFormEntity(postParams));
HttpResponse response = client.execute(post);
int responseCode = response.getStatusLine().getStatusCode();
BufferedReader rd = new BufferedReader(
new InputStreamReader(response.getEntity().getContent()));
StringBuffer result = new StringBuffer();
String line = "";`enter code here`
while ((line = rd.readLine()) != null) {
result.append(line);
}
return result;
}
回答by David Primmer
Richard above is right, in setRedirectUri you need to use the full redirect URI that you specified when you registered your application. That should not be relative, but absolute. (and hopefully https)
上面的理查德是对的,在 setRedirectUri 中,您需要使用您在注册应用程序时指定的完整重定向 URI。这不应该是相对的,而是绝对的。(希望是 https)
davep
戴维普
回答by Richard Berger
In getting a Java app and an Android app to access my Oauth server, I found the two following libraries useful - but they serve different purposes - perhaps one is better suited to your needs than the other.
在让 Java 应用程序和 Android 应用程序访问我的 Oauth 服务器时,我发现以下两个库很有用 - 但它们用于不同的目的 - 也许一个比另一个更适合您的需求。
google-oauth-java-client Used in DailyMotion. https://code.google.com/p/google-oauth-java-client/, http://samples.google-oauth-java-client.googlecode.com/hg/dailymotion-cmdline-sample/instructions.htmlThis library/sample code allows you to access your own OAuth2 server from Java.
google-api-java-client Used in: Auth2 flow in Android (Latitude) http://blog.doityourselfandroid.com/2011/08/06/oauth-2-0-flow-android/This library/sample code is specifically for accessing Google APIs through OAuth2.
google-oauth-java-client 在 DailyMotion 中使用。 https://code.google.com/p/google-oauth-java-client/, http://samples.google-oauth-java-client.googlecode.com/hg/dailymotion-cmdline-sample/instructions.html此库/示例代码允许您从 Java 访问您自己的 OAuth2 服务器。
google-api-java-client 用于:Android(Latitude)中的Auth2流http://blog.doityourselfandroid.com/2011/08/06/oauth-2-0-flow-android/这个库/示例代码是专门用于通过 OAuth2 访问 Google API。
I am not sure which problem you are trying to solve, but one of those two should help. Both go through the process of exchanging a "code" for an "authToken", but in slightly different manner. RB
我不确定您要解决哪个问题,但这两个问题之一应该会有所帮助。两者都经历了将“代码”交换为“authToken”的过程,但方式略有不同。RB
回答by Manish Prajapati
please remove the "&response_type=token" parameter from request URL that is problem in EDIT code and your problem get solved.
请从编辑代码中存在问题的请求 URL 中删除“&response_type=token”参数,您的问题就会得到解决。