I am trying to get the NodeJs Gmail API Quickstart example working. At first, I was able to get the example running and receive an out put that looked like this.
INBOX
SPAM
ETC ...
I made a few changes after so that I could see messages, etc. Once that happened I started getting the following error after the prompt (It was working prior).
Authorize this app by visiting this url: https://accounts.google.com/o/oauth2/v2/auth?access_type=offline&scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fgmail.modify&response_type=code&client_id=***&redirect_uri=***
Enter the code from that page here:
I get this error code
Error retrieving access token GaxiosError: invalid_grant
at Gaxios.<anonymous> (C:\***\node_modules\gaxios\build\src\gaxios.js:73:27)
at Generator.next (<anonymous>)
at fulfilled (C:\***\node_modules\gaxios\build\src\gaxios.js:16:58)
at processTicksAndRejections (internal/process/task_queues.js:97:5) {
response: {
config: {
method: 'POST',
url: 'https://oauth2.googleapis.com/token',
data: 'code=***client_id=***&client_secret=***&redirect_uri=http***=authorization_code&code_verifier=',
headers: [Object],
params: [Object: null prototype] {},
paramsSerializer: [Function: paramsSerializer],
body: 'code=***&client_id=***&client_secret=***&redirect_uri=***&grant_type=authorization_code&code_verifier=',
validateStatus: [Function: validateStatus],
responseType: 'json'
},
data: {
error: 'invalid_grant',
error_description: 'Malformed auth code.'
},
headers: {
***,
***
},
status: 400,
statusText: 'Bad Request'
},
config: {
method: 'POST',
url: 'https://oauth2.googleapis.com/token',
data: 'code=***&client_id=***&client_secret=***&redirect_uri=***=authorization_code&code_verifier=',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'User-Agent': 'google-api-nodejs-client/3.1.2',
},
params: [Object: null prototype] {},
paramsSerializer: [Function: paramsSerializer],
body: 'code=***&client_id=***&client_secret=***&redirect_uri=***&grant_type=authorization_code&code_verifier=',
validateStatus: [Function: validateStatus],
responseType: 'json'
},
code: '400'
}
So I reverted the changes back to the original quickstart code, and I am still getting the above error. I have no idea why this is happening and would appreciate some help!
the taken of Gmail api expires really soon after you work with it
try to delete the credentials.json and start the script again .
Related
I'm trying to implement Google Oauth to get information on users who sign in with Google such as their name and profile photo.
I found this react library which seems like it can get me a code when using the flow: 'auth_code' param.
Additionally I've found these Google docs which outline how to exchange a code for an ID token which will have user information.
I can successfully retrieve a code using the react component as shown in this slightly redacted log message from my browser:
{
"code": "4/0AWtgzh4VK3QT85egP0m9Rsau_gND-FPDxpM-cPB7ocxTfNkZSCzFSbE86<redacted suffix>",
"scope": "email profile openid https://www.googleapis.com/auth/userinfo.profile https://www.googleapis.com/auth/userinfo.email",
"authuser": "0",
"prompt": "consent"
}
I then send this code to my backend which fires off the following request to the token endpoint as found in the Discovery document, mentioned in the OpenID Google docs:
try {
const resp = await axios.post("https://oauth2.googleapis.com/token", {
code: googleJWT,
client_id: getGoogleClientId(),
client_secret: googleSecret,
redirect_uri: "http://localhost:3000",
grant_type: "authorization_code"
}, {
headers: {
"Content-Type": "application/x-www-form-urlencoded"
}
})
console.log("################## posted", resp)
} catch (e) {
console.log("################## could not post")
console.log(e)
}
However, this results in an error being thrown:
error: 'unsupported_grant_type',
error_description: 'Invalid grant_type: '
even though a grant type of authorization_code is reported as supported by the Discovery document.
For completeness, here's the redacted axios config that gets printed with the above error message:
config: {
transitional: {
silentJSONParsing: true,
forcedJSONParsing: true,
clarifyTimeoutError: false
},
adapter: [Function: httpAdapter],
transformRequest: [ [Function: transformRequest] ],
transformResponse: [ [Function: transformResponse] ],
timeout: 0,
xsrfCookieName: 'XSRF-TOKEN',
xsrfHeaderName: 'X-XSRF-TOKEN',
maxContentLength: -1,
maxBodyLength: -1,
validateStatus: [Function: validateStatus],
headers: {
Accept: 'application/json, text/plain, */*',
'Content-Type': 'application/x-www-form-urlencoded',
'User-Agent': 'axios/0.26.1',
'Content-Length': 298
},
method: 'post',
url: 'https://oauth2.googleapis.com/token',
data: '{"code":"4/0AWtgzh4VK3QT85egP0m9Rsau_gND-FPDxpM-cPB7ocxTfNkZSCzFSbE86<redacted>","client_id":"221274282648-q9nrm8j61s5cba218qot926vnloua2hb.apps.googleusercontent.com","client_secret":"<redacted>","redirect_uri":"http://localhost:3000","grant_type":"authorization_code"}'
},
Why is google complaining that the provided grant type isn't supported and how can I swap this code for an ID token?
I am building a file uploader which provides the user an option to upload files from his google drive. Google picker is set up and working on the frontend (reactJS) and I have the fileID and OAuth token given by Google Picker. I send these to the backend (node.js) and have the Google Drive API over there. I followed the documentation https://developers.google.com/drive/api/v3/manage-downloads and put the oauth token in the auth param in drive.files.get, now I got the following error
Error GaxiosError: [object Object]
at Gaxios._request (/home/.../node_modules/gaxios/src/gaxios.ts:112:15)
at processTicksAndRejections (internal/process/task_queues.js:97:5) {
response: {
config: {
url: 'https://www.googleapis.com/drive/v3/files/1GqxjzMjrDdJquOPeMrFGIMngE20vTrjU?alt=media&key=ya29.6q33c6T418VuSILwq...cLKnBMKEG4vhui8K',
method: 'GET',
responseType: 'stream',
userAgentDirectives: [Array],
paramsSerializer: [Function],
headers: [Object],
params: [Object],
validateStatus: [Function],
retry: true,
retryConfig: [Object]
},
data: PassThrough {
_readableState: [ReadableState],
readable: true,
_events: [Object: null prototype],
_eventsCount: 2,
_maxListeners: undefined,
_writableState: [WritableState],
writable: false,
allowHalfOpen: true,
_transformState: [Object],
[Symbol(kCapture)]: false
},
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': 'private, max-age=0',
connection: 'close',
'content-length': '176',
'content-type': 'application/json; charset=UTF-8',
date: 'Wed, 16 Dec 2020 11:42:15 GMT',
expires: 'Wed, 16 Dec 2020 11:42:15 GMT',
server: 'UploadServer',
vary: 'Origin, X-Origin',
'x-guploader-uploadid': 'ABg5-Uw8z7O1Hpe1od4_dQF9So652TfYS0Mc1vpIu3t4DDXPzB7YvNwQAeHKCvoNBF-7m_pW9e8EHPOgrEHS84HWR7M'
},
status: 400,
statusText: 'Bad Request',
request: {
responseURL: 'https://www.googleapis.com/drive/v3/files/1GqxjzMjrDdJquOPeMrFGIMngE20vTrjU?alt=media&key=ya29.6q33c6T418VuSILwq...cLKnBMKEG4vhui8K'
}
},
config: {
url: 'https://www.googleapis.com/drive/v3/files/1GqxjzMjrDdJquOPeMrFGIMngE20vTrjU?alt=media&key=ya29.6q33c6T418VuSILwq...cLKnBMKEG4vhui8K',
method: 'GET',
responseType: 'stream',
userAgentDirectives: [ [Object] ],
paramsSerializer: [Function],
headers: {
'x-goog-api-client': 'gdcl/4.4.3 gl-node/12.19.0 auth/6.1.3',
'Accept-Encoding': 'gzip',
'User-Agent': 'google-api-nodejs-client/4.4.3 (gzip)'
},
params: {
alt: 'media',
key: 'ya29.6q33c6T418VuSILwq...cLKnBMKEG4vhui8K'
},
validateStatus: [Function],
retry: true,
retryConfig: {
currentRetryAttempt: 0,
retry: 3,
httpMethodsToRetry: [Array],
noResponseRetries: 2,
statusCodesToRetry: [Array]
}
},
code: '400'
}
Here I observed that, there's a "key" parameter but from what I understand there should be an Authorization token. I tried using the file url from POSTMAN using a GET call with Authorization Bearer but it responded with a sign in page.
Questions:
Since I provided a token, shouldn't it download the file directly?
Why isn't the file downloading on the backend?
Note: I did follow the google drive api documentation on node.js but even that prompts user sign in which shouldn't be the case.
Edit: Added the client code as well
Client side (reactjs)
<GooglePicker
clientId={"7...b.apps.googleusercontent.com"}
developerKey={"AIz...PY"}
scope={["https://www.googleapis.com/auth/drive.readonly"]}
onChange={handleFileChange}
onAuthenticate={(token) => setDownloadToken(token)}
onAuthFailed={(data) => console.log("on auth failed:", data)}
multiselect={false}
navHidden={false}
authImmediate={false}
query={"a query string like .txt or fileName"}
viewId={"PDFS"}
>
<Button variant="contained" size="small">
G-Drive
</Button>
</GooglePicker>{" "}
Node.js Code
export const googleDriveUpload = async (_, {fileID, authToken}) => {
console.log(fileID, authToken);
const drive = google.drive({version: 'v3', auth:authToken});
var dest = fs.createWriteStream('/tmp/resume.pdf');
drive.files.get({fileId: fileID, alt: 'media'},
{responseType: 'stream'}, (err, res ) => {
if (err) {
console.log("Error " ,err);
} else {
res.data.pipe(file);
console.log("Download complete");
}
});
When you define const drive = google.drive({version: 'v3', auth:XXX}), you need to assign to auth the response of the function authorize(), as shown in the quickstart for Drive API in node.js
Please follow the complete quickstart to obtain a valid authenticated client
If creating authenticating with an oAuth2 client is not what you want, there are also other options to create valid crendetials, see google-api-nodejs-client library
I am using axios in the backend nodejs and wanted to fetch the data of the movie database API.
when is send request from frontend to my nodejs API it gives Error: read ECONNRESET error. But sometimes it works properly. here is my API route :-
app.get("/api/v1/movie/details/:movieId",(req,res) => { const id = req.params.movieId;
let results = {};
axios
.get(
`/movie/${id}?api_key=${process.env.API_KEY}&language=en-US&append_to_response=videos,credits`
)
.then((response) => {
results = { ...response.data };
return res.status(200).json(results);
})
.catch((e) => {
console.log(e);
return res.status(500).json(e.message);
});});
And here is the error I am getting in console
Error: read ECONNRESET
at TLSWrap.onStreamRead (internal/stream_base_commons.js:205:27) {
errno: 'ECONNRESET',
code: 'ECONNRESET',
syscall: 'read',
config: {
url: '/movie/556984?api_key=API_KEY&language=en-US&append_to_response=videos,credits',
method: 'get',
headers: {
Accept: 'application/json, text/plain, */*',
'User-Agent': 'axios/0.20.0'
},
baseURL: 'https://api.themoviedb.org/3',
transformRequest: [ [Function: transformRequest] ],
transformResponse: [ [Function: transformResponse] ],
timeout: 0,
adapter: [Function: httpAdapter],
xsrfCookieName: 'XSRF-TOKEN',
xsrfHeaderName: 'X-XSRF-TOKEN',
maxContentLength: -1,
maxBodyLength: -1,
validateStatus: [Function: validateStatus],
data: undefined
},
I don't understand how sometimes it working but sometimes its showing this error.
But whenever I send request to directly to the movie database API from the browser (not sending to my own API) i got response everytime... please help me !!!
I've written my code some month ago, and now without changing something there is an error message and I don't know why.
My Code in a Google Cloud Function loads a picture from an AWS S3 bucket to google cloud and saves it in a bucket, which was actually working some month ago!
My code is running node.js 8:
const tmpdir = os.tmpdir();
const filePath = path.join(tmpdir, fileName);
console.log(filePath);
console.log(data);
await writeFile(filePath, data.Body);
const bucketName = "test";
console.log('test1');
let storage;
if(!storage){
storage = new Storage();
}
await storage.bucket(bucketName).upload(filePath, {
gzip: false,
metadata: {
cacheControl: "public, max-age=31536000"
}
});
console.log('test2');
console.log(`${filePath} uploaded to ${bucketName}.`);
"test1" is printed in the logs, but "test2" not.
The error I get:
function-138m28l2agh39{ Error: Could not refresh access token: Unsuccessful response status code. Request failed with status code 500
at Gaxios._request (/srv/node_modules/gaxios/build/src/gaxios.js:85:23)
at <anonymous>
at process._tickDomainCallback (internal/process/next_tick.js:229:7)
response:
{ config:
{ url: 'http://169.254.169.254/computeMetadata/v1/instance/service-accounts/default/token?scopes=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fiam%2Chttps%3A%2F%2Fwww.googleapis.com%2Fauth%2Fcloud-platform%2Chttps%3A%2F%2Fwww.googleapis.com%2Fauth%2Fdevstorage.full_control',
headers: [Object],
retryConfig: [Object],
params: [Object],
responseType: 'text',
timeout: 0,
paramsSerializer: [Function: paramsSerializer],
validateStatus: [Function: validateStatus],
method: 'GET' },
data: 'Could not fetch URI /computeMetadata/v1/instance/service-accounts/default/token?scopes=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fiam%2Chttps%3A%2F%2Fwww.googleapis.com%2Fauth%2Fcloud-platform%2Chttps%3A%2F%2Fwww.googleapis.com%2Fauth%2Fdevstorage.full_control\n',
headers:
{ connection: 'close',
'content-length': '260',
'content-type': 'text/plain; charset=utf-8',
date: 'Thu, 16 Jul 2020 14:25:37 GMT',
'x-content-type-options': 'nosniff' },
status: 500,
statusText: 'Internal Server Error',
request:
{ responseURL: 'http://169.254.169.254/computeMetadata/v1/instance/service-accounts/default/token?scopes=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fiam%2Chttps%3A%2F%2Fwww.googleapis.com%2Fauth%2Fcloud-platform%2Chttps%3A%2F%2Fwww.googleapis.com%2Fauth%2Fdevstorage.full_control' } },
config:
{ url: 'http://169.254.169.254/computeMetadata/v1/instance/service-accounts/default/token?scopes=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fiam%2Chttps%3A%2F%2Fwww.googleapis.com%2Fauth%2Fcloud-platform%2Chttps%3A%2F%2Fwww.googleapis.com%2Fauth%2Fdevstorage.full_control',
headers: { 'Metadata-Flavor': 'Google' },
retryConfig:
{ noResponseRetries: 3,
currentRetryAttempt: 3,
retry: 3,
httpMethodsToRetry: [Array],
statusCodesToRetry: [Array] },
params:
{ scopes: 'https://www.googleapis.com/auth/iam,https://www.googleapis.com/auth/cloud-platform,https://www.googleapis.com/auth/devstorage.full_control' },
responseType: 'text',
timeout: 0,
paramsSerializer: [Function: paramsSerializer],
validateStatus: [Function: validateStatus],
method: 'GET' },
code: '500' }
Did somebody face a similar issue or can somebody help? :)
Im trying to make a POST request to a FacePlusPlus API.
At the moment I'm just running app.js with node, but I keep getting an error .
My axios request inside express app:
axios({
method: "post",
url: "https://api-us.faceplusplus.com/facepp/v3/face/analyze",
headers: {
'Content-Type': "application/json",
},
data: {
'api_key': '<My api key goes here>',
'api_secret': '<My api secret goes here>',
'image_url': 'https://images.pexels.com/photos/220453/pexels-photo-220453.jpeg?w=1260&h=750&auto=compress&cs=tinysrgb'
}
})
.then(res => console.log(res))
.catch(err => console.log(err))
The Response error:
{ Error: Request failed with status code 400
at createError (/Users/Matt/webdev/test/node_modules/axios/lib/core/createError.js:16:15)
at settle (/Users/Matt/webdev/test/node_modules/axios/lib/core/settle.js:18:12)
at IncomingMessage.handleStreamEnd (/Users/Matt/webdev/test/node_modules/axios/lib/adapters/http.js:192:11)
at emitNone (events.js:110:20)
at IncomingMessage.emit (events.js:207:7)
at endReadableNT (_stream_readable.js:1047:12)
at _combinedTickCallback (internal/process/next_tick.js:102:11)
at process._tickCallback (internal/process/next_tick.js:161:9)
config:
{ adapter: [Function: httpAdapter],
transformRequest: { '0': [Function: transformRequest] },
transformResponse: { '0': [Function: transformResponse] },
timeout: 0,
xsrfCookieName: 'XSRF-TOKEN',
xsrfHeaderName: 'X-XSRF-TOKEN',
maxContentLength: -1,
validateStatus: [Function: validateStatus],
headers:
{ Accept: 'application/json, text/plain, */*',
'Content-Type': 'application/json',
'User-Agent': 'axios/0.17.1',
'Content-Length': 212 },
method: 'post',
url: 'https://api-us.faceplusplus.com/facepp/v3/face/analyze',
data: '{"api_key":"*** i removed this for question ***","api_secret":"*** i removed this for question ***","image_url":"https://images.pexels.com/photos/220453/pexels-photo-220453.jpeg?w=1260&h=750&auto=compress&cs=tinysrgb"}' }
...
...
data: { error_message: 'MISSING_ARGUMENTS: api_key' } } }
The data is obviously getting, sent, but why does it say missing argument?
Try console logging the api-key through the response and see what you get, since it is telling you it is a missing argument. Your data is a string and not an object should it be like that, just out of curiosity?