Google API Batch returns 401 - javascript

Doing two or more requests in one batch at once leads to a 401 for each request.
const batch = gapi.client.newBatch();
batch.add(gapi.client.drive.files.list());
batch.add(gapi.client.drive.files.list());
batch.then((e) => {
console.log(e);
});
The error is:
{
"error": {
"errors": [
{
"domain": "global",
"reason": "authError",
"message": "Invalid Credentials",
"locationType": "header",
"location": "Authorization"
}
],
"code": 401,
"message": "Invalid Credentials"
}
}
Using only one batch.add works perfectly fine. It doesn't make any sense to me.
Why? What do I do wrong?

Directly from the documentation handle errors
401: Invalid Credentials
Invalid authorization header. The access token you're using is either expired or invalid.
{
"error": {
"errors": [
{
"domain": "global",
"reason": "authError",
"message": "Invalid Credentials",
"locationType": "header",
"location": "Authorization",
}
],
"code": 401,
"message": "Invalid Credentials"
}
}
Suggested action: Refresh the access token using the long-lived refresh token. If this fails, direct the user through the OAuth flow, as described in Authorizing Your App with Google Drive.
Batch documentation.
var searchRequest = function(name) {
return gapi.client.request({
'path': 'plus/v1/people',
'params': {'query': name}
});
};
var searchAlvin = searchRequest('Alvin');
var searchSimon = searchRequest('Simon');
// Adding just the request
batch.add(searchAlvin);
// Adding the request with an ID
batch.add(searchSimon, {'id': 'searchSimon'});

Related

Display Asp.net Core ModelState errors in javascript client

If there is a validation error in the model.
Server Code
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
Server Response:
{
"type": "https://tools.ietf.org/html/rfc7231#section-6.5.1",
"title": "One or more validation errors occurred.",
"status": 400,
"traceId": "00-193353f9eda8d843af165acdb78f55d9-97b06892bbb3e541-00",
"errors": {
"ConfirmPassword": [
"The password and confirmation password do not match."
]
}
}
However, if we add a custom Error in server code like
ModelState.AddModelError(error.Code, error.Description);
return BadRequest(ModelState);
Server Response:
{
"DuplicateUserName": [
"User name is already taken."
]
}
Why is there a difference in error response?
How to send a similar json object response to client?
If its not possible then how to reconcile this at client's end?

Lambda error: ExpressionAttributeValues must not be empty when using API Gateway

Using the test in the lambda function, the update method succesfully inserts the data in the correspondent column of the database. However when I try it in API Gateway as a PUT request triggering this lamdba function, the following error appears:
Lambda execution failed with status 200 due to customer function error: ExpressionAttributeNames must not be empty
Here´s the code of the function:
exports.handler = function(event, context, callback) {
// manually id:
let scanningParameters = {
Key: {
"email": event.email
},
UpdateExpression: "set sites = :sites",
ExpressionAttributeValues: {
":sites":event.sites
},
TableName: 'Users'
}
return docClient
.update(scanningParameters)
.promise()
.then(() => {
return {
"statusCode": 200,
'headers': { 'Content-Type': 'application/json' }
}})
}
I have tried changing ExpressionAttributeValues by ExpressionAttributeNames but it hasn´t worked either.
When you use API gateway for lambda proxy integration, recommended way, the event object send to your function has special format:
{
"resource": "Resource path",
"path": "Path parameter",
"httpMethod": "Incoming request's method name"
"headers": {String containing incoming request headers}
"multiValueHeaders": {List of strings containing incoming request headers}
"queryStringParameters": {query string parameters }
"multiValueQueryStringParameters": {List of query string parameters}
"pathParameters": {path parameters}
"stageVariables": {Applicable stage variables}
"requestContext": {Request context, including authorizer-returned key-value pairs}
"body": "A JSON string of the request payload."
"isBase64Encoded": "A boolean flag to indicate if the applicable request payload is Base64-encode"
}

AccessDenied: Not authorized to perform sts:AssumeRoleWithWebIdentity

