Skip to content

CloudFront Signed URL returns 403 with content-disposition query parameterΒ #3614

@CodyDunlap

Description

@CodyDunlap

Describe the bug

Providing the response-content-disposition query parameter in a CloudFront Signed URL using the new cloudfront-signer package results in a 403 if the query parameter contains a filename option. For example, using the query parameter value 'attachment; filename=test.mp4;' results in a 403. However, if I simply use the value attachment; the download works fine, except that it doesn't change the download filename as intended.

Your environment

I have an API Gateway that is using a Lambda function to create the cloudfront url and sign it before returning to the browser. The url returned to the browser has been signed and contains the urlEncoded query parameter for response-content-disposition.

SDK version number

@aws-sdk/[email protected]

Is the issue in the browser/Node.js/ReactNative?

I'm not sure if this is a problem with the SDK in node or if it's a bug with Cloudfront. I've seen some reports with other libraries that may have the same issue, potentially indicating an issue with Cloudfront. In those reports it seems to be that specifically the query parameter doesn't work as expected. However, using a header may resolve the issue. But the cloudfront-signer library does not allow me to provide headers like this.

Details of the browser/Node.js/ReactNative version

Node v14.18.0

Steps to reproduce

Please share code or minimal repo, and steps to reproduce the behavior.

Using a CloudFront distribution with an S3 origin, the following JS is used to create the disposition query parameter and sign the url.

const disposition = `attachment; filename=test.mp4;`;

const url = new URL(s3Object.path, `https://${cloudfrontDomain}`);
url.searchParams.append("response-content-disposition", encodeURIComponent(disposition));

info.url = getSignedUrl({
  url: url.toString(),
  keyPairId: cloudFrontPublicKeyId,
  privateKey: cloudFrontPrivateKey,
  dateLessThan: new Date().setUTCMinutes(new Date().getUTCMinutes() + 5).toISOString()
});

Observed behavior

A clear and concise description of what happens.

I receive the following response:

<Error>
  <Code>AccessDenied</Code>
  <Message>Access denied</Message>
</Error>

Expected behavior

A clear and concise description of what you were expecting to happen.

I expect the request to begin a download of a file named test.mp4

Screenshots

If applicable, add screenshots to help explain your problem.

Additional context

Add any other context about the problem here.

Metadata

Metadata

Assignees

Labels

bugThis issue is a bug.closing-soonThis issue will automatically close in 4 days unless further comments are made.p3This is a minor priority issuewontfixWe have determined that we will not resolve the issue.workaround-availableThis issue has a work around available.

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions