Используя 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 через тег скрипта на 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/*"
}
Примечание. Визуальный редактор вставил эти идентификаторы автоматически после того, как я его отредактировал.
Теперь код, который я выполняю для чтения моей корзины 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.
Вот попытка 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.2019 — 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_ !!!
Я думаю, что ваша настоящая проблема в том, что у вас нет учетных данных для пользователя.
Спасибо, Джон. Я внес рекомендованные вами изменения, но по-прежнему получаю ту же ошибку. Однако я думаю, что вы правы в том, что эта ошибка TypeError маскирует реальную проблему и связана с аутентификацией или политикой. Тем не менее, ваш совет был хорош, и я поместил все в ту же область. Я собираюсь опубликовать новый код ниже и посмотреть, есть ли другие идеи оттуда. — person motivus; 01.01.2019
Это был какой-то пост, который заставил меня включить фиктивные accessKeyId и secretAccessKey в обновление конфигурации. Я вижу, вы их удалили. Я тоже сделал это, и это привело к ошибке 400: Ошибка: недопустимый токен входа. Эмитент не совпадает с providerName. Я не совсем уверен, что это значит и как с этим бороться. Я расследую … — person motivus; 01.01.2019
Ваша последняя ошибка теперь имеет смысл. Добавьте к своему вопросу код, в котором вы обрабатываете пользователя Cognito. Это также необходимо правильно настроить. — person motivus; 01.01.2019
Хорошо. Поскольку я построил свое решение на основе двух разных примеров AWS, я все время беспокоился, что они могут мешать друг другу при интеграции и настройке. Прямо сейчас единственный важный код, который, как мне кажется, я упустил, — это код, который находится в моем config.js. Это происходит следующим образом … (но я собираюсь просмотреть код Cognito, который у меня есть в трех разных файлах .js, все они включены на страницу html). ‘window._config = {cognito: {userPoolId:’ user-pool-id ‘, userPoolClientId:’ user-pool-client-id ‘, region:’ us-east-1 ‘}, api: {invokeUrl: // this пока не вызывается}}; — person motivus; 01.01.2019
Дважды проверьте свои
Logins
карту иIdentityPoolId
и убедитесь, что вы правильно указали идентификаторы. — person motivus; 01.01.2019Фу. У меня в UserPoolId был дефис вместо подчеркивания. Это решило проблему, и код будет выполняться до следующей ошибки, которая кажется совершенно другой. Я обновлю свой вопрос и отмечу ответ как можно скорее. Спасибо брат! С Новым Годом! (Исправлено: я имел в виду UserPoolId) — person motivus; 01.01.2019
Отлично — рад помочь. Я много работал с Cognito. Если у вас есть другая проблема, задайте новый вопрос и напишите мне. Я постараюсь помочь. — person motivus; 01.01.2019