0

We are using OAuth2 to get access to a client's access_token to manage some of their Google Locations.

Our implementation is working fine for most of our clients, but there is a user who is receiving the following response when sending an authorization_code request: { "error": "invalid_grant", "error_description": "Bad Request"}

I have seen that there are many reasons why we can receive this for refresh_token requests, but why can we receive this for the initial authorization_code request?

Our authorization server URL: https://accounts.google.com/o/oauth2/auth

The token server URL: https://oauth2.googleapis.com/token

We have asked the user to try multiple times, by first removing our application from the authorized accounts, but they still receive the invalid_grant response. The issue is also present when another user of the same company wants to authorize us for the same locations.

Edit for additional details:

We are using spring-social for getting the access token from the authorization code (I know that it is EOL, we are only using a small part of it).

Our own code:

final OAuth2ConnectionFactory<T> connectionFactory = (OAuth2ConnectionFactory<T>) this.connectionFactoryLocator
                    .getConnectionFactory();
            final String callbackUrl = "...";
// This is the failing call
            final AccessGrant accessGrant = connectionFactory.getOAuthOperations().exchangeForAccess(code, callbackUrl, null);

The relevant parts of the library call:

    public AccessGrant exchangeForAccess(String authorizationCode, String redirectUri, MultiValueMap<String, String> additionalParameters) {
        MultiValueMap<String, String> params = new LinkedMultiValueMap<String, String>();
        if (useParametersForClientAuthentication) {
            params.set("client_id", clientId);
            params.set("client_secret", clientSecret);
        }
        params.set("code", authorizationCode);
        params.set("redirect_uri", redirectUri);
        params.set("grant_type", "authorization_code");
        if (additionalParameters != null) {
            params.putAll(additionalParameters);
        }
        return postForAccessGrant(accessTokenUrl, params);
    }

    protected AccessGrant postForAccessGrant(String accessTokenUrl, MultiValueMap<String, String> parameters) {
        Map<String, Object> result = getRestTemplate().postForObject(accessTokenUrl, parameters, Map.class);
        if (result == null) {
            throw new RestClientException("access token endpoint returned empty result");
        }
        return extractAccessGrant(result);
    }

The OAuth2Template setup:

final OAuth2Template oAuth2Template = new OAuth2Template(config.getClientId(), config.getClientSecret(),
                GoogleOAuthConstants.AUTHORIZATION_SERVER_URL, GoogleOAuthConstants.TOKEN_SERVER_URL);
oAuth2Template.setUseParametersForClientAuthentication(true);

Adam Szabo
  • 11
  • 3

1 Answers1

1

After some further investigation, the invalid_grant response was a red herring in our case.

We have some post-processing handled on the same request (loading some data from Google based on that access token), and it seems that if this takes more than ~90 seconds, Google will repeat the callback (with the same authorization_code).

This resulted in us trying to re-use the authorization code - which resulted in the error responses in our logs.

So, the correct answer in our case: If you are receiving the invalid_grant - Bad Request for an authorization_code request from Google's token servers, then you might be trying to re-use the authorization_code.

Adam Szabo
  • 11
  • 3