Daniel Bayerlein
Posted on April 28, 2020
AWS Amplify is a development platform for building secure, scalable mobile and web applications. It provides several libraries for the communication with the AWS services.
In this blog post I show you how to store images (also audio, video, etc. possible) on Amazon S3 using a React application.
This example uses the @aws-amplify/storage
and the @aws-amplify/auth
package. More on this later.
To manage the infrastructure I use the Serverless Framework.
Amazon S3 and Cognito Identity Pool
For the upload we need a S3 bucket to store the files and a Cognito Identity Pool for access control.
Configure S3 bucket
First of all you need a S3 bucket. I create it as a private bucket called example-bucket
.
The CORS configuration is important, otherwise some CORS exceptions occur and the upload will not work. You can also define the allowed methods - in the example GET
and PUT
are allowed.
S3ImageBucket:
Type: AWS::S3::Bucket
Properties:
BucketName: example-bucket
AccessControl: Private
CorsConfiguration:
CorsRules:
-
AllowedOrigins:
- '*'
AllowedHeaders:
- '*'
AllowedMethods:
- GET
- PUT
MaxAge: 3000
ExposedHeaders:
- x-amz-server-side-encryption
- x-amz-request-id
- x-amz-id-2
- ETag
Configure Cognito Identity Pool
After the S3 bucket has been created, a Cognito Identity Pool must be created.
I use an existing Cognito User Pool as provider. This can be configured with the CognitoIdentityProviders
option. Of course you can also use another provider. In the policy, I specify which actions may be carried out. In this case s3:GetObject
and s3:PutObject
.
CognitoIdentityPool:
Type: AWS::Cognito::IdentityPool
Properties:
IdentityPoolName: ${self:service}-${self:provider.stage}-${self:provider.region}-IdentityPool
AllowUnauthenticatedIdentities: false
CognitoIdentityProviders:
- ClientId: 111xxx111xxx111xxx111
ProviderName: cognito-idp.eu-central-1.amazonaws.com/eu-central-1_XXX
CognitoIdentityPoolRoles:
Type: AWS::Cognito::IdentityPoolRoleAttachment
Properties:
IdentityPoolId:
Ref: CognitoIdentityPool
Roles:
authenticated:
!GetAtt CognitoAuthRole.Arn
CognitoAuthRole:
Type: AWS::IAM::Role
Properties:
Path: /
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: 'Allow'
Principal:
Federated: 'cognito-identity.amazonaws.com'
Action:
- 'sts:AssumeRoleWithWebIdentity'
Condition:
StringEquals:
'cognito-identity.amazonaws.com:aud':
Ref: CognitoIdentityPool
'ForAnyValue:StringLike':
'cognito-identity.amazonaws.com:amr': authenticated
Policies:
- PolicyName: ${self:service}-${self:provider.stage}-${self:provider.region}-S3CognitoAuthPolicy
PolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: 'Allow'
Action:
- 's3:GetObject'
- 's3:PutObject'
Resource:
- !Join [ '', [ !GetAtt S3ImageBucket.Arn, '/*' ]
š” You can also set a role for unauthenticated users via unauthenticated
if your application requires access to the S3 bucket.
The Storage module
The @aws-amplify/storage
module provides a simple mechanism for managing user content for your app in public, protected or private storage buckets.
Configure Amplify Storage
The configuration is very simple. You only have to set the bucket
name and the region
of this S3 bucket.
import Storage from '@aws-amplify/storage'
Storage.configure({
AWSS3: {
bucket: 'example-bucket',
region: 'eu-central-1'
}
})
The Auth module
Additionally we need the @aws-amplify/auth
module so that the application can authenticate itself.
Configure Amplify Auth
The configuration object expects the following parameters:
-
region
: Region of your Amazon Cognito -
identityPoolId
: ID of your Amazon Cognito Identity Pool -
userPoolId
: ID of your Amazon Cognito User Pool -
userPoolWebClientId
: Web Client ID of your Amazon Cognito User Pool
As code it looks like this:
import Auth from '@aws-amplify/auth'
Auth.configure({
region: 'eu-central-1',
identityPoolId: 'eu-central-1:xxx-xxx-xxx-xxx-xxxxxx',
userPoolId: 'eu-central-1_XXX',
userPoolWebClientId: '111xxx111xxx111xxx111'
})
Using Amplify Storage
Enough configurations, time for usage. š
With the Storage.put()
function you can put the data to S3. It returns a {key: S3 Object key}
object on success.
const S3ImageUpload = () => {
const onChange = async (file) => {
const { key } = await Storage.put('example.png', file, {
contentType: 'image/png'
})
console.log('S3 Object key', key)
}
return (
<input
type='file'
accept='image/png'
onChange={(e) => onChange(e.target.files[0])}
/>
)
}
With the return value (key
) and the function Storage.get()
you can retrieve the image again.
š All Storage functions can be found in the documentation.
Posted on April 28, 2020
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.