DEV Community

BERAT DİNÇKAN
BERAT DİNÇKAN

Posted on

1

The Solution to the Issue of Signed URL for an S3 Object Expiring Before the Desired Time

In my current project, my team was instructed to create a signed URL for an s3 object created programmatically so that they were able to download the s3 object without any AWS account.

Writing The Code

We created a lambda function. This lambda function used typescript and javascript aws sdk v3.

import { Context } from "aws-lambda";
import {
  GetObjectCommand,
  PutObjectCommand,
  S3Client,
  S3ClientConfig,
} from "@aws-sdk/client-s3";
import { getSignedUrl } from "@aws-sdk/s3-request-presigner";
export const lambdaHandler = async (event: object, context: Context) => {
  const maxExpireTime = 604800; //7 days maximum expire time
  const region = "us-west-2";
  const s3client = new S3Client({
    region,
  } as S3ClientConfig);
  const bucketName = "my-bucket-name";
  const key = "my-key";
  const body = "my-body";

  const putObjectCommand = new PutObjectCommand({
    Bucket: bucketName,
    Key: key,
    Body: body,
  });
  await s3client.send(putObjectCommand);

  const getObjectCommand = new GetObjectCommand({
    Bucket: bucketName,
    Key: key,
  });
  const signedURL = await getSignedUrl(s3client, getObjectCommand, {
    expiresIn: maxExpireTime,
  });
  return {
    statusCode: 200,
    body: {
      signedURL,
    },
  };
};
Enter fullscreen mode Exit fullscreen mode

According to this link, the max expiration time is 604800 seconds which means 7 days.

The Problem

So far so good. Lambda worked properly and gave us the signed URL but after 12 hours the signed URL for the s3 object expired and threw an error like below.
S3 signed url expired error

After investigating, we found out that if the token expires the signed URL expires.

The Solution

if you want a token that expires in 7 days which means more than 12 hours you need to use IAM user credentials with signature version 4.

We created IAM user access keys using the AWS console and implemented these keys with signature version 4 in our lambda function.

import { Context } from "aws-lambda";
import {
  GetObjectCommand,
  PutObjectCommand,
  S3Client,
  S3ClientConfig,
} from "@aws-sdk/client-s3";
import { getSignedUrl } from "@aws-sdk/s3-request-presigner";
export const lambdaHandler = async (event: object, context: Context) => {
  const maxExpireTime = 604800; //7 days maximum expire time
  const region = "us-west-2";

  const accessKeyId = "MY_ACCESS_KEY_ID";
  const secretAccessKey = "MY_SECRET_ACCESS_KEY";

  const s3client = new S3Client({
    region,
    credentials: {
      accessKeyId,
      secretAccessKey,
    },
    signatureVersion: "v4",
  } as S3ClientConfig);
  const bucketName = "my-bucket-name";
  const key = "my-key";
  const body = "my-body";

  const putObjectCommand = new PutObjectCommand({
    Bucket: bucketName,
    Key: key,
    Body: body,
  });
  await s3client.send(putObjectCommand);

  const getObjectCommand = new GetObjectCommand({
    Bucket: bucketName,
    Key: key,
  });
  const signedURL = await getSignedUrl(s3client, getObjectCommand, {
    expiresIn: maxExpireTime,
  });
  return {
    statusCode: 200,
    body: {
      signedURL,
    },
  };
};
Enter fullscreen mode Exit fullscreen mode

The Result

After using the IAM user access keys with signature version 4, the generated signed URL didn't expire after 12 hours as expected.

The Sources

Contact me:

AWS Q Developer image

Your AI Code Assistant

Generate and update README files, create data-flow diagrams, and keep your project fully documented. Built to handle large projects, Amazon Q Developer works alongside you from idea to production code.

Get started free in your IDE

Top comments (0)

Postmark Image

Speedy emails, satisfied customers

Are delayed transactional emails costing you user satisfaction? Postmark delivers your emails almost instantly, keeping your customers happy and connected.

Sign up

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay