File upload to S3, define access per user

Hi all,
I would like your help to figure out the following:

The scenario
I have an app with many users, these users are able to upload (sensitive) files (stored in S3). Per file, the user sets sharing permission who can read the file (similar to Dropbox). I am figuring out the best security practice. Only the users who are allowed to view a file should be able to download these files - if a user shares a download link it should obviously not work.

My suggestions
My initial thought was to use S3’s authentication framework, but it would require to create an Amazon user for every user on my app and store their keys. That doesn’t seem right. So, I intend to have one Amazon user (and one bucket?) who authenticates all file uploads from the app. Then in the database, I will keep track which users are allowed to access the files. By using temporary signed links I will create download links when a user wants to download a file. This basically shifts the whole security to my app, not sure if that is proper.

What are your thoughts on this?

1 Like

Hi

take a look at edgee:slingshot atmosphere package this works well allowing the upload to go directly from browser to S3 (not via your server) in a secure way.

A.

Thanks, Annie, however, the issue is not uploading the files, it is making them private. All the files you upload with Slingshot etc are public for everybody to view/download.

I fixed the problem, I will leave my solution here for future reference if anybody has a similar problem.

I used the S3 npm package to do client-side upload to my S3 bucket - similar to Slingshot. I set the acl rights of the files to private when you upload and store the filepath in the database. Then I used the AWS SDK npm to create signed links (valid for 1 minute) whenever a user wants to download the file.

'files.getSignedUrl': function (file) {
    check(file, String);
    filePath = file.substr(1);

    const s3 = new S3({
      credentials: {
        accessKeyId: Meteor.settings.private.S3.accessKeyId,
        secretAccessKey: Meteor.settings.private.S3.secretAccessKey,
      },
      region: 'ap-southeast-1',
    });

    const url = s3.getSignedUrl('getObject', {
      Bucket: 'xxxxxxx',
      Key: filePath,
      Expires: 60,
    });

    return url;
  },

Hope this helps

4 Likes

Thank you so much Paul! This is indeed very helpful! :gift::gift::gift: