Pre-Signed AWS S3 URLs with Firebase Functions

Obtaining a pre-signed URL from S3 with a custom backend

Google Cloud Functions to the rescue

Obtaining a pre-signed URL from S3 with Google Cloud Functions
<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<CORSRule>
<AllowedOrigin>*</AllowedOrigin>
<AllowedMethod>GET</AllowedMethod>
<AllowedMethod>POST</AllowedMethod>
<AllowedMethod>PUT</AllowedMethod>
<AllowedMethod>HEAD</AllowedMethod>
<AllowedMethod>DELETE</AllowedMethod>
<MaxAgeSeconds>3000</MaxAgeSeconds>
<AllowedHeader>*</AllowedHeader>
</CORSRule>
</CORSConfiguration>
functions/
index.js
node-modules/
package-lock.json
package.json
aws_access_key_id = YOUR_ACCESS_KEY_ID
aws_secret_access_key = YOUR_SECRET_ACCESS_KEY
npm add aws-sdk
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp();
const AWS = require('aws-sdk');
exports.getS3SignedUrlUpload = functions.https.onCall((data, context) => {
AWS.config.update({
accessKeyId: "YOUR_ACCESS_KEY_ID",
secretAccessKey: "YOUR_SECRET_ACCESS_KEY",
region: "YOUR_AWS_REGION" // (e.g. :)"eu-west-1"
});
var s3 = new AWS.S3();
const s3Params = {
Bucket: data.S3BucketName,
Key: data.key,
Expires: 600, // Expires in 10 minutes
ContentType: data.contentType,
ACL: 'public-read', // Could be something else
ServerSideEncryption: 'AES256'
};
return s3.getSignedUrl('putObject', s3Params);
});
exports.getS3SignedUrlUpload = functions.https.onCall((data, context) =>
data {
S3BucketName: "my-bucket-name",
key: "file-to-upload-name",
contentType: "mime-content-type", // E.g.: "application/zip",
}
  AWS.config.update({
accessKeyId: "YOUR_ACCESS_KEY_ID",
secretAccessKey: "YOUR_SECRET_ACCESS_KEY",
region: "YOUR_AWS_REGION" // (e.g. :)"eu-west-1"
});
var s3 = new AWS.S3();
  const s3Params = {
Bucket: data.S3BucketName,
Key: data.key,
Expires: 600, // Expires in 10 minutes
ContentType: data.contentType,
ACL: 'public-read', // Could be something else
ServerSideEncryption: 'AES256'
};
return s3.getSignedUrl('putObject', s3Params);
...// Retrieve the Cloud Function
var getPost = functions.httpsCallable('getS3SignedUrlUpload');
// Call the cloud function
getPost(s3GetUrlParams).then(result => {
// S3 pre-signed URL
const options = {
headers: {
'Content-Type': 'application/zip',
'x-amz-acl': 'public-read',
'x-amz-server-side-encryption': 'AES256'
}
};
// Run a HTTP PUT request to the pre-signed URL
return axios.put(result.data, this.state.zipFile, options)
.then(result => {...});
}
return s3.getSignedUrl('getObject', s3Params);

Conclusion

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store