Question

I'm using Google OAuth2 client-side to authorize a web-app (Liferay Portlet) to use the Calendar Service.

  • On my Development Server, the whole flow completes successfully:

    1. I start creating a GoogleAuthorizationCodeRequestUrl
    2. Using com.google.api.client.extensions.jetty.auth.oauth2.LocalServerReceiver I create a new redirect URI and set it to wait for Google Response.
    3. a new window/tab opens in user's browser, to googleAuthorizationCodeRequestUrl
    4. user Logs in (if not already logged)
    5. User authorizes the requested scopes
    6. the tab closes automatically, the jetty's Callback URI is fetched from Google,
    7. The flow continues with token exchange etc

  • But when Deploying on some other remote server (identical environment) the flow gets stuck in step 6. Google seems to be unable to find the redirect_uri. My browsers are landing on an error page, informing that they couldn't establish a connection to the server at localhost:[random port generated from jetty]

Checking the logs, I can see that in both cases (dev/remote server), the redirect_uri created by jetty is localhost:[5digits]/Callback. (not affected by the dns or ip on the remote server) Is this normal ? Did I miss something on the configuration? Maybe jetty was supposed to create another redirect URI, that I should additionally add from Google Dev Console (obviously I cant set to localhost..)

Is it possible that a firewall or proxy setting is blocking the redirect_url?

Any other ideas what I did wrong?

EDIT: posting some code for the URLs creation

GoogleAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow.Builder(httpTransport, jsonFactory, secrets, scopes)
 .setDataStoreFactory(dataStore).build();

 Credential credents = flow.loadCredential(usermail);
 String redirect_url = null;

 // Checking if the given user is not authorized
 if (credents == null) {
     // Creating a local receiver
     LocalServerReceiver receiver = new LocalServerReceiver();
     try {
         // Getting the redirect URI
         String redirectUri = receiver.getRedirectUri();

         // Creating a new authorization URL
         AuthorizationCodeRequestUrl authorizationUrl = flow.newAuthorizationUrl();

         // Setting the redirect URI
         authorizationUrl.setRedirectUri(redirectUri);

         // Building the authorization URL
         String url = authorizationUrl.build();

         // Logging a short message
         log.info("Creating the authorization URL : " + url);

         //This url will be fetched right after, as a button callback (target:_blank)
         //by using :FacesContext.getCurrentInstance().getExternalContext().redirect(googleAuthUrl);
         googleAuthUrl = url;


         // Receiving authorization code
         String code = receiver.waitForCode();

         // Exchanging it for an access token
         TokenResponse response = flow.newTokenRequest(code).setRedirectUri(redirectUri).execute();

         // Storing the credentials for later access
         credents = flow.createAndStoreCredential(response, id);


     } finally {
         // Releasing resources
         receiver.stop();
     }
 }

 // Setting up the calendar service client
 client = new com.google.api.services.calendar.Calendar.Builder(httpTransport, jsonFactory, credents).setApplicationName(APPLICATION_NAME)
         .build();
Was it helpful?

Solution

Instead of creating an instance of LocalServerReceiver by this:

// Creating a local receiver
LocalServerReceiver receiver = new LocalServerReceiver();

You should do this by using a LocalServerReceiver.Builder.

According to documentation non-parameter constructor is: Constructor that starts the server on "localhost" selects an unused port.

So you can use builder, set proper host name (remote server) and build LocalServerReceiver instance. (or you can use LocalServerReceiver(host, port) constructor)

This should set redirect_uri to proper address.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top