Google Books OAuth returns 401 even though I'm passing an access_token - axios

I'm trying to add a book to a bookshelf using the google books API by sending an axios POST request in my express server. I need to send an access token to authorize the POST request according to the docs, and I'm getting that access token from the token client model from Google Identity Services. I have the token and I have my API key, but I can't get google to authorize the request.
Here's the call from my front end:
axios.get(
'http://localhost:5000/to-read',
{
params: {
bookId: bookId,
shelfId: shelfId,
token: token
}
})
and here's the back end:
.get((req, res) => {
const headers = {
'Authorization': req.query.token,
'Content-Type': 'application/json',
}
axios.post(
`https://www.googleapis.com/books/v1/mylibrary/bookshelves/${req.query.shelfId}/addVolume?volumeId=${req.query.bookId}&key=${process.env.REACT_APP_API_KEY}`,
{},
{headers: headers}
).then((response) => {
console.log(response);
}).catch((error) => {
console.log(error.response.data)
})
When I send the request with the API key, I get this error:
error: {
code: 401,
message: 'API keys are not supported by this API. Expected OAuth2 access token or other authentication credentials that assert a principal. See https://cloud.google.com/docs/authentication',
errors: [ [Object] ],
status: 'UNAUTHENTICATED',
details: [ [Object] ]
}
and when I remove the API key (it's optional for this call according to the docs) I get this error:
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: [ [Object] ],
status: 'UNAUTHENTICATED',
details: [ [Object] ]
}
and https://developers.google.com/identity/sign-in/web/devconsole-project leads to a 404

Related

Random "User does not have sufficient permissions for this profile." error from Google Analytics API v3

I am receiving this error randomly when I am trying to send a request to Google Analytics API v3:
"User does not have sufficient permissions for this profile."
From every 8-10 times that I try a same request (same parameters, authentication, etc.), I receive this error only once and the other times I receive the correct response in the other times. The other strange part is that we are handling many clients and I only have seen this error for only handful of our clients.
For more background, we are using googleapis NPM package to send our Google Analytics API requests.
This is parameters that I am sending to the API:
{
params: {
auth: OAuth2Client {
_events: [Object: null prototype] {},
_eventsCount: 0,
_maxListeners: undefined,
transporter: DefaultTransporter {},
credentials: [Object],
eagerRefreshThresholdMillis: 300000,
forceRefreshOnFailure: false,
certificateCache: {},
certificateExpiry: null,
certificateCacheFormat: 'PEM',
refreshTokenPromises: Map {},
_clientId: 'XXXXX,
_clientSecret: 'XXXX',
redirectUri: 'postmessage'
},
ids: 'ga:XXXX',
metrics: 'ga:sessions,ga:bounces,ga:transactions,ga:transactionRevenue,ga:goalCompletionsAll',
dimensions: 'ga:date',
'start-date': '2021-10-01',
'end-date': '2021-10-20',
samplingLevel: 'HIGHER_PRECISION',
quotaUser: 'XXX'
}
}
new Promise((resolve, reject) => {
return google
.analytics({ version: "v3"})
.data.ga.get(params, (error, { data: response } = {}) => {
if (error) {
return reject(new Error(`Google API sent the following error: ${error}`));
}
return resolve(response);
});
})
Authentication:
const OAuth2 = google.auth.OAuth2;
const oauth2Client = new OAuth2(process.env.GOOGLE_CLIENT_ID, process.env.GOOGLE_CLIENT_SECRET, "postmessage");
oauth2Client.setCredentials(tokens);
await oauth2Client.getRequestHeaders().catch((error) => {
throw error;
});
And then passing oauth2Client in the params as auth.
I resolved the issue. In my case I was using the same object of oauth2Client for multiple API requests but was calling these lines before each request:
oauth2Client.setCredentials(tokens);
await oauth2Client.getRequestHeaders();
This could potentially change the token that I was passing in the request parameters, params, before it was being sent.
So in other words if you are sending multiple requests to the API at the same time, it is better to generate the token once and use the same token for all those requests.

Using Axios as an Alternative to request in nodejs

I am building a flutter application that requires oauth 1 authorization for one of the third party services I am using. Because flutter oauth 1 package is restricted I decided to use the oauth 1 package that npm provides. This is the code that is used to access the user generated access token from the site.
I previously used request to make a call to the api endpoint first, to access the token and secondly to use the token recieved to make another call to a different resource endpoint
How can I use axios to make the same request, emphasis on the fact that each request needs a hmac-sha1 signed signature in the header.
Thank you.
consumer: {
key: CONSUMER KEY,
secret: CONSUMER SECRET,
},
signature_method: 'HMAC-SHA1',
hash_function(base_string, key) {
return crypto
.createHmac('sha1', key)
.update(base_string)
.digest('base64')
},
})
const request_data = {
url: 'https://www.instapaper.com/api/1/oauth/access_token/',
method: 'POST',
data: { x_auth_username : USERNAME , x_auth_password : PASSWORD , x_auth_mode : 'client_auth' },
}
request(
{
url: request_data.url,
form: request_data.data,
method: request_data.method,
headers: oauth.toHeader(oauth.authorize(request_data)),
},
function(error, response, body) {
// Process your data here
console.log(error);
console.log(response);
console.log(body);
}
)
Finally found the answer for this link to the issue created on github
https://github.com/axios/axios/issues/2771

Retrieving google photos with IONIC 3 with google photos API

I am working on an IONIC application.
In this app the user will be able to get photos from his google photos account and do some design manipulations on the image he selected.
So for that I want to use the google photos API
I did not find any example on how to accomplish this in IONIC.
So I am looking for some sample code or guid on how to get this done.
=======================================================
UPDATE
I tried to do it like this:
Login to google with: cordova-plugin-googleplus
And request the https://www.googleapis.com/auth/photoslibrary
scope
Here is the code:
//Here we do a login.
this.gplus.login({
'webClientId': '***********',
'offline': true,
'scopes': 'profile email https://www.googleapis.com/auth/photoslibrary'
}).then((res) => {
//after login we try to get the google photos albums
this.http.get('https://photoslibrary.googleapis.com/v1/albums', {
responseType: ResponseContentType.Json,
params:{
accessToken: res.accessToken,
pageSize: 50,
}
}).subscribe(res=>{
console.log('<--- google images res: ', res);
},err=>{
console.log('<--- google images err: ', err);
});
});
Now I get an error 'Expected OAuth 2 access token'
Here is the full error description:
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.
==========================================================
UPDATE 2
So after some research I am trying to get the OAuth 2 access token like this:
//Here we do a login.
this.gplus.login({
'webClientId': '***********',
'offline': true,
'scopes': 'profile email https://www.googleapis.com/auth/photoslibrary'
}).then((res) => {
//after login we need to get the OAuth 2 access
//I think like this:
this.http.post('https://www.googleapis.com/oauth2/v4/token', {
code: res.serverAuthCode,
client_id: '*****************',
client_secret: '*************',
redirect_url: '***************',
grant_type: 'authorization_code'
},{
responseType: ResponseContentType.Json
}).subscribe(res=>{
//after we got the OAuth 2 access, we try to get the google photos albums
let myHeaders= new Headers();
myHeaders.append('Content-Type', 'application/json');
this.http.get('https://photoslibrary.googleapis.com/v1/albums', {
responseType: ResponseContentType.Json,
params:{
pageSize: 50,
accessToken: {'bearer': res['_body'].access_token},
},
headers: myHeaders
}).subscribe(res=>{
console.log('<--- google images res: ', res);
},err=>{
console.log('<--- google images err: ', err);
})
},err=>{
......
})
}
}), err => {
.....
});
But still getting the same error:
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.
So now the question is how do is get an OAuth 2 access token ?

Automatic request signing with API Gateway REST API and Amplify

This https://aws-amplify.github.io/docs/js/api#signing-request-with-iam says AWS Amplify provides the ability to sign requests automatically ..is this the same with API gateway REST requests that are restricted by Cognito?
auth.currentSession().then(token => {
console.log('>>>>', token.getIdToken().getJwtToken());
authToken = token.getIdToken().getJwtToken();
const myInit = { // OPTIONAL
headers: {
Authorization: authToken
},
response: true,
};
api.get(apiName, path, myInit).then(response => {
// Add your code here
console.log(response);
}).catch(error => {
console.log(error.response);
});
}
);
but I get Authorization header requires 'Credential' parameter. Authorization header requires 'Signature'
But in angular this does not work as Auth.currentSession() does not compile
endpoints: [
{
name: 'test',
endpoint: 'https://xyz.execute-api.us-west-2.amazonaws.com/test',
custom_header: async () => {
// Alternatively, with Cognito User Pools use this:
return {Authorization: (await Auth.currentSession()).idToken.jwtToken};
}
}
]
}
Resolved had typo with the request url it had to be /items/:test where test was the partition name in dynamo, also the
headers: {
Authorization: token
},
is not required:
https://github.com/aws-amplify/amplify-js/issues/2810#issuecomment-470213459

Parse.com REST API Call gives invalid session token error

I have logged into parse from cloud code using Parse.User.logIn
After a successful login have retrieved session token using user._session
Parse.User.logIn(request.params.userdata.email, "sdfisadufhkasdjhf", {
success: function(user) {
response.success(user._sessionToken);
},
error: function(user, error) {
}
});
This session token is passed to the client which then makes a REST API call by setting the token in the header.
However, the rest API call is not successful and returns invalid session token error.
REST API call works perfect when I don't send session token for requests that don't need authentication
From chrome console, I can see that the headers are set correctly and the value of session token is same as Parse.User.current().getSessionToken()
in app.config()
$httpProvider.defaults.headers.post['X-Parse-Application-Id'] = "dxfhgfxhxhxhxxxxxxxxxxxxxxxxxxxxxdgerstrattgrft";
$httpProvider.defaults.headers.post['X-Parse-REST-API-Key'] = "gfhjjhfjfjjchfjcccccccccccccccccccccccccccccccccccc";
$httpProvider.defaults.headers.post['Content-Type'] = "application/json";
From controller
$scope.createGroup = function()
{
shan = $scope.creategroup;
$http.post('https://api.parse.com/1/functions/addGroup', $scope.creategroup,
{ headers: {
'X-Parse-Session-Token':sessionToken
}
}).success(function(data, status, headers, config) {
alert("success : "+JSON.stringify(data));
}).
error(function(data, status, headers, config) {
alert("error : "+JSON.stringify(data));
});
}