Why is my presigned URL for an Amazon S3 bucket expiring before the expiration time that I specified?

2 minute read
2

I created a presigned URL for an Amazon Simple Storage Service (Amazon S3) bucket using a temporary token. However, the URL expired before the expiration time that I specified. Why did this happen? How can I create a presigned URL that's valid for a longer time?

Resolution

If you created a presigned URL using a temporary token, then the URL expires when the token expires. The URL expires even if the URL was created with a later expiration time.

The credentials that you can use to create a presigned URL include:

  • AWS Identity and Access Management (IAM) instance profile: Valid up to six hours.
  • AWS Security Token Service (STS): Valid up to 36 hours when signed by an AWS Identity and Access Management (IAM) user, or valid up to one hour when signed by the root user.
  • IAM user: Valid up to seven days when using AWS Signature Version 4.

To create a presigned URL that's valid up to seven days, designate IAM user credentials (the access key and secret access key) to your SDK. Then, generate a presigned URL using AWS Signature Version 4. For examples, see Signature calculations in AWS Signature Version 4.

When creating a presigned URL, keep the following points in mind:

  • Services that assume a role, such as the AWS Lambda execution role, don't necessarily comply with the role's session duration settings.
  • Because presigned URLs grant Amazon S3 bucket access to whoever has the URL, it's a best practice to protect them appropriately.
  • If you created a presigned URL using a temporary token, then the URL expires when the token expires. This is true even if the URL was created with a later expiration time.

To allow users access to the objects in your Amazon S3 bucket for longer than seven days, consider using one of these options:


Related information

Sharing objects using presigned URLs

GetSessionToken

Retrieve security credentials from instance metadata

Authenticating requests: Using query parameters (AWS Signature Version 4)

Boto 3 Docs: S3

AWS OFFICIAL
AWS OFFICIALUpdated 2 years ago
2 Comments

I use the following approach (AWS sdk v3 Javascript) in my lambda function:

import { GetObjectCommand, S3Client } from "@aws-sdk/client-s3";
const client = new S3Client({ region });  // perhaps we can pass here credentials of IAM user
const command = new GetObjectCommand({ Bucket: bucket, Key: key });
const url = await getSignedUrl(client, command, { expiresIn: 4320000 }); // I expect that link will expire in 5 days

But the problem is the link expires in ~12-14hours. Here is the fragment of cloudformation template:

Resources:
  LambdaFunctionRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: "Allow"
            Action: "sts:AssumeRole"
    Path: "/"

  GetPresignedUrlFunction:
    Type: AWS::Serverless::Function
    Properties:
      FunctionName: !Sub "get-presigned-url-${EnvName}"
      Handler: getPresignedUrl.handler
      Role: !GetAtt LambdaFunctionRole.Arn

Should I use credentials of IAM user for S3Client constructor options like:

const client = new S3Client({ region, credentials: { accessKeyId: 'test', secretAccessKey: 'test' }});
replied 4 days ago

Thank you for your comment. We'll review and update the Knowledge Center article as needed.

profile pictureAWS
MODERATOR
replied 3 days ago