Reputation: 3
I have been using k6 to load test a web application where I need to access gmail inbox for parsing. As googleapis and axios are not supported in k6 I created http requests using k6/http module. I was able to retrieve the access token but couldn't access the mail inbox. Struck with this error
INFO[0001] {"error":{"code":401,"message":"Request is missing required authentication credential. Expected OAuth 2 access token, login cookie or other valid authentication credential. See https://developers.google.com/identity/sign-in/web/devconsole-project.","errors":\[{"message":"Login Required.","domain":"global","reason":"required","location":"Authorization","locationType":"header"}],"status":"UNAUTHENTICATED","details":[{"domain":"googleapis.com","metadata":{"service":"gmail.googleapis.com","method":"caribou.api.proto.MailboxService.ListMessages"},"@type":"type.googleapis.com/google.rpc.ErrorInfo","reason":"CREDENTIALS_MISSING"}]}}
This is the manually written access token retrieval part
const payload = `client_id=${clientId}&client_secret=${clientSecret}&refresh_token=${refreshToken}&grant_type=refresh_token`;
const tokenResponse = http.post(tokenUrl, payload, {
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
});
const accessToken = tokenResponse.json().access_token;
It logged the accestoken in the console
const options = {
url: 'https://gmail.googleapis.com/gmail/v1/users/[email protected]/messages',
params: {
q: `from:[email protected] to:${profilesEmailAddress}`,
},
headers: {
Authorization: `Bearer ${accessToken.access_token}`,
},
};
const response = http.get(options.url, options.params, options.headers);
This is used to access the gmail inbox where I used http.get() instead of axios(). It couldn't access the mail inbox and returns the error mentioned above. Can someone help me with this? What am I doing wrong? Why it isn't able to access the mail body? I was able to get a response in Postman with the same logic cURL command.
curl -X GET \
'https://gmail.googleapis.com/gmail/v1/users/[email protected]/messages?q=from%3Ano-reply%40rework.link%20to%[email protected]' \
-H 'Authorization: Bearer <access_token>'
Thanks.
Upvotes: 0
Views: 172
Reputation: 3
Thanks for the heads-up. Its actually working now, I did little changes to the http.get() method as it accepts only two parameters inside the method, I referred from the documentation.
const options = {
url: 'https://gmail.googleapis.com/gmail/v1/users/[email protected]/messages',
params: {
// q: `from:[email protected] to:${profilesEmailAddress}`,
// },
headers: {
Authorization: `Bearer ${accessToken.access_token}`,
},
}
};
const response = await http.get('https://gmail.googleapis.com/gmail/v1/users/[email protected]/messages?q=from:[email protected]%20to:[email protected]', options.params);
I inserted the query to the link to get the specified mail.
Upvotes: 0
Reputation: 265717
It looks like you are accessing your access token incorrectly: you try to access a non-existent property of a string (accessToken.access_token
). accessToken
already is the token, not an object. Can you log the value of options.headers.Authorization
and does it match your expected value?
Additionally, you are not passing the headers correctly, they must be passed as property of the options argument ({ headers: { … } }
), but you are passing an options argument without a headers key, passing the headers themselves as options ({ … }
).
The following fixed and simplified code should work:
const payload = `client_id=${clientId}&client_secret=${clientSecret}&refresh_token=${refreshToken}&grant_type=refresh_token`;
const tokenResponse = http.post(tokenUrl, {
client_id: clientId,
client_secret: clientSecret,
refresh_token: refreshToken,
grant_type: 'refresh_token',
});
const accessToken = tokenResponse.json('access_token');
const response = http.get(
'https://gmail.googleapis.com/gmail/v1/users/[email protected]/messages',
{ q: `from:[email protected] to:${profilesEmailAddress}` },
{
headers: {
authorization: `bearer ${accessToken}`,
}
});
Upvotes: 0