12
votes

I'm trying to use the authorization flow outlined at https://developers.google.com/identity/sign-in/web/server-side-flow. I've created the credentials as indicated... with no Authorized redirect URIs specified as the doc indicates: "The Authorized redirect URI field does not require a value. Redirect URIs are not used with JavaScript APIs."

The code initiating the authorization is: Client button and callback:

<script>
$('#signinButton').click(function() {


    var auth2 = gapi.auth2.getAuthInstance(); 
    auth2.grantOfflineAccess().then(signInCallback);

});
function signInCallback(authResult) {

    console.log('sending to server');

    if (authResult['code']) {

        // Send the code to the server
        $.ajax({
          type: 'POST',
          url: 'CheckAuth',

          headers: {
            'X-Requested-With': 'XMLHttpRequest'
          },
          contentType: 'application/octet-stream; charset=utf-8',
          success: function(result) {
            // Handle or verify the server response.
          },
          processData: false,
          data: authResult['code']
        });
      } else {
        // There was an error.
      }
}
</script>

Server side (CheckAuth method to create credentials from auth code, which it receives correctly via the javascript callback):

private Credential authorize() throws Exception {
    // load client secrets
    InputStream is = new FileInputStream(clientSecretsPath_);
    InputStreamReader isr = new InputStreamReader(is);
    GoogleClientSecrets clientSecrets = GoogleClientSecrets.load(JSON_FACTORY, isr);



    String redirect_URI = "";
    GoogleTokenResponse tokenResponse =
                  new GoogleAuthorizationCodeTokenRequest(
                          httpTransport, JSON_FACTORY,
                      "https://www.googleapis.com/oauth2/v4/token",
                      clientSecrets.getDetails().getClientId(),
                      clientSecrets.getDetails().getClientSecret(),
                      token_,
                      redirect_URI)  
                      .execute();

        String accessToken = tokenResponse.getAccessToken();

        // Use access token to call API
        GoogleCredential credential = new GoogleCredential().setAccessToken(accessToken);
        return credential;

    }

The flow works correctly, up until the point my server attempts to exchange the authorization code for the token response (GoogleAuthorizationCodeTokenRequest.execute() )... the auth server returns:

400 Bad Request
{
  "error" : "invalid_request",
  "error_description" : "Missing parameter: redirect_uri"
}

Given the error, I looked in debug at the auth instance in javascript and noted what it indicated was the redirect_uri. I then updated my google credentials and specified that URI in the Authorized redirect URIs (it's the URL that accessed the javascript, as the auth server correctly returns to the specified javascript callback). With the updated credentials and the URI specified in the instantiation of GoogleAuthorizationCodeTokenRequest (String redirect_URI = "http://example.com:8080/JavascriptLocation";), the error then becomes:

400 Bad Request
{ 
  "error" : "redirect_uri_mismatch",
  "error_description" : "Bad Request"
}

I've tracked all the way through to the actual HttpRequest to the auth server (www.googleapis.com/oauth2/v4/token) and cannot tell what redirect_uri it is looking for.

Does anyone know what the value of redirect_uri should be in this case (when using grantOfflineAccess())? I'm happy to post more of the code, if that is at all helpful... just didn't want to flood the page. Thanks.

1

1 Answers

19
votes

Found a reference to "postmessage" right after posting the question... using it as the redirect_URI on the server side seems to generate a successful response from the auth server. So... setting redirect_URI="postmessage" in the code below appears to work in this situation.

GoogleTokenResponse tokenResponse =
                  new GoogleAuthorizationCodeTokenRequest(
                          httpTransport, JSON_FACTORY,
                      "https://www.googleapis.com/oauth2/v4/token",
                      clientSecrets.getDetails().getClientId(),
                      clientSecrets.getDetails().getClientSecret(),
                      token_,
                      redirect_URI) 
                      .execute();