Google Maps Tracks API 401 Invalid Credentials - node.js

I do have checked validity of my access_token at https://www.googleapis.com/oauth2/v1/tokeninfo?access_token=mytoken
which is replying as follows,
{
"issued_to": "myservice_account_emailid",
"audience": "myservice_account_emailid",
"scope": "https://www.googleapis.com/auth/tracks",
"expires_in": 1300,
"access_type": "offline"
}
which means still my token is valid, but if i make request to google tracks api from my application, using the same access_token, am getting response as below ,
Response: {
"error": {
"errors": [
{
"domain": "global",
"reason": "authError",
"message": "Invalid Credentials",
"locationType": "header",
"location": "Authorization"
}
],
"code": 401,
"message": "Invalid Credentials"
}
}
Even i created new project in google developer console, and created new service account , and used the new credentials in application, but still getting same response. what could be the reason?

Found my self.
My error prone code is as below ,
var jwt = new googleapis.auth.JWT(client_email, keyFile, null, scopes, null);
jwt.authorize(function(jwtErr, tokens){
if(jwtErr){
return;
}
else{
headers = {
'content-type' : 'application/json;charset=utf-8',
'content-length': Buffer.byteLength(data),
'Authorization' : tokens.access_token
};
options = {
host: 'www.googleapis.com',
path: '/tracks/v1/entities/create',
headers : headers,
method : 'POST',
};
var post_req = https.request(options, function(res){
res.setEncoding('utf8');
res.on('data', function (chunk) {
console.log('Response: ' + chunk);
});
});
post_req.on('error', function(error_msg){
console.log(error_msg);
});
post_req.write(data);
post_req.end();
}
});
The problem is in header object, 'Authorization' field is set to only access.token value, along with that we must specify token_type value also.
so header must be like below.
headers = {
'content-type' : 'application/json;charset=utf-8',
'content-length': Buffer.byteLength(data),
'Authorization' : tokens.token_type+' '+tokens.access_token
};
and now it solves 401 Invalid Credentials error.

Related

Axios Post Request in NodeJS

I have an API call in POSTMAN, which I am trying to replicate in nodeJS project using Axios, but the result is not the same that of a POSTMAN.
The call looks like this in POSTMAN:
Inside the body element I have: models and values properties and Authorization is of type Bearer .
I get a response result as an array.
Now, I try to do the same using axios, but I get error:
Code
axios.defaults.baseURL = 'http://XXXXXXXXXXXXXXX:8069/api';
axios({
method: 'POST',
url: '/create/res.users',
data: {
models: 'res.users',
values: "{ 'login': 'john#gmail.com', 'name':'john', 'email':'john#gmail.com', 'password': '123123123' }"
},
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Authorization': 'Bearer ' + accessToken
},
})
.then(function (response) {
console.log("Register", response);
res.status(200).send({
message: response.data
});
})
.catch(function (error) {
console.log("Error", error.response.data);
res.status(error.response.status).send({
message: error.response.data
});
});
Error
{
"message": {
"name": "odoo.exceptions.RedirectWarning",
"message": "You cannot create a new user from here.\n To create new user please go to configuration panel.\n74\nGo to the configuration panel",
"arguments": [
"You cannot create a new user from here.\n To create new user please go to configuration panel.",
74,
"Go to the configuration panel"
],
"exception_type": "error",
"code": 500,
"description": "Restful API Error"
}
}
By default, axios serializes JavaScript objects to JSON. To send data in the application/x-www-form-urlencoded format instead, This document may help you:
https://github.com/axios/axios#using-applicationx-www-form-urlencoded-format

PUT API request returning JSON body error

Im trying to update a distribution list by sending a put request, when I run this code and test it in postman by giving it a JSON body I get this error in my node.js terminal stating SyntaxError: Unexpected end of JSON input ... any idea what I should change?
My PUT API request
app.put("/api/Dls/Add/:groupId" , (req, res) => {
const response = {
success: false
};
if (Authorized.myToken) {
response.success = true;
response.data = {};
var options = {
method: 'PUT',
url: 'https://SomeAPI.com/' + req.params.groupId,
headers:
{
Accept: 'application/json',
Authorization: 'Bearer' + ' ' + Authorized.myToken
},
body: JSON.stringify(req.body)
};
request(options, function (error, response, body){
if (error) {
console.log(error);
return;
}
const data = response.body;
const dls = JSON.parse(data)
return res.json(dls);
});
}
});
JSON body I'm passing through postman to test the API call
{
"groupId": "123456789",
"SomeField1": null,
"SomeField2": "xxxxxxxxx",
"SomeField3": true,
"SomeField4": "xxxxxxxxx",
"SomeField5": "xxxxxxxxx",
"SomeField6": [
"xxxxxxxxx"
],
"SomeField7": "xxxxxxxxx",
"SomeField8": "xxxxxxxxx",
"SomeField9": "xxxxxxxxx",
"SomeField10": "xxxxxxxxx",
"SomeField11": [],
"SomeField12": "xxxxxxxxx",
"SomeField13": null,
"SomeField14": false,
"SomeField15": ["xxxxxxxxx"]
}
Any feedback is appreciated!
If the JSON that you posted here is the real one that you pass via postman then, it is not the valid JSON as you have the same name properties. When I say valid it means you get something like this after posting to the endpoint.
{
"groupId": "123456789",
"SomeField": [
"xxxxxxxxx"
]
}
Request npm package is also deprecated so it is better to not use it and replace it with something like Axios. TBH I did not see any error in the code that causes the error that you mentioned, do you have access to the API to check the logs? Maybe something went wrong on the https://SomeAPI.com/ endpoint.
I figured out what the issue was, I needed to add the .end to the return statement
ex. return res.status(200).end()

How to update a pull request by GitHub APP API?

I developed GitHub APP to manage pull requests process, I'm using two APIs
1. statuses check API
2. update-a-pull-request API
I get this error message when a request to update an existing pull request that was created by one of the users.
How I can get installation token with the right permissions?
{
"message": "Validation Failed",
"errors": [
{
"message": "Only the pull request author may change the maintainer_can_modify value",
"resource": "PullRequest",
"field": "maintainer_can_modify",
"code": "invalid"
}
],
"documentation_url": "https://developer.github.com/v3/pulls/#update-a-pull-request"
}
To execute API call, I need token, I generated the token in this way:
Created app in GitHub Account
Created a private PEM key in the APP
In code, created JWT token using PEM key
Using the JWT token to create installation token as below
Header
function generateJwtToken() {
return jsonwebtoken.sign(
{
iat: Math.floor(new Date() / 1000),
exp: Math.floor(new Date() / 1000) + 60,
iss: ISSUER_ID,
},
PEM,
{algorithm: 'RS256'},
);
}
let githubHeadersToAccessToken = {
'User-Agent': 'nodejs',
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + generateJwtToken(),
'Accept': 'application/vnd.github.machine-man-preview+json'
};
Get Installation token
payloadToken = {
"repository_ids": [
],
"permissions": {
"pull_requests": "write",
"statuses": "write",
"administration" : "write",
"organization_administration": "write",
"contents": "write",
"team_discussions": "write",
}
};
request.get({
url: 'https://api.github.com/app/installations',
headers: githubHeadersToAccessToken
}, function optionalCallback(err, httpResponse, body) {
if (err) {
return console.error('Connected App get token failed:', err);
}
console.log('APP Installation id');
console.log('Installation id: ' + JSON.parse(body)[0].id);
app_installed_id = JSON.parse(body)[0].id;
request.post({
url: 'https://api.github.com/app/installations/'+app_installed_id+'/access_tokens',
headers: githubHeadersToAccessToken,
json: payloadToken
}, function optionalCallback(err, httpResponse, body) {
if (err) {
return console.error('Failed to get access token to GitHub: ', err);
}
//console.log(body);
console.log('Access token to GitHub: ' + body.token);
});
});
Update existind pull request that was created by one of the users
request.post({
url: 'https://api.github.com/repos/'+owner+'/'+repo+'/statuses/'+sha,
headers: githubHeadersApiV3,
json: {
"state": status,
"context": "PR <> GUS Validation"
}
}, function optionalCallback(err, httpResponse, body) {
if (err) {
return console.error('Connected App get token failed:', err);
}
//console.log(body);
console.log('commit sha: ' + sha + ' updated with status: ' + status);
});
I want to update that the code is working, I can update pull request using Github APP.
The problem I mentioned happen when I try to change "maintainer_can_modify" in pull request, which is not allowed, only by owner, then I just removed it.
But in my case I wanted to add comment, change title, etc ..
I will leave this question as an example for building GitHub app to update pull request using NodeJS.

Setting Cookie in http response header from AWS lambda Node JS

