Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Invalid Grant Error when using OAuth2Client set with tokens from Firebase Google Auth to make gmail requests #2353

Closed
ShehabSN opened this issue Sep 6, 2020 · 5 comments
Assignees
Labels
type: question Request for information or clarification. Not an issue.

Comments

@ShehabSN
Copy link

ShehabSN commented Sep 6, 2020

So my application uses firebase and so I've utilized Firebase's Google Auth implementation as it is very simple and firebase handles all the background work like persistence and what not. However, I plan on getting permission from the users to access their gmail and read or send emails using the https://www.googleapis.com/auth/gmail.modify scope and Firebase Cloud Functions. I've been able to successfully authenticate with Firebase with the given scopes. Upon login I get a lot of data back, including an access token, id token, refresh token, and the users google info like google id etc, as well as a lot of highly obfuscated fields. So I am assuming that what happened is Firebase handles the initial part of the authentication where they get back an authorization code and then get back an access token and id token as well as referesh token which I get access to.

With that being said, I figured I would be able to use the access and refresh tokens as well as the user's google id to make api calls to modify the emails. So this is the code that I have tested out on a node.js server.

const express = require("express");
const { google } = require("googleapis");
const app = express();

// client id and secret from autogenerated client by firebase
const oauth2Client = new google.auth.OAuth2(
	CLIENT_ID,
	CLIENT_SECRET
);

//tokens returned after auth by Firebase Google Auth
const tokens = {
	refresh_token: REFRESH_TOKEN,
	access_token: ACCESS_TOKEN,
}

oauth2Client.setCredentials(tokens);

const gmail = google.gmail({
	version: "v1",
	auth: oauth2Client,
});

//Test Route
app.get("/",  (req, res) => {
	gmail.users.messages
		.list({ userId: GOOGLE_ID })
		.then(data => {
			console.log(data);
		})
		.catch(err => console.log(err));
	res.send("Testing");
});

app.listen(PORT, () => {
	console.log(`Example app listening at http://localhost:${PORT}`);
});

When I go to the google developer console, I notice for my firebase email, an OAuth client and service account have been autogenerated by firebase which i think is expected.

When I run this code, I get an Invalid grant error. I have traced the code, it is failing when I try to get the user messages. I am not sure what is causing this? I thought perhaps google's default auth access_type was online so I made sure to set custom parameters and set it to offline so that's not the issue. These are the logs when i run this:

GaxiosError: invalid_grant
    at Gaxios._request (C:\Users\Shehab\Documents\testing-server\node_modules\gaxios\build\src\gaxios.js:89:23)
    at processTicksAndRejections (internal/process/task_queues.js:97:5)
    at async OAuth2Client.refreshTokenNoCache (C:\Users\Shehab\Documents\testing-server\node_modules\google-auth-library\build\src\auth\oauth2client.js:172:21)
    at async OAuth2Client.refreshAccessTokenAsync (C:\Users\Shehab\Documents\testing-server\node_modules\google-auth-library\build\src\auth\oauth2client.js:196:19)
    at async OAuth2Client.requestAsync (C:\Users\Shehab\Documents\testing-server\node_modules\google-auth-library\build\src\auth\oauth2client.js:367:21) {
  response: {
    config: {
      method: 'POST',
      url: 'https://oauth2.googleapis.com/token',
      data: 'refresh_token=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX',
      headers: [Object],
      params: [Object: null prototype] {},
      paramsSerializer: [Function: paramsSerializer],
      body: 'refresh_token=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX',
      validateStatus: [Function: validateStatus],
      responseType: 'json'
    },
    data: { error: 'invalid_grant', error_description: 'Bad Request' },
    headers: {
      'alt-svc': 'h3-29=":443"; ma=2592000,h3-27=":443"; ma=2592000,h3-T051=":443"; ma=2592000,h3-T050=":443"; ma=2592000,h3-Q050=":443"; ma=2592000,h3-Q046=":443"; ma=2592000,h3-Q043=":443"; ma=2592000,quic=":443"; ma=2592000; v="46,43"',
      'cache-control': 'private',
      connection: 'close',
      'content-encoding': 'gzip',
      'content-type': 'application/json; charset=utf-8',
      date: 'Sun, 06 Sep 2020 03:47:38 GMT',
      server: 'scaffolding on HTTPServer2',
      'transfer-encoding': 'chunked',
      vary: 'Origin, X-Origin, Referer',
      'x-content-type-options': 'nosniff',
      'x-frame-options': 'SAMEORIGIN',
      'x-xss-protection': '0'
    },
    status: 400,
    statusText: 'Bad Request',
    request: { responseURL: 'https://oauth2.googleapis.com/token' }
  },
  config: {
    method: 'POST',
    url: 'https://oauth2.googleapis.com/token',
    data: 'refresh_token=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX',
    headers: {
      'Content-Type': 'application/x-www-form-urlencoded',
      'User-Agent': 'google-api-nodejs-client/6.0.6',
      'x-goog-api-client': 'gl-node/13.9.0 auth/6.0.6',
      Accept: 'application/json'
    },
    params: [Object: null prototype] {},
    paramsSerializer: [Function: paramsSerializer],
    body: 'refresh_token=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX',
    validateStatus: [Function: validateStatus],
    responseType: 'json'
  },
  code: '400'
}

Any ideas?

@yoshi-automation yoshi-automation added the triage me I really want to be triaged. label Sep 6, 2020
@ShehabSN ShehabSN closed this as completed Sep 6, 2020
@ShehabSN ShehabSN reopened this Sep 6, 2020
@ShehabSN
Copy link
Author

ShehabSN commented Sep 7, 2020

I've realised the issue, the refresh token firebase provided along with the access_token has nothing to do with google but rather its own use to maintain the user's auth status in relation to firebase. So the real question here is how do I use my one time access token and id token upon initial authorization and authentication to get a google refresh token so I can continue to make authorized api calls?

@yoshi-automation yoshi-automation added the 🚨 This issue needs some love. label Sep 11, 2020
@bcoe bcoe added the type: question Request for information or clarification. Not an issue. label Sep 11, 2020
@yoshi-automation yoshi-automation removed 🚨 This issue needs some love. triage me I really want to be triaged. labels Sep 11, 2020
@fhinkel
Copy link
Contributor

fhinkel commented Dec 7, 2020

Hi @ShehabSN , thank you for the detailed bug report. Unfortunately, this issue tracker has limited visibility and scope - basically, it's just for reporting issues with the samples contained here and is only watched by the folks who work on these samples.

We are happy to help you move this bug to venues where it'll get the attention of the appropriate product teams.

I'm going to close this issue because the folks who own this repo have no actionable way to resolve it directly, but please let us know if there's anything we can do to help!

@fhinkel fhinkel closed this as completed Dec 7, 2020
@fhinkel fhinkel self-assigned this Dec 8, 2020
@vickywane
Copy link

@fhinkel i just experienced this now using the google-auth-library to access the Google Calendar API.

Here is a copy of the error log without the tokens:

GaxiosError: internal_failure at Gaxios._request (/home/victory/Desktop/office/lifechitect-backend-mvp/node_modules/gaxios/build/src/gaxios.js:89:23) at processTicksAndRejections (internal/process/task_queues.js:97:5) at async OAuth2Client.refreshTokenNoCache (/home/victory/Desktop/office/lifechitect-backend-mvp/node_modules/google-auth-library/build/src/auth/oauth2client.js:172:21) at async OAuth2Client.getRequestMetadataAsync (/home/victory/Desktop/office/lifechitect-backend-mvp/node_modules/google-auth-library/build/src/auth/oauth2client.js:259:17) at async OAuth2Client.requestAsync (/home/victory/Desktop/office/lifechitect-backend-mvp/node_modules/google-auth-library/build/src/auth/oauth2client.js:332:23) { response: { config: { method: 'POST', url: 'https://oauth2.googleapis.com/token', data: '&grant_type=refresh_token', headers: [Object], params: [Object: null prototype] {}, paramsSerializer: [Function: paramsSerializer], body: '&grant_type=refresh_token', validateStatus: [Function: validateStatus], responseType: 'json' }, data: { error: 'internal_failure', error_description: 'Internal Error' }, headers: { 'alt-svc': 'h3-29=":443"; ma=2592000,h3-T051=":443"; ma=2592000,h3-Q050=":443"; ma=2592000,h3-Q046=":443"; ma=2592000,h3-Q043=":443"; ma=2592000,quic=":443"; ma=2592000; v="46,43"', 'cache-control': 'no-cache, no-store, max-age=0, must-revalidate', connection: 'close', 'content-encoding': 'gzip', 'content-type': 'application/json; charset=utf-8', date: 'Mon, 14 Dec 2020 12:12:29 GMT', expires: 'Mon, 01 Jan 1990 00:00:00 GMT', pragma: 'no-cache', server: 'scaffolding on HTTPServer2', 'transfer-encoding': 'chunked', vary: 'Origin, X-Origin, Referer', 'x-content-type-options': 'nosniff', 'x-frame-options': 'SAMEORIGIN', 'x-xss-protection': '0' }, status: 500, statusText: 'Internal Server Error', request: { responseURL: 'https://oauth2.googleapis.com/token' } }, config: { method: 'POST', url: 'https://oauth2.googleapis.com/token', data: '&grant_type=refresh_token', headers: { 'Content-Type': 'application/x-www-form-urlencoded', 'User-Agent': 'google-api-nodejs-client/6.1.2', 'x-goog-api-client': 'gl-node/12.18.2 auth/6.1.2', Accept: 'application/json' }, params: [Object: null prototype] {}, paramsSerializer: [Function: paramsSerializer], body: 'refresh_token=&grant_type=refresh_token', validateStatus: [Function: validateStatus], responseType: 'json' }, code: '500' }

@vickywane
Copy link

It works now. I guess the Calendar API went down for few seconds

@pisoftwareptyltd
Copy link

I've realised the issue, the refresh token firebase provided along with the access_token has nothing to do with google but rather its own use to maintain the user's auth status in relation to firebase. So the real question here is how do I use my one time access token and id token upon initial authorization and authentication to get a google refresh token so I can continue to make authorized api calls?

Any luck? are you able to do that??

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: question Request for information or clarification. Not an issue.
Projects
None yet
Development

No branches or pull requests

6 participants