AWS CloudFront with Signed URL: 403 Access Denied

In my case the problem was with URL I was passing to URL signing code (I was using AWS SDK for Node.js).

cloudFront.getSignedUrl({
  url: `${distributionUrl}/${encodeURI(key)}`,
  expires: Math.floor(new Date().getTime() / 1000) + 60 * 60
})

Note encodeURI. I was not doing that. The resulting signed URL would still have URI components encoded, BUT would have invalid signature, thus causing 403 error.

EDIT: ...And you have to wrap it into url.format() like this:

cloudFront.getSignedUrl({
  url: url.format(`${distributionUrl}/${encodeURI(key)}`),
  expires: Math.floor(new Date().getTime() / 1000) + 60 * 60
})

I guess they should be doing that in SDK.


I received the same Access Denied error and spent the last couple hours trying to figure out what was going on. I finally realized that the Expires parameter was set in the past since I was using my local time instead of UTC. Make sure to set the Expires in the future according to UTC.