Используя AWS JavaScript SDK, я пытаюсь прочитать определенную корзину S3, когда аутентифицированный пользователь Cognito вошел в защищенную область моего веб-сайта.Я подтвердил, что я вхожу как аутентифицированный пользователь, благодаря действительному authToken, который я получаю после подтверждения моей Cognito Identity.Фактически, я протестировал и доказал весь процесс регистрации, многофакторной проверки, входа и выхода из Cognito.
По какой-то причине, когда я выполняю свой первый запрос s3.getObject, я получаю следующееTypeError, хотя я УВЕРЕН, я передаю строку (ключ) в качестве первого аргумента.Вот ошибка:
TypeError: First argument must be a string, Buffer, ArrayBuffer, Array, or array-like object.
Теперь, во-первых, я включаю JavaScript SDK через тег script на HTML-странице следующим образом:
script src="https://sdk.amazonaws.com/js/aws-sdk-2.154.0.min.js"></script>
У меня есть следующая роль IAMсозданный Cognito:
Cognito_MyAppNameAuth_Role
К которому я добавил следующую политику S3:
{
"Sid": "VisualEditor1",
"Effect": "Allow",
"Action": "s3:ListBucket",
"Resource": "arn:aws:s3:::my-bucket-name"
},
{
"Sid": "VisualEditor2",
"Effect": "Allow",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::my-bucket-name/*"
}
Примечание. Визуальный редактор автоматически вставил эти Sids после того, как я их отредактировал.
Теперь код, который я выполняю для чтения моего сегмента S3, находится в файле .js, который я включаю через тег.Он запускается после загрузки ...
<body onLoad="bodyOnLoad();">
Первое, что делает код, это проверяет учетные данные пользователя.Я получаю пул пользователей;тогда я получаю текущего пользователя.Тогда я получаю сессию.И затем я вызываю учетные данные пользователя с помощью AWS.CognitoIdentityCredentials () следующим образом:
AWS.config.update({ //testing... 12/29
region: 'us-east-1',
accessKeyId: 'anything',
secretAccessKey: 'anything',
credentials: new AWS.CognitoIdentityCredentials({
IdentityPoolId: 'us-east-1:numbers-and-letters-and-bears-oh-my',
Logins: {
'cognito-idp.us-east-1.amazonaws.com/us-east-1-xxxyyyxxx': session.getIdToken().getJwtToken()
}
})
});
Я буквально указываю «что-нибудь» для accessKeyId и secretAccessKey, поскольку я не считаю, что они требуются.Когда это работает, нет ошибок.Все появляется в порядке с проверкой моего аутентифицированного пользователя, принадлежащего требуемому Cognito Identity Pool.
Вот попытка s3.getObject, которая происходит далее и приводит к приведенной выше ошибке TypeError:
const s3 = new AWS.S3({
apiVersion: '2006-03-01',
params: {
Bucket: 'my-bucket-name'
}
});
var params = {
Bucket: 'my-bucket-name',
Key: 'index.json'
};
s3.getObject(params, (err, data) => {
if (err) {
// EXECUTION LANDS HERE!
callback(err);
return;
}
const content = data.Body.toString('utf-8');
callback(null, content);
});
}
Я пробовал много перестановок на пути передачи параметров в метод getObject.В том числе ..
s3.getObject({Key: 'index.json'}, (err, data) => { ... }
Я получаю одну и ту же ошибку каждый раз.Что в мире я делаю неправильно ???Заранее спасибо !!!
ОБНОВЛЕНИЕ 01.01.2009 - HNY!
Отвечая Джону ниже, я изменил свой код, чтобы переместить все в ту же область,(Еще раз спасибо.) Хороший совет, но я все еще получаю ту же ошибку TypeError (показано выше).Теперь, я думаю, Джон может быть прав, что настоящая проблема связана с моей аутентификацией или политикой Identity Pool.Если я удаляю фиктивные accessKeyId и secretAccessKey из AWS.config.update (как Джон удалил их в своем примере), я получаю другую ошибку: я получаю ошибку 400, а затем это ..
Error: Invalid login token. Issuer doesn't match providerName
Вот код, который у меня есть в config.js:
window._config = {
cognito: {
userPoolId: 'user-pool-id',
userPoolClientId: 'user-pool-client-id',
region: 'us-east-1'
},
api: {
invokeUrl: 'https://<invoke-url>.execute-api.us-east-1.amazonaws.com/prod'
}
};
Вот новый поток кода после объединения всех в одну и ту же область:
function loadFileFromS3(key, callback) {
console.log('loadFileFromS3: ' + key); //key is 'index.json'
var poolData = {
UserPoolId: _config.cognito.userPoolId,
ClientId: _config.cognito.userPoolClientId
};
var userPool;
userPool = new AmazonCognitoIdentity.CognitoUserPool(poolData);
if (typeof AWSCognito !== 'undefined') {
AWSCognito.config.region = _config.cognito.region;
}
var cognitoUser = userPool.getCurrentUser();
if (cognitoUser) {
cognitoUser.getSession(function sessionCallback(err, session) {
if (err) {
reject(err);
} else if (!session.isValid()) {
resolve(null);
} else {
console.log('authToken is ' + session.getIdToken().getJwtToken());
// Configure the credentials provider to use your identity pool
AWS.config.update({ //testing... 12/29
region: 'us-east-1',
accessKeyId: 'anything', //remove gives me 400 error as shown above
secretAccessKey: 'anything', //
credentials: new AWS.CognitoIdentityCredentials({
IdentityPoolId: 'us-east-1:<identity-pool-id>',
Logins: {
'cognito-idp.us-east-1.amazonaws.com/us-east-1-<user-pool-id>': session.getIdToken().getJwtToken()
}
})
});
console.log('AWS.config update happened...');
// call refresh to authenticate user and get credentials
AWS.config.credentials.refresh((error) => {
if (error) {
console.error(error);
} else {
console.log('Success');
// NOTE: The credential are valid HERE
const s3 = new AWS.S3({
apiVersion: '2006-03-01',
params: {
Bucket: 'my-bucket-name'
}
});
var params = {
Bucket: 'my-bucket-name',
Key: key
};
console.log('s3.getObject with key: ' + key);
s3.getObject(params, (err, data) => {
if (err) {
console.log('getObject ERROR: ' + err);
callback(err);
return;
}
const content = data.Body.toString('utf-8');
callback(null, content);
});
}
});
}
});
} else {
resolve(null);
}
}
ОБНОВЛЕНИЕ
Хорошо.Проблема не имела ничего общего с аргументом, который я передавал s3.getObject
, и все, что было связано с опечаткой в моем UserPoolId в Logins
.Мне не хватало подчеркивания.Г!Спасибо, Джон, за то, что привел меня в порядок.Я бы навсегда запутался, если бы вы не предложили мне перепроверить.
Исправление кода выше:
Logins: {
'cognito-idp.us-east-1.amazonaws.com/us-east-1_<user-pool-id>': session.getIdToken().getJwtToken() //underscore after us-east-1_ !!!