Generate pre-signed Url for the file via Node.Js

Ankit Kumar Rajpoot
4 min readMay 25, 2020

A pre-signed URL is a URL that you can provide to your users to grant temporary access to a specific S3 object. Using the URL, a user can either READ the object or WRITE an Object (or update an existing object).

You can give also create a pre-signed URL — meaning users can interact with objects without the need for AWS credentials or IAM permissions.

I am assuming, you have already a bucket and IAM user with accessKeyId and secretAccessKey . Give inline(JSON) s3full permission to the user which is given below-

{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "PublicReadGetObject",
"Effect": "Allow",
"Action": [
"s3:PutObject",
"s3:PutObjectAcl",
"s3:GetObject",
"s3:GetObjectAcl",
"s3:DeleteObject"
],sme-testing
"Resource": [
"arn:aws:s3:::sme-testing/*" // Bucket Name
]
}
]
}

Set Bucket policy which is given below:-

{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::706126218522:user/user-name" // User name
},
"Action": [
"s3:PutObject",
"s3:PutObjectAcl",
"s3:GetObject",
"s3:GetObjectAcl",
"s3:DeleteObject"
],
"Resource": "arn:aws:s3:::sme-testing/*"
}
]
}

Set Default encryption:- Go to bucket’s properties section and select(AES-256) Use Server-Side Encryption with Amazon S3-Managed Keys (SSE-S3).

Set aws-sdk:-

const AWS = require("aws-sdk");const s3 = new AWS.S3({
endpoint: 's3-ap-south-1.amazonaws.com', // Put you region
accessKeyId: 'AKXXXXXXXXXXXXXXXA6U', // Put you accessKeyId
secretAccessKey: 'kzFHoXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXssoGp', // Put you accessKeyId
Bucket: 'Bucket-Name', // Put your bucket name
signatureVersion: 'v4',
region: 'ap-south-1' // Put you region
});

Upload a file in S3 bucket without pre-signed URL:-

var uploadPan = async () => {
const ext = '.pdf'
const fileName = crypto.randomBytes(16).toString("hex") + ext;
console.log("File Name ------>", fileName)
const buf = fs.readFileSync('document.pdf');
console.log(buf)
var params = {
Bucket: 'Bucket-Name', // Put your bucket name
Key: fileName, // Put new file name
ContentEncoding: 'base64',
ContentDisposition: 'inline',
Body: buf
};
try{
const data = await s3.putObject(params).promise();
console.log(data);
} catch (err) {
if (err) {
console.log(err)
}
}
};
uploadPan() // Call function to upload file.

OutPut URL:-

File Name ------> 0cfdbb61f798a31f66eb254b3d35e921.pdf
<Buffer 25 50 44 46 2d 31 2e 33 0a 25 ff ff ff ff 0a 36 20 30 20 6f 62 6a 0a 3c 3c 0a 2f 50 72 65 64 69 63 74 6f 72 20 31 35 0a 2f 43 6f 6c 6f 72 73 20 31 0a ... >
{ ETag: '"07c8393c487fad766b0bb6e52359355a"',
ServerSideEncryption: 'AES256' }

Generate pre-signed URL to download a file:-

The URL contains specific parameters that are set by your application. A pre-signed URL uses three parameters to limit access to the user;

  • Bucket: The bucket that the object is in (or will be in)
  • Key: The name of the object(Filename for signed URL)
  • Expires: The duration of time that the URL is valid(In seconds)
const getSingedUrl = async () => {const params = {
Bucket: 'Bucket-Name',
Key: '317ec11af14a46b89f400bcf8f9fff12.pdf',
Expires: 60 * 5
};
try {
const url = await new Promise((resolve, reject) => {
s3.getSignedUrl('getObject', params, (err, url) => {
err ? reject(err) : resolve(url);
});
});
console.log(url)
} catch (err) {
if (err) {
console.log(err)
}
}
}
getSingedUrl() // Call function to generate pre-signed url.

OutPut URL:- This is the signed URL for download 317ec11af14a46b89f400bcf8f9fff12.pdf file.

https://sme-testing.s3-ap-south-1.amazonaws.com/317ec11af14a46b89f400bcf8f9fff12.pdf?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AXXXXXXXXXXXXXXA6U%2F20200524%2Fap-south-1%2Fs3%2Faws4_request&X-Amz-Date=20200524T225329Z&X-Amz-Expires=300&X-Amz-Signature=a46f53fhdfjkahjaskjhfasjkfhjahshsaidfahfhjkashfieuiwq900rufqweqfhaasfhjah81bd6c4f50826&X-Amz-SignedHeaders=host

Via this URL you can download the file within 5 minutes because we have set expire time 5 minutes.

Generate pre-signed URL to upload a file:-

const getSingedUrlforPut = async () => {const params = {
Bucket: 'Bucket-Name',
Key: '317ec11af14a46b89f400bcf8f9fff1222.pdf',
Expires: 60 * 5
};
try {
const url = await new Promise((resolve, reject) => {
s3.getSignedUrl('putObject', params, (err, url) => {
err ? reject(err) : resolve(url);
});
});
console.log(url)
} catch (err) {
if (err) {
console.log(err)
}
}
}
getSingedUrlforPut()

OutPut URL:- This is the signed URL for upload 317ec11af14a46b89f400bcf8f9fff1222.pdf file.

https://sme-testing.s3-ap-south-1.amazonaws.com/317ec11af14a46b89f400bcf8f9fff1222.pdf?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AXXXXXXXXXXXXXXA6U%2F20200525%2Fap-south-1%2Fs3%2Faws4_request&X-Amz-Date=20200525T085040Z&X-Amz-Expires=300&X-Amz-Signature=1f0ecf99d207176156e9316f640ecc0fa36177e02e2a9f35a8100bcf649542bb&X-Amz-SignedHeaders=host

Upload file via pre-signed URL:-

In this section, we will upload a file in s3 via pre-signed URL with the help of postman. Put this URL in the URL section, select the put method in postman and select file in the form-data section.

This is the code for javaScript-jquery and you can see any language’s code from the postman right corner.

var form = new FormData();
form.append("", fileInput.files[0], "director_pan_af8ef2d261c46877f95038622c96e7c0.pdf");
var settings = {
"url": "https://sme-testing.s3-ap-south-1.amazonaws.com/317ec11af14a46b89f400bcf8f9fff1222.pdf?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIXXXXXXXXXXXX6U%2F20200525%2Fap-south-1%2Fs3%2Faws4_request&X-Amz-Date=20200525T083419Z&X-Amz-Expires=300&X-Amz-Signature=ea063731d7d043b62d0dc7c0984f4d5792c7f7f41e9ffb52a97d62adadcef422&X-Amz-SignedHeaders=host",
"method": "PUT",
"timeout": 0,
"processData": false,
"mimeType": "multipart/form-data",
"contentType": false,
"data": form
};
$.ajax(settings).done(function (response) {
console.log(response);
});

You can see any language code from the postman’s code section.

Anyone with a valid pre-signed URL can interact with the objects as specified during creation. For example, if a GET (Read) pre-signed URL is provided, a user could not use this as a PUT (Write). and for any other use.

--

--

Ankit Kumar Rajpoot

I’m a MERN Developer. ( Redux | AWS | Python ) I enjoy taking on new things, building skills, and sharing what I’ve learned.