Access Denied Excemtion when Using AWS Elastic Transcoder on website - javascript

I am getting an 403 error when trying to use AWS Elastic Transcoder on my test site and I can’t seem to figure out where the problem lies. I have checked in my IAM policies and identity pools etc. to no avail.
The error:
GET https://
elastictranscoder.us-east-1.amazonaws.com/2012-09-25/pipelines/xxxxxxxxxxxxx-xxxxxx
403 (Forbidden) index.html:xxx AccessDeniedException: User:
arn:aws:sts::xxxxxxxxxxxx:assumed-role/Cognito_Unauth_Role/CognitoIdentityCredentials
is not authorized to perform: elastictranscoder:CreateJob on resource:
arn:aws:elastictranscoder:us-east-1:
xxxxxxxxxxxxx:pipeline/xxxxxxxxxxxxx-xxxxxx
AWS.config.region = ‘xx - xxx - x’; // Region
AWS.config.credentials = new AWS.CognitoIdentityCredentials({
IdentityPoolId: "xx-xxx-x:xxxxx-xxxxx-xxxx-xxxx-xxxxxxxxx”,
});
var elastictranscoder = new AWS.ElasticTranscoder();
var button = document.getElementById('button');
button.addEventListener('click', function() {
var params = {
PipelineId: ‘xxxxxxxxxxxxxx’,
/* required */
Input: {
Key: “xxxxxxxxxx / xxxxxxx.xxx”
},
OutputKeyPrefix: ‘xxxxxxx / ‘,
Outputs: [{
Key: ‘xxxx.xxx’,
PresetId: ‘xxxxxxxxxxxx’,
}, ],
};
elastictranscoder.createJob(params, function(err, data) {
if (err) console.log(err, err.stack); // an error occurred
else console.log(data); // successful response
});
});

