Reputation: 5291
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
@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 JacksonFactory(),
"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 request but there wan't much I could use in my code
EDIT
The google API did not work for me so I wrote following code without using any library
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)
Upvotes: 3
Views: 19669
Reputation: 21
I also wasted my 2 days solving this issue. I was not able to post token request using HttpUrlConnection
. HttpClient
worked for me.
Following is working code:
1) Value passed:
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
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;
}
Upvotes: 2
Reputation: 392
please remove the "&response_type=token" parameter from request URL that is problem in EDIT code and your problem get solved.
Upvotes: 0
Reputation: 241
In the setRedirectUri
method in the initial code above to get the access token, the redirect_uri
is not set correctly. The redirect_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 the response_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 the Authorization
header to the URLConnection
should also solve the purpose.
Upvotes: 5
Reputation: 247
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.
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.html This 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.
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
Upvotes: 0
Reputation: 421
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)
davep
Upvotes: 0