Eric Seastrand
Eric Seastrand

Reputation: 2633

How can I use AWS Signature Version 4 with AWS Javascript SDK to upload to S3 from the browser?

I need to be able to upload large (1+ gb) files to S3 from the user's browser. Sending them through the application server (PHP) is simply not an option because of size and load constraints.

I would like to use the AWS Javascript SDK to do this, as shown here: http://docs.aws.amazon.com/AWSJavaScriptSDK/guide/browser-examples.html#Uploading_a_local_file_using_the_File_API

The problem is, the Javascript SDK only (officially) lists a few authentication methods, and it isn't clear how you can make the SDK use "AWS Signature V4" authentication, as shown here: http://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-post-example.html

The question is: Can you use "Signature V4" with the "AWS JS SDK"?

Edit: It sounds like maybe I need to use the "Security Token Service" : http://docs.aws.amazon.com/STS/latest/APIReference/API_AssumeRole.html Can anyone confirm if this is the right way to go?

More specifics that may be relevant: My use case is in the admin area of an online store, where the admin user is already authenticated by logging into the admin section, but still shouldn't be able to see the master AWS secret key. The AWS JS SDK lets you authenticate with Facebook or other ID providers, but this would be a weird user-experience since the admin has already logged in.

Because this functionality must be packaged into a single module for installation in an ecommerce platform (Magento,) it isn't feasible to ask the installer to also go and create a new IAM role with separate credentials just for the uploader feature.

Upvotes: 2

Views: 5460

Answers (3)

RajeevJ
RajeevJ

Reputation: 151

Adding more info to the accepted answer, you can refer to my blog to see a running version of the code, using AWS Signature version 4.

Will summarize here:

As soon as the user selects a file to be uploaded, do the followings:

  1. Make a call to the web server to initiate a service to generate required params

  2. In this service, make a call to AWS IAM service to get temporary cred

  3. Once you have the cred, create a bucket policy (base 64 encoded string). Then sign the bucket policy with the temporary secret access key to generate final signature

  4. Send the necessary parameters back to the UI

  5. Once this is received, create a html form object, set the required params and POST it.

For detailed info, please refer https://wordpress1763.wordpress.com/2016/10/03/browser-based-upload-aws-signature-version-4/

Upvotes: -1

Krishna Srinivas
Krishna Srinivas

Reputation: 1700

To upload files from browser to S3 you can use presigned PUT. This way you will not be disclosing the aws secret to the browser. You can use the minio-js library to generate presigned PUT url.

On the server side you can generate the presigned PUT url like this:

var Minio = require('minio')

// find out your s3 end point here:
// http://docs.aws.amazon.com/general/latest/gr/rande.html#s3_region

var s3Client = new Minio({
    endPoint: 's3.amazonaws.com',
    accessKey: 'YOUR-ACCESSKEYID',
    secretKey: 'YOUR-SECRETACCESSKEY'
})
var presignedUrl = s3Client.presignedPutObject('bucket', 'object', 24*60*60)
// presignedUrl expires in 1 day

You can pass this presigned URL to the browser which can just do a simple HTTP PUT to amazon s3. The PUT request will succeed because the signature will be part of the presignedUrl.

You can also alternatively use presigned POST to upload too.

Upvotes: 4

TaraW
TaraW

Reputation: 225

You have 2 options since hardcoding credentials is never a good choice.

  1. Amazon Cognito
  2. Web Identity Federation

I would suggest you leverage the AWS SDK for JavaScript with AWS Cognito with Developer Authenticated Identities. The scenario you noted is exactly what Cognito was designed to address. You can have the admin log in to the system with your own designed auth method as you are doing now, but use that authorization to generate a token via Cognito that can be used to authenticate for all the AWS services.

For examples of both scenarios, please review the AWS JavaScript Developer Guide: Loading Credentials in the Client's Browser: http://docs.aws.amazon.com/AWSJavaScriptSDK/guide/browser-configuring.html#Loading_Credentials_in_the_Client_s_Browser

References that may also assist you:

Amazon Cognito Developer Authenticated Identities: http://docs.aws.amazon.com/cognito/devguide/identity/developer-authenticated-identities/

Identity Providers and Federation: http://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers.html

AWS SDK for JavaScript Developer Guide: http://docs.aws.amazon.com/AWSJavaScriptSDK/guide/index.html

Upvotes: 1

Related Questions