Securely Upload Files to S3 for Guests Using AWS Cognito
For security reasons, if you allow guest users to upload files from your app, it's better to use Guest Access from AWS Cognito instead of a direct AWS Access Key from an IAM User.
Why?
An IAM User access key is long-lived and never expires.
With AWS Cognito, you can decide how long the temporary guest access key will be valid.
Requirements:
AWS Cognito > Identity pool
S3 Bucket
Step-by-steps:
Create Cognito Identity Pool
Go to Amazon Cognito > Identity pools > Create identity pool
Configure identity pool trust:
Select: Guest access (this enables unauthenticated)
Click Next
- Configure permissions:
Select: Create a new IAM role (Your AWS IAM account needs some permissions to do that)
iam:CreateRole(create role)iam:PutRolePolicy(add inline policies)iam:AttachRolePolicy(attach managed policies)iam:DetachRolePolicy(detach managed policies)iam:TagRole/iam:UntagRole(if you use tags)
Role name: guest-uploader-role or anything you want
Click Next
- Configure properties:
Identity pool name: guest-uploader-pool or anything you want
Click Next
Review and create > Click Create identity pool
Create S3 Bucket
Go to S3 > Click on the button Create bucket
Fill-out your bucket data (eg. bucket name as guest-bucket)
Click Create Bucket
Add S3 Permission to the Role
Go to IAM > Roles > search for guest-uploader-role (you created on the previous step)
Click the role > Add permissions > Create inline policy
Switch to JSON tab, paste:
{ "Version": "2012-10-17", "Statement": [{ "Effect": "Allow", "Action": "s3:PutObject", "Resource": "arn:aws:s3:::guest-bucket/uploads/*" }] }- Note: Because I want to store all guest upload files in the
/uploadsfolder, I put it in the source field.
- Note: Because I want to store all guest upload files in the
Click Next > Name it S3UploadPolicy > Create policy
Update CORS for S3 bucket to allow your frontend to put file:
Go to S3 > Click on bucket guest-bucket or anything you created from previous step
Go to Permissions tab > Scroll down to Cross-origin resource sharing (CORS) (bottom of page)
Click on Edit, paste:
[ { "AllowedHeaders": [ "*" ], "AllowedMethods": [ "PUT" ], "AllowedOrigins": [ "[YOUR_FRONTEND_URL]", ], "ExposeHeaders": [] } ]- Click on Save Changes
Best Practices:
For security reasons, it is advisable to block all public access to the S3 bucket.
To optimize costs, consider setting a lifecycle policy for the bucket, such as deleting files after 6 months if they are not important.