I have a Lambda proxy integration enabled, and setting the response headers as part of Lambda output and API Gateway that will return them as part of the HTTP response to the client.
Sample code:
callback(null, {
"statusCode": 302,
"Location" : "https://somewebsite.com"
"headers": { "headerName": "headerValue", ... },
"body": "..."
});
I need to send out 3 cookies in the headers. I tried. But, failed:
callback(null, {
"statusCode": 302,
"Location" : "https://somewebsite.com"
"headers": { "Set-Cookie": [cookie1String, cookie2String, cookie3String] },
"body": "..."
});
[Edit]
I concatenated the cookie and passed in as the response, the client gets the cookie. But when the client calls the target in "location", the request does not have the cookie in the header.
callback(null, {
"statusCode": 302,
"Location" : "https://somewebsite.com"
"headers": { "Set-Cookie": c1=cookie1String;c2=cookie2String; c3=cookie3String] },
"body": "..."
});
Please help in sending these 3 cookies out to my client.
Use multiValueHeaders instead of headers.
const response = {
isBase64Encoded: true,
statusCode: 200,
multiValueHeaders : {"Set-Cookie": [`language=${language}`, `theme=${theme}`]},
body: JSON.stringify('User profile set successfully')
};
callback(null, response);
If you need it to be smarter, consider something like
function createHeaders(headers) {
const defaultHeaders = {
'Access-Control-Allow-Origin': '*',
};
const allHeaders = Object.assign({}, defaultHeaders, headers);
const singleValueHeaders = {};
const multiValueHeaders = {};
Object.entries(allHeaders).forEach(([key, value]) => {
const targetHeaders = Array.isArray(value) ? multiValueHeaders : singleValueHeaders;
Object.assign(targetHeaders, { [key]: value });
});
return {
headers: singleValueHeaders,
multiValueHeaders,
};
}
Then use it in the callback function.
callback(null, {
statusCode: status || 200,
body: JSON.stringify(body),
...createHeaders({ 'Set-Cookie': cookie }),
});
API gateway does not let you map the same header more than once. I got around by using different casing to set-cookie method.
callback(null, {
"statusCode": 302,
"Location" : "https://somewebsite.com"
"headers": { "Set-Cookie": cookie1, "set-Cookie": cookie2 },
"body": "..."
});
I would say that your issue is related to the fact that your response object in the callback is not formatted the way the api gateway expects.
These links reference aws documentation specifically to that.
http://docs.aws.amazon.com/apigateway/latest/developerguide/handle-errors-in-lambda-integration.html
Issue with your code...
'location' does not look like a valid property
Make sure your header key/value pairs are actual JSON objects using something like JSON.stringify
Don't forget to enable logs for both api gateway and lambda with full requests and responses. These two logs will help you debug.

google maps tracks api - send request using node js

In order to access the google maps tracks API, i have access token sent by Google’s OAuth 2.0 Authorization Server. Now i need to send this access token with every http request i made to google map tracks API. Where should i put this access token in http request ?. I tried to put in headers as 'X-Access-Token' : 'myaccesstoken', but am getting response from api as below.
body: '{\n "error": {\n "errors": [\n {\n "domain": "global",\n "reason": "required",\n "message": "Login Required",\n "locationType": "header",\n "location": "Authorization"\n }\n ],\n "code": 401,\n "message": "Login Required"\n }\n}\n' }
I referred google map tracks API official documentation https://developers.google.com/maps/documentation/tracks/auth, but unable to solve this error.
below is the code am using to authenticate with Google’s OAuth 2.0 Authorization Server, and code to send request to google map tracks API.
var jwt = new googleapis.auth.JWT(client_email, keyFile, null, scopes, null);
jwt.authorize(function(jwtErr, tokens){
if(jwtErr){
return;
}
else{
headers = {
'content-type' : 'application/json',
'X-Access-Token' : tokens.access_token
};
options = {
url : 'https://www.googleapis.com/tracks/v1/geofences/list',
headers : headers,
method : 'POST',
};
request(options, function(error, response, body){
if(error){
return;
}
console.log(response);
});
}
});
Found the solution, access token should be put in
header : { 'Authorization' : 'myaccesstoken' },
so after changes, code will look like below.
var jwt = new googleapis.auth.JWT(client_email, keyFile, null, scopes, null);
jwt.authorize(function(jwtErr, tokens){
if(jwtErr){
return;
}
else{
headers = {
'content-type' : 'application/json;charset=utf-8',
'content-length': Buffer.byteLength(data),
**'Authorization' : tokens.access_token**
};
options = {
host: 'www.googleapis.com',
path: '/tracks/v1/entities/create',
headers : headers,
method : 'POST',
};
var post_req = https.request(options, function(res){
res.setEncoding('utf8');
res.on('data', function (chunk) {
console.log('Response: ' + chunk);
});
});
post_req.on('error', function(error_msg){
console.log(error_msg);
});
post_req.write(data);
post_req.end();
}
});

Resources