Let’s now add an attachment to our note. The flow we are using here is very simple.

  1. The user selects a file to upload.

  2. The file is uploaded to S3 under the user’s space and we get a URL back.

  3. Create a note with the file URL as the attachment.

We are going to use the AWS SDK to upload our files to S3. The S3 Bucket that we created previously, is secured using our Cognito Identity Pool. So to be able to upload, we first need to generate our Cognito Identity temporary credentials with our user token.

Get Cognito Identity Pool Credentials

We are going to use the NPM module aws-sdk to help us get the Identity Pool credentials.

Install it by running the following in your project root.

$ npm install aws-sdk --save

Next, let’s append the following to our src/libs/awsLib.js.

export function getAwsCredentials(userToken) {
  const authenticator = `cognito-idp.${config.cognito.REGION}.amazonaws.com/${config.cognito.USER_POOL_ID}`;

  AWS.config.update({ region: config.cognito.REGION });

  AWS.config.credentials = new AWS.CognitoIdentityCredentials({
    IdentityPoolId: config.cognito.IDENTITY_POOL_ID,
    Logins: {
      [authenticator]: userToken

  return AWS.config.credentials.getPromise();

And include the AWS SDK in our header.

import AWS from 'aws-sdk';

To get our AWS credentials we need to add the following to our src/config.js in the cognito block. Make sure to replace YOUR_IDENTITY_POOL_ID with your Identity pool ID from the Create a Cognito identity pool chapter.

REGION: 'us-east-1',

Now we are ready to upload a file to S3.

Upload to S3

Append the following in src/awsLib.js.

export async function s3Upload(file, userToken) {
  await getAwsCredentials(userToken);

  const s3 = new AWS.S3({
    params: {
      Bucket: config.s3.BUCKET,
  const filename = `${AWS.config.credentials.identityId}-${Date.now()}-${file.name}`;

  return s3.upload({
    Key: filename,
    Body: file,
    ContentType: file.type,
    ACL: 'public-read',

And add this to our src/config.js above the apiGateway block. Make sure to replace YOUR_S3_UPLOADS_BUCKET_NAME with the your S3 Bucket name from the Create an S3 bucket for file uploads chapter.

s3: {

The above method does a couple of things.

  1. It takes a file object and the user token as parameters.

  2. Generates a unique file name prefixed with the identityId. This is necessary to secure the files on a per-user basis.

  3. Upload the file to S3 and set it’s permissions to public-read to ensure that we can download it later.

  4. And return a Promise object.

Upload Before Creating a Note

Now that we have our upload methods ready, let’s call them from the create note method.

Replace the handleSubmit method in src/containers/NewNote.js with the following.

handleSubmit = async (event) => {

  if (this.file && this.file.size > config.MAX_ATTACHMENT_SIZE) {
    alert('Please pick a file smaller than 5MB');

  this.setState({ isLoading: true });

  try {
    const uploadedFilename = (this.file)
      ? (await s3Upload(this.file, this.props.userToken)).Location
      : null;

    await this.createNote({
      content: this.state.content,
      attachment: uploadedFilename,
  catch(e) {
    this.setState({ isLoading: false });


And make sure to include s3Upload in the header by doing this:

import { invokeApig, s3Upload } from '../libs/awsLib';

The change we’ve made in the handleSubmit is that:

  1. We upload the file using s3Upload.

  2. Use the returned URL and add that to the note object when we create the note.

Now when we switch over to our browser and submit the form with an uploaded file we should see the note being created successfully. And the app being redirected to the homepage.

Next up we are going to make sure we clear out AWS credentials that are cached by the AWS JS SDK before we move on.