Uploading Files Securely to AWS S3 Using Presigned URLs

Uploading Files Securely to AWS S3 Using Presigned URLs Subtitle: A practical guide to keeping your uploads safe by generating and using AWS presigned URLs in your web applications. Uploading files directly to AWS S3 from a frontend app can be risky if not handled securely. Exposing your S3 credentials or allowing open write access is a big no-no. The best practice? Use presigned URLs — short-lived links that grant temporary access to upload a specific file. In this tutorial, you'll learn how to securely generate and use presigned URLs for file uploads using Node.js and AWS SDK v3. Step 1: Set Up Your AWS S3 Bucket In the AWS Console: Create an S3 bucket (or use an existing one). Ensure it has private access by default. Enable CORS (Cross-Origin Resource Sharing) to allow browser-based uploads. Example configuration: { "CORSRules": [ { "AllowedHeaders": ["*"], "AllowedMethods": ["PUT"], "AllowedOrigins": ["*"], "ExposeHeaders": [] } ] } Step 2: Install the AWS SDK npm install @aws-sdk/client-s3 @aws-sdk/s3-request-presigner Step 3: Generate the Presigned URL in Your Backend Create an endpoint that your frontend can call to get a temporary upload URL. // server.js (Node.js/Express) import express from 'express'; import { S3Client, PutObjectCommand } from '@aws-sdk/client-s3'; import { getSignedUrl } from '@aws-sdk/s3-request-presigner'; const app = express(); const s3 = new S3Client({ region: 'your-region' }); app.get('/generate-presigned-url', async (req, res) => { const { fileName, fileType } = req.query; const command = new PutObjectCommand({ Bucket: 'your-bucket-name', Key: fileName, ContentType: fileType }); const url = await getSignedUrl(s3, command, { expiresIn: 60 }); // 1 minute res.json({ url }); }); app.listen(3000, () => console.log('Server running on port 3000')); Step 4: Upload the File in Your Frontend // JavaScript (frontend) async function uploadFile(file) { const res = await fetch(`/generate-presigned-url?fileName=${file.name}&fileType=${file.type}`); const { url } = await res.json(); await fetch(url, { method: 'PUT', headers: { 'Content-Type': file.type }, body: file }); alert('Upload complete!'); } Conclusion Presigned URLs are a secure and scalable solution for file uploads in modern web apps. By delegating the responsibility to AWS, you minimize backend load and eliminate security risks associated with direct uploads. Make sure to apply appropriate file type and size validations before generating URLs!

Apr 9, 2025 - 08:40
 0
Uploading Files Securely to AWS S3 Using Presigned URLs

Uploading Files Securely to AWS S3 Using Presigned URLs

Subtitle: A practical guide to keeping your uploads safe by generating and using AWS presigned URLs in your web applications.

Uploading files directly to AWS S3 from a frontend app can be risky if not handled securely. Exposing your S3 credentials or allowing open write access is a big no-no. The best practice? Use presigned URLs — short-lived links that grant temporary access to upload a specific file.

In this tutorial, you'll learn how to securely generate and use presigned URLs for file uploads using Node.js and AWS SDK v3.

Step 1: Set Up Your AWS S3 Bucket

In the AWS Console:

  • Create an S3 bucket (or use an existing one).
  • Ensure it has private access by default.
  • Enable CORS (Cross-Origin Resource Sharing) to allow browser-based uploads. Example configuration:
{
  "CORSRules": [
    {
      "AllowedHeaders": ["*"],
      "AllowedMethods": ["PUT"],
      "AllowedOrigins": ["*"],
      "ExposeHeaders": []
    }
  ]
}

Step 2: Install the AWS SDK

npm install @aws-sdk/client-s3 @aws-sdk/s3-request-presigner

Step 3: Generate the Presigned URL in Your Backend

Create an endpoint that your frontend can call to get a temporary upload URL.

// server.js (Node.js/Express)

import express from 'express';
import { S3Client, PutObjectCommand } from '@aws-sdk/client-s3';
import { getSignedUrl } from '@aws-sdk/s3-request-presigner';

const app = express();
const s3 = new S3Client({ region: 'your-region' });

app.get('/generate-presigned-url', async (req, res) => {
  const { fileName, fileType } = req.query;

  const command = new PutObjectCommand({
    Bucket: 'your-bucket-name',
    Key: fileName,
    ContentType: fileType
  });

  const url = await getSignedUrl(s3, command, { expiresIn: 60 }); // 1 minute

  res.json({ url });
});

app.listen(3000, () => console.log('Server running on port 3000'));

Step 4: Upload the File in Your Frontend

// JavaScript (frontend)

async function uploadFile(file) {
  const res = await fetch(`/generate-presigned-url?fileName=${file.name}&fileType=${file.type}`);
  const { url } = await res.json();

  await fetch(url, {
    method: 'PUT',
    headers: {
      'Content-Type': file.type
    },
    body: file
  });

  alert('Upload complete!');
}

Conclusion

Presigned URLs are a secure and scalable solution for file uploads in modern web apps. By delegating the responsibility to AWS, you minimize backend load and eliminate security risks associated with direct uploads. Make sure to apply appropriate file type and size validations before generating URLs!