Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

OAuth2 "Invalid Grant" response from server

I ask my client to hit at this URL with his authorized gmail account with which he has created the google api project.

https://accounts.google.com/o/oauth2/auth?scope=https://www.googleapis.com/auth/androidpublisher&response_type=code&access_type=offline&redirect_uri=http://www.XXXXXXXX.com/oauth2callback&client_id=XXXXXX.apps.googleusercontent.com&state=profile&approval_prompt=force

and then ask him to provide me the code parameter from the redirected URL

http://www.XXXXXXXX.com/oauth2callback?code=4/jUxc2MdX0xmF-b4_I6v2SLMQMuxO.cvQLVEpcJMUXOl05ti8ZT3ZvsT9ddwI

Then i myself post this form with following info.

<form action="https://accounts.google.com/o/oauth2/token" method="post" >

<input type="hidden" name="grant_type" value="authorization_code" >
<input type="text" name="code" value="**is the one i recieved from previous step**">
<input type="hidden" name="client_id" value="XXXXXXX.apps.googleusercontent.com" >
<input type="hidden" name="client_secret" value="XXXXXXXXXXXX" >
<input type="hidden" name="redirect_uri" value="http://www.XXXXXX.com/oauth2callback" >
<input type="submit" value="Submit">

</form>

and then i get the following error

{
    "error" : "invalid_grant"
}

When i generate the code url param myself and perform the next step. i am successfully presented with following response

{
  "access_token" : "XXXXXXStBkRnGyZ2mUYOLgls7QVBxOg82XhBCFo8UIT5gM",
  "token_type" : "Bearer",
  "expires_in" : 3600,
  "refresh_token" : "XXXXXX3SEBX7F2cfrHcqJEa3KoAHYeXES6nmho"
}

But if the client generate the url param "code" then i see the invalid grant error.

My Client is in UK and i am in another country. Can anybody please confirm if it's the error because client is generating the code param in another country and i am using that code in another country ?

Thanks in advance.

like image 760
shaikh Avatar asked Dec 18 '12 20:12

shaikh


People also ask

What is an invalid grant error?

The "invalid_grant" error usually means you tried to use the same authorization code to get more than one developer token. The authorization code is the string returned after you click Accept from the URL provided by the offline credentials example, and you can only use an authorization code once.

What does invalid OAuth 2.0 access token mean?

If the access token request is invalid, such as the redirect URL didn't match the one used during authorization, then the server needs to return an error response. Error responses are returned with an HTTP 400 status code (unless specified otherwise), with error and error_description parameters.


1 Answers

I got annoyed by invalid_grant error instead of the fact that same code is getting me correct access token some times.

Shaikh's answer has guided me to correct direction.

First of all we try to get access code from:

https://accounts.google.com/o/oauth2/auth

User is directed to "Allow Permission" screen and then our app receive access code.

Using that access code we try to get access token from:

https://accounts.google.com/o/oauth2/token

In the first attempt it will return us access_token with grant_type=authorization_code, but once access_token has been provided to us, it no longer expect to receive grant_type=authorization again, instead it likes to receive grant_type=refresh_token

For fellow android developers code is as follows:

String accessToken = null, refreshToken = null;
HttpPost httppost = new HttpPost(https://accounts.google.com/o/oauth2/token);
HttpParams myParams = new BasicHttpParams();
httppost.setHeader("Content-type", "application/x-www-form-urlencoded");
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(4);
nameValuePairs.add(new BasicNameValuePair("client_id", BLOGGER_CLIENT_ID));
SharedPreferences prefs = context.getSharedPreferences(PREFERENCES_NAME, Context.MODE_PRIVATE);
String bloggerAccessToken = prefs.getString(PREFERENCES_KEY_BLOGGER_ACCESS_TOKEN, null);

if(bloggerAccessToken != null && bloggerAccessToken.length() > 0){
    nameValuePairs.add(new BasicNameValuePair("refresh_token",  prefs.getString(PREFERENCES_KEY_BLOGGER_REFRESH_TOKEN, null)));
    nameValuePairs.add(new BasicNameValuePair("grant_type",    "refresh_token"));
} else{
    nameValuePairs.add(new BasicNameValuePair("code",  prefs.getString(PREFERENCES_KEY_BLOGGER_ACCESS_CODE, null)));
    nameValuePairs.add(new BasicNameValuePair("grant_type",    "authorization_code"));
    nameValuePairs.add(new BasicNameValuePair("redirect_uri",  "http://localhost"));
}

httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
HttpClient httpClient = new DefaultHttpClient(myParams);
response = httpClient.execute(httppost);

String returnedJsonStr = EntityUtils.toString(response.getEntity());
JSONObject jsonObject = new JSONObject(returnedJsonStr);
accessToken = jsonObject.getString("access_token");
if(jsonObject.has("refresh_token"))
    refreshToken = jsonObject.getString("refresh_token");
like image 102
Sourab Sharma Avatar answered Sep 22 '22 11:09

Sourab Sharma