Постоянная ошибка типа при попытке получить объект в корзине S3, требующей аутентифицированного доступа

Используя 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.

См. также:  GCP: можно ли использовать Pony ORM с облачными функциями и Cloud SQL

Вот попытка 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_ !!!

Понравилась статья? Поделиться с друзьями:
IT Шеф
Комментарии: 1
  1. motivus

    Я думаю, что ваша настоящая проблема в том, что у вас нет учетных данных для пользователя.

    AWS.config.update({ //testing... 12/29
      region: 'us-east-1',
      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()
        }
      })
    });
    
    // 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
        // Put your S3 code HERE.
        const s3 = new AWS.S3({
          apiVersion: '2006-03-01',
          params: {
            Bucket: 'my-bucket-name'
          }
        });
        // Continue with the rest of your S3 code HERE
      }
    });
    // The credentials are not valid HERE
    

    Спасибо, Джон. Я внес рекомендованные вами изменения, но по-прежнему получаю ту же ошибку. Однако я думаю, что вы правы в том, что эта ошибка 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

Добавить комментарий

;-) :| :x :twisted: :smile: :shock: :sad: :roll: :razz: :oops: :o :mrgreen: :lol: :idea: :grin: :evil: :cry: :cool: :arrow: :???: :?: :!: