Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

'Credential is missing' Error On Instantiating S3 Class Using AWS-SDK JS V3

I am getting en error when creating S3 client from class S3 in newer v3 of aws-sdk javascript.

I add aws config parameters including credentials obtained from aws sts when user gets authenticated (assuming a role with permission to call getObject) at service-level (when instantiating S3 class) along with other parameters. See my code below:

const { S3, ... } = require("@aws-sdk/client-s3");

someFunc();
function someFunc(authUserCredentials) {
 ...
 try {

   const { AccessKeyid, SecretKey, SessionToken } = authUserCredentials;
   const s3Client = new S3({
                      signatureVersion: 'v4',
                      accessKeyId: AccessKeyId,
                      secretAccessKey: SecretKey,
                      sessionToken: SessionToken,
                      region: 'us-east-1',
   });

   console.log(s3Client.config);
   ...

 }catch(e) {
     console.error(e);
 }
}

I checked the class S3 code in aws-sdk-js-v3 repo, and there doesn't seem to be no 'Credential' constructor config argument required. Am I doing something wrong?

like image 875
Waleed93 Avatar asked Jun 27 '20 15:06

Waleed93


4 Answers

Just to clarify Chris Williams's answer combined with @Waleed93's second comment, what used to work with the AWS Javascript SDK v2 is:

import S3 from 'aws-sdk/clients/s3';

const AccessKeyId = xxxxx,
      SecretKey = yyyyyyyy,
      SessionToken = zzzzzzzzzz;

const s3Client = new S3({
    apiVersion: '2006-03-01',
    region: 'us-east-1',
    accessKeyId: AccessKeyId,
    secretAccessKey: SecretKey,
    sessionToken: SessionToken
});

For SDK v3, the constructor no longer accepts individual credential parameters but does take a "credentials" object as a parameter. What works is:

const { S3 } = require('@aws-sdk/client-s3');

const AccessKeyId = xxxxx,
      SecretKey = yyyyyyyy,
      SessionToken = zzzzzzzzzz;

const creds = {
    accessKeyId: AccessKeyId,
    secretAccessKey: SecretKey,
    sessionToken: SessionToken
};

const s3Client = new S3({
    apiVersion: '2006-03-01',
    region: 'us-east-1',
    credentials: creds
});

This change is nowhere to be found in the AWS SDK documentation, class reference, or Developer Guide for SDK Version 3. Thank you to Chris and @Waleed93 for figuring it out.

like image 69
JJJSchmidt Avatar answered Oct 10 '22 16:10

JJJSchmidt


According to the documentation for the constructor these arguments are valid.

There is still an argument name for the Credential object with the name credentials. If you instantiate a AWS.Credentials object you can pass this into that argument.

like image 28
Chris Williams Avatar answered Oct 10 '22 15:10

Chris Williams


The value of credentials should be an object containing your credentials passed into the config as below:

import { S3Client, GetObjectCommand } from '@aws-sdk/client-s3'

const CREDENTIAL = {
  accessKeyId: 'accesKeyIdString',
  secretAccessKey: 'secretAccessKeyIdString',
};

const REGION: 'aws region';
const s3Client = new S3Client({region: REGION, credentials: CREDENTIAL});
like image 1
Rex Osariemen Avatar answered Oct 10 '22 14:10

Rex Osariemen


I'm going to expand on this a bit more with my own experiences. I was working through this guide from AWS for "Viewing Photos in an Amazon S3 Bucket from a Browser" (giving guest users -- no login --, the ability to interact with s3 objects through a cognito identity pool). The resources in the AWS guide are for the V2 version of the SDK. So, I had to do a lot of digging to set it up for V3.

So, in short I'm doing the following:

  • using V3 SDK for javascript
  • getting credentials from an AWS Cognito Identity Pool (see linked guide)
  • using those credentials in the new S3({ ... credentials })
import { fromCognitoIdentityPool } from "@aws-sdk/credential-providers";
import { S3, ListObjectsCommand } from "@aws-sdk/client-s3";

// get identity pool creds (in my case)
const credentials = fromCognitoIdentityPool({
  identityPoolId: "your-identity-pool-id",
  clientConfig: { region: "your-region" },
});

// initialize V3 SDK S3 class
const client = new S3({
  apiVersion: "2006-03-01",
  region: "your-region",
  // plug in credentials
  credentials,
});

...

This was my specific use case. Here are the resources I found really helpful.

  • getting credentials: https://www.npmjs.com/package/@aws-sdk/credential-providers
  • great V3 SDK resource: https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/clients/client-s3/modules/credentials.html#sessiontoken
like image 1
kevin Avatar answered Oct 10 '22 14:10

kevin