Originally posted on my personal blog http://haidrali.com/aws-s3-file-upload-from-client-side/
Last week I pushed a new feature on production which involve file upload on AWS S3. When you are uploading file to S3 from frontend there is always a risk of exposing your AWS secrets to user, so you have following options to avoid this risk
- Involve server as middleware and upload via server API, you will have more control over it
- Allow users to upload directly to S3 anonymously
I don’t like both of above methods, as involving middleware you are uploading file twice i.e. frontend → server, server → s3 bucket and I don’t really want server to do this heavy lifting of uploading files to S3 on user behalf, while allowing user anonymous upload you are giving a blank check to you S3 bucket i.e. anyone in the world can upload to your s3 bucket, this was also not acceptable to me as this could have very swear consequences. I wanted to have bit more control over uploads while not compromising security issues, so I used AWS Security Token Service to generate secrets (access_key, access_secret) which lived temporarily and have limited access as you define it.
H3 Configure an IAM user on AWS console to generate temporary secrets
In order to generate temporary secrets you need following configurations on AWS console
- create a new IAM user
- create a policy to allow upload on S3 bucket
- create a role for you IAM user to assume Security Token Service
Watch this video for configurations
Now, you can generate AWS STS with this ruby code
aws_sts = AWS::STS::Client.new(
access_key_id: ENV['AWS_ACCESS_KEY_ID'],
secret_access_key: ENV['AWS_SECRET_ACCESS_KEY']
).assume_role(
role_arn: ENV['AWS_ROLE_ARN'],
role_session_name: 'session_name',
duration_seconds: 12*60*60)
// this will generate access_key, access_secret
aws_sts.credentials
AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY are credentials you download after creating user and AWS_ROLE_ARN is value which I copied at the end of video
H3 Enable ACL uploading to S3
You will be able to successfully upload files with secrets generated with above code, Since we have used a separate user to generate STS then only this user will be able to access file. To make this file accessible by other user as well you must send ACL: 'public-read' in request body or header while uploading file to S3. you can read more about ACL
I hope this help you improve your file upload as well. If you need any help please do ping me on twitter @alihaider907.
Top comments (1)
The alternative is to have your server generate a pre-signed POST URL that the client can invoke to upload the file. That way, you don't have to generate any credential to expose in the frontend, but the actual upload is done directly by the client.