Solution! turns out I didn't know that I needed to include the AWS access key and secret key in the options section of the elastic transcoder constructor.
var elastictranscoder = new AWS.ElasticTranscoder(options = {
accessKeyId: 'xxxxxxxxxxxxxx',
secretAccessKey: 'xxxxxxx xxxxxxxxxxxxxx xxxxxxxxxxxxxx'
}

Related

Error while calling AWS Athena using javascript code using Cognito UnauthRole with Full S3 and Athena Access

I am trying to query athena by assuming a role by using Cognito_IdedtityPool to get temporary accessKey, secretKey and sessionToken which has full Athena and S3 permission. But when i call it from my .js file it throws error
User:
Error : arn:aws:sts::<acc_no>:assumed-role/... is not authorized to perform: athena:StartQueryExecution on resource: arn:aws:athena:us-east-1:... because no session policy allows the athena:StartQueryExecution action
But once I create an IAM User and hardcode the keys with full Athena and S3 permission. then i am able to get data. Can anyone help in this ?
How can i query using assumed role ?
My js code is below :
AWS.config.credentials = new AWS.CognitoIdentityCredentials({
IdentityPoolId: 'us-east-1:<pool-id>',
});
var config = {
accessKey: credentials.accessKeyId, // REQUIRED
secretKey: credentials.secretAccessKey, //REQUIRED
sessionToken: credentials.sessionToken,// REQUIRED
region: 'us-east-1',
apiVersion: '2017-05-18',
}
AWS.config.update(config);
const AthenaExpress = require("athena-express"),
const athenaExpressConfig = {
aws: AWS,
s3: "s3://athena-output-destination/Test",
getStats: true,
workgroup: 'primary',
catalog: ATHENA_CATALOG,
retry: 4,
formatJson: true,
};
const athenaExpress = new AthenaExpress(athenaExpressConfig);
(async () => {
let myQuery = {
sql: query_string,
db: ATHENA_DB
};
try {
let results = await athenaExpress.query(myQuery);
console.log(results);
} catch (error) {
console.log(error);
}
})();

On beanstalk -Cognito stops authenticating after some time and throws error of "missing credentials in config"

First I have searched solutions, but I am unable to pinpoint the issue.
This is app hosted on beanstalk and works as intended after deploying. I can login, do what i need to do and close the app. If the browser is refreshed you will have to log in again (as intended).
Issue: I deployed my app around 12pm and around 2pm I tried logging in and I get a "missing credentials in config" error.
I deployed again around 2:20pm and as of now (2:58pm) it is still working as intended. But if this throws same error again, what am I possibly doing wrong?
Please see below snippet of code for my authenticating route in node js. This is a beanstalk reactjs node app.
AWS.config.update({
region: process.env.Region
});
var AmazonCognitoIdentity = require('amazon-cognito-identity-js');
const poolData = { //--Moved to env variables
UserPoolId: process.env.UserPoolId, // your user pool id here
ClientId: process.env.ClientId // your app client id here
};
const userPool = new AmazonCognitoIdentity.CognitoUserPool(poolData);
router.post('/api/authenticateuser', (req, res) => {
var authenticationData = {
Username: val.value.user, // your username here
Password: val.value.pass, // your password here
};
// AWS.config.credentials = new AWS.CognitoIdentityCredentials({
// IdentityPoolId: 'IDENTITY_POOL_ID',
// });
const cognitoidentityserviceprovider = new AWS.CognitoIdentityServiceProvider();
var loginParams = {
AuthFlow: 'USER_PASSWORD_AUTH',
/* required */
ClientId: process.env.ClientId,
/* required */
AuthParameters: {
'USERNAME': val.value.user,
'PASSWORD': val.value.pass
}
};
cognitoidentityserviceprovider.initiateAuth(loginParams, function(err, data) {
if (err) {
// console.log(err, err.stack); // an error occurred
res.json(err);
} else {
console.log(data); // successful response
if (data.ChallengeName === process.env.Challenge_NEW_PASS) {
res.json({
changePass: "changePass",
session: data.Session
});
} else if (data.ChallengeName === process.env.Challenge_MFA) {
// console.log(data);
res.json({
MFA: "MFA",
session: data.Session,
user: val.value.user
});
} else {
const accessToken = data.AuthenticationResult.AccessToken;
// Add the User's Id Token to the Cognito credentials login map.
const idToken = data.AuthenticationResult.IdToken;
AWS.config.credentials = new AWS.CognitoIdentityCredentials({
IdentityPoolId: process.env.IdentityPoolId,
Logins: {
[process.env.CognitoIdp]: idToken
},
LoginId: val.value.user
});
res.json({
accessToken,
idToken,
user: val.value.user,
test: data
});
}
}
});
})
Cognito session expires after 1 hour by default. Your temporary access key and secret expires along with it and so does the identity token and session token. You will have to use the refresh token every hour to get new credentials. If you want to avoid this, you can try using Amplify Authentication, which will automatically do the refreshing for you.

Getting 403 (Forbidden) when trying to synchronize() to amazon cognito

I am able to login into Facebook, get an access token and use this to access my identity pool at amazon cognito. When trying to synchronize() my local dataset with amazon I get the error Failed to load resource: the server responded with a status of 403 (Forbidden).
It follows amazons documentation but I must be missing some credential since it does not work. In chrome I get the message
{"message":"Missing Authentication Token"} which clearly indicates that.
But the sync manager github repo does not show how to add more credentials other than the pool ID.
function facebookSignIn(accessToken) {
AWS.config.update({
region: 'eu-west-1',
credentials: new AWS.CognitoIdentityCredentials({
IdentityPoolId: learnjs.poolId,
Logins: {
'graph.facebook.com': accessToken
}
})
});
AWS.config.credentials.get(function() {
var client = new AWS.CognitoSyncManager();
client.openOrCreateDataset('Timebooking', function(err, dataset) {
dataset.put('1', 'En', function(err, record) {
console.log('put(): ' + record);
dataset.synchronize({
sessionToken: sessionToken,
onSuccess: function(dataset, newRecords) {
console.log('synchronize() onSuccess, length: ' + newRecords.length);
}
});
});
});
});
}
I have added the AWS SDK in html:
<script src='/aws-sdk.min.js'></script>
<script src='/amazon-cognito.min.js'></script>

The security token included in the request is invalid. aws js sdk

I posted here on the AWS forum
I'm using the aws-js-sdk v2.2.3 with the following code. I get data back with Credentials populated. When I try to use the credentials I get the error that they are invalid. I'm using the developer authenticated identities flow. I have both roles Auth & UnAuth. My identity pool looks like it's correct. The trust relationships look like they are pointing to the correct identity pool id. There are policies attached to the Auth role for S3 & DynamoDB. I'm at a loss. Any help would be appreciated.
javascript client side:
var cognitoidentity = new AWS.CognitoIdentity({region: 'us-east-1'});
var params = {
IdentityId: user.cognito_id,
Logins: {
'cognito-identity.amazonaws.com': user.cognito_token
}
};
cognitoidentity.getCredentialsForIdentity(params, function(err, data) {
if (err) console.log(err, err.stack); // an error occurred
else console.log(data.Credentials);
});
I console.log the Id & SecretKey and they are filled in.
var aws_creds = StateService.get('user').aws_creds;
console.log(aws_creds.AccessKeyId);
console.log(aws_creds.SecretKey);
AWS.config.update({ accessKeyId: aws_creds.AccessKeyId,
secretAccessKey: aws_creds.SecretKey,
endpoint: ENV.aws_dyndb_endpoint,
region: 'us-east-1'
});
var dynamodb = new AWS.DynamoDB();
console.log("user obj: ", StateService.get('user'));
var params = {
TableName: games_table_name,
KeyConditionExpression: "Id = :v1",
ExpressionAttributeValues: {
":v1": {"N": id}
}
};
return dynamodb.query(params);
My Solution
What I came up with was to explicitly refresh the credentials versus get them lazily when I created a DynamoDb object for instance. Here's the function I use which returns a promise & resolves when the credentials are refreshed.
refresh: function() {
var deferred = $q.defer();
AWS.config.region = 'us-east-1';
AWS.config.credentials = new AWS.CognitoIdentityCredentials({
IdentityPoolId: COGNITO_IDENTITY_POOL_ID,
IdentityId: COGNITO_ID,
Logins: 'cognito-identity.amazonaws.com'
});
AWS.config.credentials.refresh(function(error) {
if ((error === undefined) || (error === null)) {
$log.debug("Credentials Refreshed Success: ", AWS.config.credentials);
var params = {
region: 'us-east-1',
apiVersion: '2012-08-10',
credentials: AWS.config.credentials
};
$rootScope.dynamodb = new AWS.DynamoDB({params: params});
deferred.resolve();
}
else {
$log.debug("Error refreshing AWS Creds:, ", error);
deferred.reject(error);
}
});
return deferred.promise;
}
If you want to use Cognito credentials to call other AWS services, I recommend you use the high-level AWS.CognitoIdentityCredentials object from the Javascript SDK, instead of calling the service API directly.
You can find more information about how to initialize and use AWS.CognitoIdentityCredentials in the Cognito Developer Guide:
Developer Authenticated Identities
Albert
The flow is like this: You ask the CognitoIdentityCredentials for a IdentityId, the IDentityId is supposed to track users accross devices and across Identities providers like (Facebook, Google, TWitter, etc.) then you with that ID you ask for a role attached to your pole CognitoIdentity, after you get the token, you ask the STS.assumeRoleWithWebIdentity for a temporary credentials with the appropriate roles attached to your pole.
Here is an example of how I did it:
// set the Amazon Cognito region
AWS.config.region = 'us-east-1';
// initialize the Credentials object with our parameters
AWS.config.credentials = new AWS.CognitoIdentityCredentials({
IdentityPoolId: 'us-east-1:YMIDENTITYPOLEID',
});
// We can set the get method of the Credentials object to retrieve
// the unique identifier for the end user (identityId) once the provider
// has refreshed itself
AWS.config.credentials.get(function(err) {
if (err) {
console.log("Error: "+err);
return;
}
console.log("Cognito Identity Id: " + AWS.config.credentials.identityId);
params = {
IdentityId: AWS.config.credentials.identityId
}
// Other service clients will automatically use the Cognito Credentials provider
// configured in the JavaScript SDK.
// Get the Role associated with the id coming from the pool
var cognitoidentity = new AWS.CognitoIdentity();
cognitoidentity.getOpenIdToken(params, function(err, data) {
if (err){
console.log(err, err.stack); // an error occurred
}else{
// Get temporoarly credientials form STS to access the API
var params = {
RoleArn: 'ROLE_OF_YOUR_POLE_ARN', /* required */
RoleSessionName: 'WHATEVERNAME', /* required */
WebIdentityToken: data.Token, /* required */
};
var sts = new AWS.STS()
console.log(data); // successful response
console.log(data.Token)
sts.assumeRoleWithWebIdentity(params, function(err, data) {
if (err){
console.log(err, err.stack); // an error occurred
}else{
console.log(data); // successful response
// Now we need these credentials that we got for this app and for this user
// From here we can limit the damage by
// Burst calling to the API Gateway will be limited since we now that this is a single user on a single device
// If suspicious activities we can drop this user/device
// The privileges are limited since the role attached to this is only the API GateWay calling
// This creds are temporary they will expire in 1h
var apigClient = apigClientFactory.newClient({
accessKey: data.Credentials.AccessKeyId,
secretKey: data.Credentials.SecretAccessKey,
sessionToken: data.Credentials.Token, //OPTIONAL: If you are using temporary credentials you must include the session token
region: AWS.config.region // OPTIONAL: The region where the API is deployed, by default this parameter is set to us-east-1
});
// Call the get to test
apigClient.deviceGet({}, {})
.then(function(result){
//This is where you would put a success callback
console.log(result)
}).catch( function(result){
//This is where you would put an error callback
});
}
});
}
});
});
NB: This was a test to get access to the API Gateway service, but it is not different to get access to other services, it depends on the pole you configure it and its attached services.
If you have credential for a user created in IAM you don't need the temporary token, but if you use this flow you have to include it.
Another point, limit the access to the services on your pole, keep in mind that is a publicly given key, every one can use it to get access to your stuff.
STS.assumeRoleWithWebIdentity is used because we are on the web, in the AWS JS SDK, if you use iOS or android/java or Boto, you have to use STS.assumeRole.
Hope this helps.

Node.js 303 Permanent Redirect when connecting to AWS-SDK

Good afternoon,
I'm trying to set up a connection to my aws product api, however I keep getting a 301 Permanent Redirect Error as follows:
{ [PermanentRedirect: The bucket you are attempting to access must be addressed using the specified endpoint. Please send all future requests to this endpoint.]
message: 'The bucket you are attempting to access must be addressed using the specified endpoint. Please send all future requests to this endpoint.',
code: 'PermanentRedirect',
name: 'PermanentRedirect',
statusCode: 301,
retryable: false }
The code I am using to connect to the API is as follows:
var aws = require('aws-sdk');
//Setting up the AWS API
aws.config.update({
accessKeyId: 'KEY',
secretAccessKey: 'SECRET',
region: 'eu-west-1'
})
var s3 = new aws.S3();
s3.createBucket({Bucket: 'myBucket'}, function() {
var params = {Bucket: 'myBucket', Key: 'myKey', Body: 'Hello!'};
s3.putObject(params, function(err, data) {
if (err)
console.log(err)
else
console.log("Successfully uploaded data to myBucket/myKey");
});
});
If I try using different regions, like us-west-1 I just get the same error.
What am I doing wrong?
Thank you very much in advance!
I have fixed this issue:
You have to make sure that you already have created a bucket with the same name; in this case, the name of the bucket would be 'myBucket'.
s3.createBucket({Bucket: 'myBucket'}, function() {
var params = {Bucket: 'myBucket', Key: 'myKey', Body: 'Hello!'};
Once you created the bucket, go to properties and see what region it is using - add this into:
aws.config.update({
accessKeyId: 'KEY',
secretAccessKey: 'SECRET',
region: 'eu-west-1'
})
Now it should work! Best wishes
I've just come across this issue and I believe the example at http://aws.amazon.com/sdkfornodejs/ is incorrect.
The issue with the demo code is that Bucket names should be in lowercase - http://docs.aws.amazon.com/AmazonS3/latest/dev/BucketRestrictions.html
Had the demo actually output the err argument on the callback in s3.createBucket this would have been immediately obvious.
Also bucket names need to be unique in the region your creating them.
s3.createBucket({Bucket: 'mylowercaseuniquelynamedtestbucket'}, function(err) {
if(err){
console.info(err);
}else{
var params = {Bucket: 'mylowercaseuniquelynamedtestbucket', Key: 'testKey', Body: 'Hello!'};
s3.putObject(params, function(err, data) {
if (err)
console.log(err)
else
console.log("Successfully uploaded data to testBucket/testKey");
});
}
})
Was stuck on this for a while...
Neither setting the region name or leaving it blank in my configuration file fixed the issue. I came across the gist talking about the solution and it was quite simple:
Given:
var AWS = require('aws-sdk');
Prior to instantiating your S3 object do the following:
AWS.config.update({"region": "us-west-2"}) //replacing your region there
I was then able to call the following with no problem:
var storage = new AWS.S3();
var params = {
Bucket: config.aws.s3_bucket,
Key: name,
ACL:'authenticated-read',
Body: data
}
storage.putObject(params, function(storage_err, data){...})

Categories