I've looked around similar problems, but couldn't resolve my problem. I'm developing an web application where the user will authenticate using AWS Cognito's authentication. The sign up part is ok, but when I try to sign in, I'm getting the "not authorized" exception. I've already tried to attach custom policies to my IAM Role (authorizing sts:AssumeRoleWithWebIdentity), but didn't work.. Here is how the code is written right now:
var cognitoUser = new AWSCognito.CognitoIdentityServiceProvider.CognitoUser(userData);
cognitoUser.authenticateUser(authenticationDetails, {
onSuccess: function (result) {
var sts = new AWS.STS({apiVersion: '2011-06-15'});
var params = {
RoleArn: 'arn:aws:iam::981601120657:role/Cognito_AliceAuth_Role', /* required */
RoleSessionName: 'AliceUserSession',
WebIdentityToken: result.getIdToken().getJwtToken(),
Policy: '{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": "sts:AssumeRoleWithWebIdentity", "Resource": "*" } ] }'
};
sts.assumeRoleWithWebIdentity(params, function (err, data) {
if (err)
console.log(err, err.stack); // ** <-- ERROR HERE
else
console.log(data); // successful response
});
//document.getElementById('authForm').submit();
},
onFailure: function (err) {
alert(err);
}
});
As you can see, I specified the policy in the code too, but I still get the "AccessDenied: Not authorized to perform sts:AssumeRoleWithWebIdentity" error. Please help me :/
EDIT:
Inside the "Cognito_AliceAuth_Role" I've created the role policies:
AssumeRoleWithWebIdentityPolicy:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "sts:AssumeRoleWithWebIdentity",
"Resource": "*"
}
]
}
and: GetFederationTokenPolicy
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "sts:GetFederationToken",
"Resource": "*"
}
]
}
The trust relationship:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Federated": "cognito-identity.amazonaws.com"
},
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringEquals": {
"cognito-identity.amazonaws.com:aud": "us-east-1:e4c1833d-a62b-402a-b995-1b2513b04c02"
},
"ForAnyValue:StringLike": {
"cognito-identity.amazonaws.com:amr": "authenticated"
}
}
}
]
}
Seems like you are using the Id token vended by Cognito user pools to call the assumeRoleWithWebIdentity.
You need to federate this token with Cognito identity first and you can use the Open Id connect token vended by Cognito identity to call assumeRoleWithWebIdentity.
You can directly call getCredentialsForIdentity as well using Enhanced flow.
See this to learn more about how to federate user pools token with Cognito identity.
Came across the same issue,
Create a user pool to serve as a user directory.
Register a user (User 1) in the user pool.
Create an identity pool and configure it to integrate with the user pool.
Create an IAM role that with the required permission. When creating the user use AssumeRoleWithWebIdentity option and add the identity pool ID in the wizard.
Create a group in the user pool and map the role we created and add some users to this group.
Now after authenticating the user via cognito configure the aws sdk with the jwt token.
AWS.config.region = "<YOUR_REGION>";
AWS.config.credentials = new AWS.CognitoIdentityCredentials({
IdentityPoolId : '<YOUR_IDENTITY_POOL_ID>',
Logins : {
// Change the key below according to the specific region your user pool is in.
`cognito-idp.${AWS.config.region}.amazonaws.com/${data.UserPoolId}` : session.getIdToken().getJwtToken()
}
});
Reference Article - https://aws.amazon.com/blogs/developer/authentication-with-amazon-cognito-in-the-browser/

JavaScript Send JSON to Google API

I am new to the Google API (Calendar V3) and I have the authorization through obtaining a token working. I am using a get request to get the users calendar_Id in which I want to send in a POST request in order to add an event to the calendar.
Here is what I am working with:
var json_body = {
"end": {
"date": "2013-09-06"
},
"start": {
"date": "2013-09-06"
},
"summary": "test event 1"
};
var json_string = JSON.stringify(json_body);
http.setRequestHeader("Content-Type", "application/json");
http.setRequestHeader("Authorization","Bearer " + access_key);
http.setRequestHeader("Connection", "close");
http.onreadystatechange = function() {//Call a function when the state changes.
if(http.readyState == 4 && http.status == 200) {
alert("in here");
alert(http.responseText);
}
}
http.send(json_string);
The response I am getting is:
{
"error": {
"errors": [
{
"domain": "global",
"reason": "parseError",
"message": "Parse Error"
}
],
"code": 400,
"message": "Parse Error"
}
}
I know that the access_key authorization header is correct since it is not giving me the authorization error. I have ran this JSON structure in Googles API Explorer tool and it adds an element to my calendar correctly. I am assuming that the way I am building my JSON is incorrect. Any ideas?
Thank you in advance.
EDIT:
I found the correct solution. I was mis-using a parameter in the url request. The code above works in case anyone stumbles upon this for reference in the future.

Authentication issue with simple upload on Google Drive API

I'm trying to upload a file to my Google Drive file space, and I'm using the following code:
var httpRequest = new XMLHttpRequest();
var url_goto = "https://www.googleapis.com/upload/drive/v2/files?uploadType=media";
httpRequest.onreadystatechange = function() {
if (httpRequest.readyState==4 && httpRequest.status==200) {
Firebug.Console.log(httpRequest.responseText);
} else if (httpRequest.readyState==4 && httpRequest.status==401) {
Firebug.Console.log(httpRequest.responseText);
} else {
Firebug.Console.log('Other status: ' + httpRequest.readyState + ', ' + httpRequest.status);
}
};
var s = 'Test string';
httpRequest.open('POST', url_goto, true);
httpRequest.setRequestHeader('Content-Type', 'text/plain');
httpRequest.setRequestHeader('Content-Length', s.length);
httpRequest.setRequestHeader('Authorization', 'MY_AUTH_KEY');
httpRequest.send(s);
The problem is that I've the following output:
"Other status: 1, 0"
"Other status: 1, 0"
"Other status: 2, 401"
"Other status: 3, 401"
...and an exception is thrown:
"{
"error": {
"errors": [
{
"domain": "global",
"reason": "authError",
"message": "Invalid Credentials",
"locationType": "header",
"location": "Authorization"
}
],
"code": 401,
"message": "Invalid Credentials"
}
}"
Can anybody help me to understand why authentication is not working?
I'm using the API Key retrieved from my Google APIs Console, under section Simple API Access.
Thanks!
If you are using oauth2 token then you must specify the Bear along with auth token in Authorization header like
httpRequest.setRequestHeader("Authorization", "Bearer MY_AUTH_KEY");

Categories

Resources