3

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)
3
  • 1
    I just started working with google-oauth-java-client tonight, but it seems that you are not setting the callback URI correctly ("/") doesn't feel right to me. Perhaps following the Servlet authorization code flow at code.google.com/p/google-oauth-java-client/wiki/OAuth2 would be helpful. I found the sample code to be very useful, but it was for a Java client, not the servlet case. Good luck. Commented Nov 30, 2012 at 7:34
  • Nope, still didn't work, I tried localhost:8080... !! Commented Dec 2, 2012 at 16:43
  • @RichardBerger See my new edit, it still did not work :( Commented Dec 10, 2012 at 7:17

5 Answers 5

5
  1. 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.

  2. 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.

Sign up to request clarification or add additional context in comments.

Comments

2

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;
}

1 Comment

Thanks and I want to add that headers were very important for me.
0

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

Comments

0

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.

  1. 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.

  2. 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

3 Comments

Hey Richard, good advice to use client libraries, however, the preferred method for using OAuth2 on Android is the Google Play Services libraries. The original post was for webserver, so this doesn't apply, but for your case, you should consider moving to it, as it, for security as well as usability. developer.android.com/google/play-services/auth.html
David: Thanks for the update. One question - from my quick look at the reference you provided, it seems that the Google Play Services is the way to go when accessing any Google API, but not for accessing some random 3rd party API. Would that be generally correct?
Richard, you're correct. We've heard the requests for the ability to use other APIs other than Google but we have nothing to announce at this time.
0

please remove the "&response_type=token" parameter from request URL that is problem in EDIT code and your problem get solved.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.