1

I'm using Google calendar nodejs api to create a calendar invite for an app that connects doctors with patients. Here's my code:

const defer = Q.defer();
        oauth2Client.setCredentials({
            refresh_token: options.refreshToken,
        });

        let calendar = google.calendar({
            version: "v3",
            auth: oauth2Client,
        });
        calendar.events.insert(
            {
                auth: oauth2Client,
                singleEvents: true,
                calendarId: "primary",
                resource: {
                    start: {
                        dateTime: new Date(options.startDate),
                        timeZone: "utc",
                    },
                    end: {
                        dateTime: new Date(options.endDate),
                        timeZone: "utc",
                    },
                    attendees: [
                        {
                            email: options.user.email,
                        },
                        {
                            email: options.mentor.email,
                        },
                    ],
                    reminders: {
                        useDefault: false,
                        overrides: [
                            {
                                method: "email",
                                minutes: 15,
                            },
                            {
                                method: "email",
                                minutes: 60,
                            },
                            {
                                method: "popup",
                                minutes: 10,
                            },
                        ]
                    },
                    colorId: 4,
                    sendUpdates: "all",
                    status: "confirmed",
                },
            },
            (err, res) => {
                if (err) {
                    console.dir("Error " + err);
                    defer.reject(err);
                } else {
                    defer.resolve(res.data);
                }
            }
        );
        return defer.promise;

I had the doctor go through oauth2 to get access to his Google account.

After a while, I get the error "invalid_grant" when I try to run the code above. I'm guessing the token expired, but that can't be because I'm using the refresh token in the request above not the access token and the user hasn't revoked access.

Am I supposed to refresh the token after some time? What I'm I doing wrong?

Chris Hansen
  • 7,813
  • 15
  • 81
  • 165
  • According to the [Google documentation](https://www.google.com/url?q=https://developers.google.com/identity/protocols/oauth2) there is a limit of 50 refresh tokens per account per clientId, is it possible that you hit this limitation? Anyway using refresh tokens instead of access tokens is not the way oAuth is designed. – Robert Feb 18 '22 at 19:55
  • When you say using refresh tokens instead of access tokens is not the way oauth is design, what do you mean? How do I inset an event into a user's calendar two weeks later if I can't use the refresh token. @Robert – Chris Hansen Feb 18 '22 at 20:09
  • 1
    The refresh token purpose is to receive a new access token and the access token is used to authenticate your requests. Once in a while (after days or weeks) you use the refresh token to get a new access token (and a new refresh token as the old one becomes invalid by using it). – Robert Feb 18 '22 at 20:30
  • How will I know when it's time to retrieve a new access token? What error code will google calendar insert event API return for example? @Robert Thanks for your help! – Chris Hansen Feb 18 '22 at 20:39
  • @Robert do you know what error code Google spits out to tell me its time to refresh the access token? – Chris Hansen Feb 18 '22 at 21:40
  • I assume that is just implemented in the Google auth libraries for various languages. Check them and I am sure you will find the answer. – Robert Feb 18 '22 at 22:10
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/242165/discussion-between-chris-hansen-and-robert). – Chris Hansen Feb 18 '22 at 23:40
  • Please see my answer and in the end a correction to everything @Robert has been saying. – Linda Lawton - DaImTo Feb 19 '22 at 11:26

1 Answers1

2

refreshing access.

The client library you are using will handle refreshing your access token as long as there is a valid refresh token available to it. Access tokens expire after one hour. So its probably refreshing it without you realising it.

Anwser: invalid_grant error

invalid_grant its most often caused these days because your refresh token has expired. Refresh tokens for apps that are still in the testing phase expire after seven days.

They key here is going to be to set your app in to production. Once the app is in production your refresh token will no longer expire.

enter image description here

Clearing up confusing caused in comments

there is a limit of 50 refresh tokens per account per clientId,

This statement is unclear. There is a limit of 50 outstanding refresh tokens "per user + per client". The missing key here is the+.

  • There is no limit to the number of Users your application can authorize - - There is no limit to the number of refresh tokens your application can create.
  • There is a limit to the number of outstanding refresh tokens a user can have to an application.

When I run your app I get a refresh token, If : run it again and show the consent screen and authorize it again I now have two refresh tokens. They will both work. I can do this up to 50 times at which point I now have 50 outstanding working refresh tokens. if I do it again then the first one will be expired and I will again have 50 outstanding refresh tokens.

The actual comment from googles documentation is oauth2

There is currently a limit of 50 refresh tokens per Google Account per OAuth 2.0 client ID.

The key here being per Google Account per OAuth 2.0 client ID Each user has a google account. Refresh tokens are based upon the users google account and the client id for the app requesting authorization.

Refresh tokens expiring

After the app is no longer in test. Refresh tokens for the most part do not expire. The key here is most part as long as you use it at least once every six months it will not expire. As long as the user does not revoke the access of the app it will continue to work.

Linda Lawton - DaImTo
  • 106,405
  • 32
  • 180
  • 449
  • The quote from my comment about the 50 refresh tokens you say "is not true" is a quote from Google (so you say Google documentation is lying?). And if the 51th refresh token invalidates the first this means you can only have 50 refresh tokens, so the number of refresh tokens is limited. – Robert Feb 19 '22 at 12:02
  • I have just updated my answer and copied the line you have miss interpreted. 51 is user based. Its the number of times a single user has authorized the app. Its not the number of users in the app. I have apps with tens of thousands of users all using the same client id. Each one of those user should potentially have 50 outstanding refresh tokens and they would all work. – Linda Lawton - DaImTo Feb 19 '22 at 12:31
  • @Robert here is a question from 2014 the answer is valid to this discussion. [Google API refresh token limit](https://stackoverflow.com/a/26136111/1841839) – Linda Lawton - DaImTo Feb 19 '22 at 12:37