invalid_grant trying to get OAuth token from Google
Asked Answered
C

37

238

I keep getting an invalid_grant error on trying to get an OAuth token from Google to connect to their contacts API. All the information is correct and I have triple-checked this so I'm kind of stumped.

Does anyone know what may be causing this issue? I have tried setting up a different client ID for it but I get the same result. I have tried connecting many different ways including trying the force authentication, but still the same result.

Condign answered 14/5, 2012 at 0:41 Comment(5)
for me the problem was on google credentials page...i created another one...and solved the problem....Somerset
I had this issue recently and it also happens when you try to request the first access token with refresh token again, then the invalid_grant also shows up.. I solved it by resetting the secret and then cathing the first tokens on the first request.. if I failed and tried again I would get the invalid_grant again.. first time you need to catch the tokens save and then only refresh with refresh token otherwuse you are "invalid"Sy
@Sy care to explain your process and sequence again?Pathological
@Pathological a bit late but sure, if you are getting the invalid grant error due to the same reason like me then you solve it by resetting the secret key in the google console and go through the token generation flow again with the new secret key, but don't forget to save the refresh token which is only generated once, then you can generate access tokens using the refresh token.Sy
@Sy but this you will be doing again in the next 7 days when it is revoked again. Is there a permanent or rather a long lasting way of doing this?Lollis
C
76

I ran into this problem when I didn't explicitly request "offline" access when sending the user to the OAuth "Do you want to give this app permission to touch your stuff?" page.

Make sure you specify access_type=offline in your request.

Details here: https://developers.google.com/accounts/docs/OAuth2WebServer#offline

(Also: I think Google added this restriction in late 2011. If you have old tokens from before then, you'll need to send your users to the permission page to authorize offline use.)

Collative answered 14/5, 2012 at 21:57 Comment(4)
@Adders I agree. I set access_type to offline, this error still happens.Gazehound
Go through this developers.google.com/android-publisher/authorization documentation and read everything to implementObese
@slideshowp2. were you able to resolve this? i am still getting this issue with acccess_type being offlineSwallowtail
For this api oauth2.googleapis.com/token I used 5 things and it worked client_id, client_secret, grant_type=authorization_code, code, redirect_uri but before that in oauth api, access_type=offline & response_type=code should be thereGalliwasp
T
180

Although this is an old question, it seems like many still encounter it - we spent days on end tracking this down ourselves.

In the OAuth2 spec, "invalid_grant" is sort of a catch-all for all errors related to invalid/expired/revoked tokens (auth grant or refresh token).

For us, the problem was two-fold:

  1. User has actively revoked access to our app
    Makes sense, but get this: 12 hours after revocation, Google stops sending the error message in their response: “error_description” : “Token has been revoked.”
    It's rather misleading because you'll assume that the error message is there at all times which is not the case. You can check whether your app still has access at the apps permission page.

  2. User has reset/recovered their Google password
    In December 2015, Google changed their default behaviour so that password resets for non-Google Apps users would automatically revoke all the user's apps refresh tokens. On revocation, the error message follows the same rule as the case before, so you'll only get the "error_description" in the first 12 hours. There doesn't seem to be any way of knowing whether the user manually revoked access (intentful) or it happened because of a password reset (side-effect).

Apart from those, there's a myriad of other potential causes that could trigger the error:

  1. Server clock/time is out of sync
  2. Not authorized for offline access
  3. Throttled by Google
  4. Using expired refresh tokens
  5. User has been inactive for 6 months
  6. Use service worker email instead of client ID
  7. Too many access tokens in short time
  8. Client SDK might be outdated
  9. Incorrect/incomplete refresh token

I've written a short article summarizing each item with some debugging guidance to help find the culprit.

Topflight answered 18/7, 2016 at 10:8 Comment(4)
Another scenario is if you try to get tokens multiple times form the same auth code.Unbowed
That was exactly my problem, simply revoking the app by accident. Then had to rerun the refreshToken.php through terminal to generate another authorization code and then replace the refreshToken everywhere for this clientID.Gewgaw
In my case, I changed my password a month ago. I found out that I need to give permission to the app again and get the new refresh tokenOxcart
I don't have any of the above 11 items but I still got it.Uvulitis
H
87

I ran into this same problem despite specifying the "offline" access_type in my request as per bonkydog's answer. Long story short I found that the solution described here worked for me:

https://groups.google.com/forum/#!topic/google-analytics-data-export-api/4uNaJtquxCs

In essence, when you add an OAuth2 Client in your Google API's console Google will give you a "Client ID" and an "Email address" (assuming you select "webapp" as your client type). And despite Google's misleading naming conventions, they expect you to send the "Email address" as the value of the client_id parameter when you access their OAuth2 API's.

This applies when calling both of these URL's:

Note that the call to the first URL will succeed if you call it with your "Client ID" instead of your "Email address". However using the code returned from that request will not work when attempting to get a bearer token from the second URL. Instead you will get an 'Error 400' and an "invalid_grant" message.

Haworth answered 27/9, 2013 at 0:51 Comment(10)
Absolutely ridiculous: Especially the part where it works with the client_id if you get an initial refresh token. Googles API and their documentation is a mess.Attestation
I was banging my head against this issue for so many hours. I never expected that 'client_id' was not what was expected for the 'client_id' field. Except the occasional time when you do get a refresh_token and it does work. Pretty sure the words I have for google at the moment can't be said on SO.Lucilucia
Has anyone else noticed that this behavior changed in the last couple of days? I made this change to use the email address form a couple of months ago and everything starting working fine again for a while, but now all of a sudden all calls to both URLs are failing with "The OAuth client was not found." I switched back to the client ID form and it works again, but now I'm not sure if this is going to start breaking in the way it did before.Fickle
Hi there.. Im unable to find that "email" address you guys are talking about. this is what I have in my console --> pbs.twimg.com/media/CVVcEBWUwAAIiCy.png:largeXylography
Where is that email Address? I'm having the same issueFaculty
I guess something changed here. Look at this doc : developers.google.com/analytics/devguides/reporting/core/v3/…Centeno
Never trust Google documentation. Crapiest documentation and APIs come from Google, the most valuable company in the world. I had to spend countless hours to use Google API. There were issues after issues and then their own .Net libraries for different APIs not being compiling together due to differing dependency issues and all. The code now works well for most users but for some users I still get invalid_grant, invalid_credentials etc. for no particular reasons.Hamfurd
I receive invalid_grant exception for some users while other users work fine. So if there was something wrong with the code, it should have not worked for 95% users. All these comments as to how they fixed this issue are bogus. The fact here is that Google API is one of the crappiest product I have encountered.Hamfurd
I can only confirm that I too have had these issues... some users get invalid_grant while the calls work fine for others. Using the clientid from developer console, not the email.Holeandcorner
Replacing the client_id with the user's email gives a invalid_client error. This answer seems outdated.Raeleneraf
C
76

I ran into this problem when I didn't explicitly request "offline" access when sending the user to the OAuth "Do you want to give this app permission to touch your stuff?" page.

Make sure you specify access_type=offline in your request.

Details here: https://developers.google.com/accounts/docs/OAuth2WebServer#offline

(Also: I think Google added this restriction in late 2011. If you have old tokens from before then, you'll need to send your users to the permission page to authorize offline use.)

Collative answered 14/5, 2012 at 21:57 Comment(4)
@Adders I agree. I set access_type to offline, this error still happens.Gazehound
Go through this developers.google.com/android-publisher/authorization documentation and read everything to implementObese
@slideshowp2. were you able to resolve this? i am still getting this issue with acccess_type being offlineSwallowtail
For this api oauth2.googleapis.com/token I used 5 things and it worked client_id, client_secret, grant_type=authorization_code, code, redirect_uri but before that in oauth api, access_type=offline & response_type=code should be thereGalliwasp
M
52

If you're testing this out in postman / insomnia and are just trying to get it working, hint: the server auth code (code parameter) is only good once. Meaning if you stuff up any of the other parameters in the request and get back a 400, you'll need to use a new server auth code or you'll just get another 400.

Mulligrubs answered 17/2, 2020 at 8:41 Comment(3)
Trying the same code countless time before found this answer. You saved my day. It's strange that this answer not shown on top. I need to scroll down to find this.Borghese
This was painful to learn, and to not have been more obvious in the Google docs is ... disappointing at the very least.Actress
This was the problem for me too. Thank you. Chasing my tail with the top voted answer, but none in that list covers it!Hetrick
T
9

We tried so many things, and in the end the issue was that the client had turned "Less Secure App Access" off in their Google Account settings.

To turn this on:

  1. Go to https://myaccount.google.com/ and manage account
  2. Go to the Security tab
  3. Turn Less secure app access on

enter image description here

I hope this saves someone some time!

Trapeziform answered 28/1, 2021 at 22:34 Comment(2)
Direct link: myaccount.google.com/lesssecureapps It's not working if two-factor authorization is enabled.Embroider
Google stop less secureIva
P
8

I encountered the same problem. For me, I fixed this by using Email Address (the string that ends with [email protected]) instead of Client ID for client_id parameter value. The naming set by Google is confusing here.

Paginal answered 4/12, 2014 at 7:40 Comment(1)
This is the same answer given by @Haworth more than a year earlierHomesteader
P
6

My issue was that I used this URL:

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

When I should have used this URL:

https://www.googleapis.com/oauth2/v4/token

This was testing a service account which wanted offline access to the Storage engine.

Pignut answered 12/1, 2016 at 16:55 Comment(0)
A
6

This is a silly answer, but the problem for me was that I failed to realize I already had been issued an active oAuth token for my google user which I failed to store. The solution in this case is to go to the api console and reset the client secret.

There are numerous other answers on SO to this effect for example Reset Client Secret OAuth2 - Do clients need to re-grant access?

Asante answered 10/4, 2017 at 16:40 Comment(0)
U
5

Solved by removing all Authorized redirect URIs in Google console for the project. I use server side flow when you use 'postmessage' as redirect URI

Urissa answered 14/12, 2020 at 4:49 Comment(0)
D
5

In my case I was trying to use gcloud APIs through a Go program running locally. I recently changed my user's password so I first tried gcloud auth login but it kept outputing the same invalid_grant error.

The catch is that you are not interacting directly with the api, your code is, so you have to use gcloud auth application-default login instead. That fixed it for me.

Dimaggio answered 5/2, 2023 at 20:10 Comment(0)
N
4

Using a Android clientId (no client_secret) I was getting the following error response:

{
 "error": "invalid_grant",
 "error_description": "Missing code verifier."
}

I cannot find any documentation for the field 'code_verifier' but I discovered if you set it to equal values in both the authorization and token requests it will remove this error. I'm not sure what the intended value should be or if it should be secure. It has some minimum length (16? characters) but I found setting to null also works.

I am using AppAuth for the authorization request in my Android client which has a setCodeVerifier() function.

AuthorizationRequest authRequest = new AuthorizationRequest.Builder(
                                    serviceConfiguration,
                                    provider.getClientId(),
                                    ResponseTypeValues.CODE,
                                    provider.getRedirectUri()
                            )
                            .setScope(provider.getScope())
                            .setCodeVerifier(null)
                            .build();

Here is an example token request in node:

request.post(
  'https://www.googleapis.com/oauth2/v4/token',
  { form: {
    'code': '4/xxxxxxxxxxxxxxxxxxxx',
    'code_verifier': null,
    'client_id': 'xxxxxxxxxxxxxxxxxxxxxx.apps.googleusercontent.com',
    'client_secret': null,
    'redirect_uri': 'com.domain.app:/oauth2redirect',
    'grant_type': 'authorization_code'
  } },
  function (error, response, body) {
    if (!error && response.statusCode == 200) {
      console.log('Success!');
    } else {
      console.log(response.statusCode + ' ' + error);
    }

    console.log(body);
  }
);

I tested and this works with both https://www.googleapis.com/oauth2/v4/token and https://accounts.google.com/o/oauth2/token.

If you are using GoogleAuthorizationCodeTokenRequest instead:

final GoogleAuthorizationCodeTokenRequest req = new GoogleAuthorizationCodeTokenRequest(
                    TRANSPORT,
                    JSON_FACTORY,
                    getClientId(),
                    getClientSecret(),
                    code,
                    redirectUrl
);
req.set("code_verifier", null);          
GoogleTokenResponse response = req.execute();
Nap answered 30/3, 2017 at 0:35 Comment(0)
F
4

There are two major reasons for invalid_grant error which you have to take care prior to the POST request for Refresh Token and Access Token.

  1. Request header must contain "content-type: application/x-www-form-urlencoded"
  2. Your request payload should be url encoded Form Data, don't send as json object.

RFC 6749 OAuth 2.0 defined invalid_grant as: The provided authorization grant (e.g., authorization code, resource owner credentials) or refresh token is invalid, expired, revoked, does not match the redirection URI used in the authorization request, or was issued to another client.

I found another good article, here you will find many other reasons for this error.

https://blog.timekit.io/google-oauth-invalid-grant-nightmare-and-how-to-fix-it-9f4efaf1da35

Flooring answered 27/9, 2017 at 6:39 Comment(1)
Did you mean to post two nearly identical answers? You might want to delete this one because the other has an additional line.Forfend
C
3

I had the same error message 'invalid_grant' and it was because the authResult['code'] send from client side javascript was not received correctly on the server.

Try to output it back from the server to see if it is correct and not an empty string.

Candler answered 18/5, 2014 at 8:45 Comment(0)
S
3

Try change your url for requst to

https://www.googleapis.com/oauth2/v4/token
Superposition answered 13/1, 2017 at 9:54 Comment(0)
T
3

You might have to remove a stale/invalid OAuth response.

Credit: node.js google oauth2 sample stopped working invalid_grant

Note: An OAuth response will also become invalid if the password used in the initial authorization has been changed.

If in a bash environment, you can use the following to remove the stale response:

rm /Users/<username>/.credentials/<authorization.json>

Trantrance answered 18/5, 2017 at 22:49 Comment(0)
G
3

The code you obtain in the URL after user consent has a very short expiry. Please obtain the code again and attempt to get access token within seconds (you have to hurry) and it should work. I can't find out the expiry period of code but it's literally very short.

Governorship answered 26/1, 2021 at 9:8 Comment(1)
Didn't see it any of the docs! You made my night shorter <3Snowbird
R
2

if you are using scribe library, for example to set up the offline mode, like bonkydog suggested. here is the code:

OAuthService service = new ServiceBuilder().provider(Google2Api.class).apiKey(clientId).apiSecret(apiSecret)
                .callback(callbackUrl).scope(SCOPE).offline(true)
                .build();

https://github.com/codolutions/scribe-java/

Rhapsodic answered 19/10, 2015 at 17:33 Comment(0)
B
2

In my case it was a callback URL that was different from the original request. So, callback URL should be the same for auth request and code exchange.

Bacitracin answered 22/7, 2021 at 7:0 Comment(0)
X
2

I my case I just didn't read the documentation properly because I was trying to do const { tokens } = await oauth2Client.getToken(accessToken); every time to get an authorized client instance but for the subsequent requests you only need to include the refresh_token you store after the first user auth.

oauth2Client.setCredentials({
  refresh_token: `STORED_REFRESH_TOKEN`
});
Xylotomous answered 29/10, 2021 at 17:27 Comment(0)
O
2

This can happen if your redirect_url is not the same as the one you have when creating the token on Google Gloud. So make sure it's correct

Olfe answered 10/8, 2022 at 13:48 Comment(0)
Z
2

None of the answer worked for me. After calling

https://accounts.google.com/o/oauth2/v2/auth?redirect_uri=<CALLBACK_URL_YOU_SET_ON_GOOGLE>&prompt=consent&response_type=code&client_id=<YOUR CLIENT ID>&scope=openid%20email%20profile&access_type=offline

I was getting response url in return which had code value

4%2F0ARtbsJoGfJYFT6Cy1VpPiONgYV1vIzVhGtTK9MvyQLZfuGv_sAPDRDOzqGkRu07qOIxBfg

Instead of decoding the the url received I copied this value and passed to my app API and got the reported error invalid_grant.
%2F in the above code should be replaced by /. It should be

4/0ARtbsJoGfJYFT6Cy1VpPiONgYV1vIzVhGtTK9MvyQLZfuGv_sAPDRDOzqGkRu07qOIxBfg

Note that this code works only once.

Lesson: Always decode the received url!

Zoochore answered 22/10, 2022 at 17:11 Comment(1)
Just to add, a string can be decoded in JS/NodeJS using the built-in decodeURIComponent(string). MDN.Firstfoot
G
1

in this site console.developers.google.com

this console board select your project input the oath url. the oauth callback url will redirect when the oauth success

Gottlieb answered 14/1, 2016 at 1:5 Comment(0)
M
1

After considering and trying all of the other ways here, here's how I solved the issue in nodejs with the googleapis module in conjunction with the request module, which I used to fetch the tokens instead of the provided getToken() method:

const request = require('request');

//SETUP GOOGLE AUTH
var google = require('googleapis');
const oAuthConfigs = rootRequire('config/oAuthConfig')
const googleOAuthConfigs = oAuthConfigs.google

//for google OAuth: https://github.com/google/google-api-nodejs-client
var OAuth2 = google.auth.OAuth2;
var googleOAuth2Client = new OAuth2(
    process.env.GOOGLE_OAUTH_CLIENT_ID || googleOAuthConfigs.clientId, 
    process.env.GOOGLE_OAUTH_CLIENT_SECRET || googleOAuthConfigs.clientSecret, 
    process.env.GOOGLE_OAUTH_CLIENT_REDIRECT_URL || googleOAuthConfigs.callbackUrl);

/* generate a url that asks permissions for Google+ and Google Calendar scopes
https://developers.google.com/identity/protocols/googlescopes#monitoringv3*/
var googleOAuth2ClientScopes = [
    'https://www.googleapis.com/auth/plus.me',
    'https://www.googleapis.com/auth/userinfo.email'
];

var googleOAuth2ClientRedirectURL = process.env.GOOGLE_OAUTH_CLIENT_REDIRECT_URL || googleOAuthConfigs.callbackUrl; 

var googleOAuth2ClientAuthUrl = googleOAuth2Client.generateAuthUrl({
  access_type: 'offline', // 'online' (default) or 'offline' (gets refresh_token)
  scope: googleOAuth2ClientScopes // If you only need one scope you can pass it as string
});

//AFTER SETUP, THE FOLLOWING IS FOR OBTAINING TOKENS FROM THE AUTHCODE


        const ci = process.env.GOOGLE_OAUTH_CLIENT_ID || googleOAuthConfigs.clientId
        const cs = process.env.GOOGLE_OAUTH_CLIENT_SECRET || googleOAuthConfigs.clientSecret
        const ru = process.env.GOOGLE_OAUTH_CLIENT_REDIRECT_URL || googleOAuthConfigs.callbackUrl
        var oauth2Client = new OAuth2(ci, cs, ru);

        var hostUrl = "https://www.googleapis.com";
        hostUrl += '/oauth2/v4/token?code=' + authCode + '&client_id=' + ci + '&client_secret=' + cs + '&redirect_uri=' + ru + '&grant_type=authorization_code',
        request.post({url: hostUrl}, function optionalCallback(err, httpResponse, data) {
            // Now tokens contains an access_token and an optional refresh_token. Save them.
            if(!err) {
                //SUCCESS! We got the tokens
                const tokens = JSON.parse(data)
                oauth2Client.setCredentials(tokens);

                //AUTHENTICATED PROCEED AS DESIRED.
                googlePlus.people.get({ userId: 'me', auth: oauth2Client }, function(err, response) {
                // handle err and response
                    if(!err) {
                        res.status(200).json(response);
                    } else {
                        console.error("/google/exchange 1", err.message);
                        handleError(res, err.message, "Failed to retrieve google person");
                    }
                });
            } else {
                console.log("/google/exchange 2", err.message);
                handleError(res, err.message, "Failed to get access tokens", err.code);
            }
        });

I simply use request to make the api request via HTTP as described here: https://developers.google.com/identity/protocols/OAuth2WebServer#offline

POST /oauth2/v4/token HTTP/1.1
Host: www.googleapis.com
Content-Type: application/x-www-form-urlencoded

code=4/P7q7W91a-oMsCeLvIaQm6bTrgtp7&
client_id=8819981768.apps.googleusercontent.com&
client_secret={client_secret}&
redirect_uri=https://oauth2.example.com/code&
grant_type=authorization_code
Marvel answered 4/1, 2017 at 11:25 Comment(0)
C
1

For future folks... I read many articles and blogs but had luck with solution below...

GoogleTokenResponse tokenResponse =
      new GoogleAuthorizationCodeTokenRequest(
          new NetHttpTransport(),
          JacksonFactory.getDefaultInstance(),
          "https://www.googleapis.com/oauth2/v4/token",
          clientId,
          clientSecret,
          authCode,
          "") //Redirect Url
     .setScopes(scopes)
     .setGrantType("authorization_code")
     .execute();

This blog depicts different cases in which "invalid_grant" error comes.

Enjoy!!!

Crawly answered 7/10, 2018 at 10:11 Comment(0)
M
1

for me I had to make sure that the redirect_uri is an exact match to the one in the developer console Authorised redirect URIs, that fixed it for me, I was able to debug and know what exactly was the issue after switching from https://accounts.google.com/o/oauth2/token to https://www.googleapis.com/oauth2/v4/token

I got a proper error:

{"error": "redirect_uri_mismatch",  "error_description": "Bad Request"}
Manuelmanuela answered 7/2, 2019 at 11:6 Comment(0)
G
1

I had this problem after enabling a new service API on the Google console and trying to use the previously made credentials.

To fix the problem, I had to go back to the credential page, clicking on the credential name, and clicking "Save" again. After that, I could authenticate just fine.

Godwit answered 19/5, 2019 at 18:27 Comment(0)
M
1

In my case, the issue was in my code. Mistakenly I've tried to initiate client 2 times with the same tokens. If none of the answers above helped make sure you do not generate 2 instances of the client.

My code before the fix:

def gc_service
      oauth_client = Signet::OAuth2::Client.new(client_options)
      oauth_client.code = params[:code]
      response = oauth_client.fetch_access_token!
      session[:authorization] = response
      oauth_client.update!(session[:authorization])

      gc_service = Google::Apis::CalendarV3::CalendarService.new
      gc_service.authorization = oauth_client

      gc_service
    end
primary_calendar_id = gc_service.list_calendar_lists.items.select(&:primary).first.id

gc_service.insert_acl(primary_calendar_id, acl_rule_object, send_notifications: false)

as soon as I change it to (use only one instance):

@gc_service = gc_service
primary_calendar_id = @gc_service.list_calendar_lists.items.select(&:primary).first.id

@gc_service.insert_acl(primary_calendar_id, acl_rule_object, send_notifications: false)

it fixed my issues with grant type.

Millihenry answered 26/7, 2019 at 11:58 Comment(0)
S
1

For me the issues was I had multiple clients in my project and I am pretty sure this is perfectly alright, but I deleted all the client for that project and created a new one and all started working for me ( Got this idea fro WP_SMTP plugin help support forum) I am not able to find out that link for reference

Scutage answered 9/8, 2019 at 9:40 Comment(0)
S
1

If you are sanitizing user input (For example, $_GET["code"] in php) Make sure you don't accidentally replace something in the code.

The regex I am using is now /[^A-Za-z0-9\/-]/

Sunda answered 5/1, 2020 at 9:18 Comment(0)
U
1

Look at this https://dev.to/risafj/beginner-s-guide-to-oauth-understanding-access-tokens-and-authorization-codes-2988

First you need an access_token:

$code = $_GET['code'];

$clientid = "xxxxxxx.apps.googleusercontent.com";
$clientsecret = "xxxxxxxxxxxxxxxxxxxxx";

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "https://www.googleapis.com/oauth2/v4/token");
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, "client_id=".urlencode($clientid)."&client_secret=".urlencode($clientsecret)."&code=".urlencode($code)."&grant_type=authorization_code&redirect_uri=". urlencode("https://yourdomain.com"));
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/x-www-form-urlencoded'));

curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$server_output = curl_exec($ch);
curl_close ($ch);

$server_output = json_decode($server_output);
$access_token = $server_output->access_token;
$refresh_token = $server_output->refresh_token;
$expires_in = $server_output->expires_in;

Safe the Access Token and the Refresh Token and the expire_in, in a Database. The Access Token expires after $expires_in seconds. Than you need to grab a new Access Token (and safe it in the Database) with the following Request:

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "https://www.googleapis.com/oauth2/v4/token");
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, "client_id=".urlencode($clientid)."&client_secret=".urlencode($clientsecret)."&refresh_token=".urlencode($refresh_token)."&grant_type=refresh_token");
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/x-www-form-urlencoded'));

curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$server_output = curl_exec($ch);
curl_close ($ch);

$server_output = json_decode($server_output);
$access_token = $server_output->access_token;
$expires_in = $server_output->expires_in;

Bear in Mind to add the redirect_uri Domain to your Domains in your Google Console: https://console.cloud.google.com/apis/credentials in the Tab "OAuth 2.0-Client-IDs". There you find also your Client-ID and Client-Secret.

Ultramontanism answered 11/1, 2020 at 16:8 Comment(0)
C
1

There is a undocumented timeout between when you first redirect the user to the google authentication page (and get back a code), and when you take the returned code and post it to the token url. It works fine for me with the actual google supplied client_id as opposed to an "undocumented email address". I just needed to start the process again.

Cellular answered 17/1, 2020 at 16:43 Comment(0)
P
1

For me, this was caused by subsequent getToken calls with the same code.

Namely, in NestJS my callback endpoint was decorated with @UseGuards(AuthGuard('google')) and I tried to call getToken in the callback.

Percival answered 23/4, 2021 at 20:30 Comment(0)
G
1

Creation of the new Credentials key under:

enter image description here

Was the honey for me.

from:

enter image description here

to:

enter image description here

Gaven answered 6/9, 2022 at 15:36 Comment(0)
I
1

I ran into this problem recently and eventually learned that the issue was on my side, not Google's. My locally-running UI had React.StrictMode enabled, which caused the relevant OAuth callback circuitry to render twice, failing the second time the same code was used.

If your network tab shows two requests, the first of which succeeds, perhaps this is your issue as well.

Invalidate answered 5/12, 2023 at 14:15 Comment(0)
F
0

For me, I got to remove web cookies before testing Google connect link Api.

Floatation answered 22/6, 2022 at 13:16 Comment(0)
K
0

Generating refresh and access token:

Replace the essential values (code, client_id, client_secret) inside payload.

let payload = {
  grant_type: 'authorization_code',
  code:'********FDLJli-DFJNLDLfKJ',
  client_id: '******.googleusercontent.com',
  client_secret: 'GOCS*******m5Qzg',
  redirect_uri: 'http://localhost:3000',
};

axios
  .post(`https://oauth2.googleapis.com/token`, payload, {
    headers: {
      'Content-Type': 'application/json;',
    },
  })
  .then((res: any) => {
    return res.data;
  })
  .then((response: any) => {
    console.log('refresh token: ', response);
  })
  .catch((err) => console.log('err: ', err));

You will get a response like this:

{
    access_token: "********KAjJZmv4xLvbAIHey",
    expires_in: 3599,
    id_token: "***************VeM7cfmgbvVIg",
    refresh_token: "***************VeM7cfmgbvVIg",
    scope: "https://www.googleapis.com/auth/gmail.readonly openid 
            .....
            .....
            https://mail.google.com/",
    token_type: "Bearer",
}

Save your refresh and access token. Now you can use refresh token to generate new access token! Here is an article on how you can integrate this on your react application. You can check this out for more details.

Note: Do not request again and again for refresh token. They provide it only once. I faced some issues while requesting refresh token for more than 1 time.

Kondon answered 4/3, 2023 at 8:2 Comment(0)
O
0

If you are using GoogleCredentials.getApplicationDefault() and get the invalid_grant error then you can try to re-login with gcloud auth application-default login

Olivenite answered 7/8, 2023 at 19:45 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.