Cloudfront Malformed Policy Error with AWS Cloudfront-Signer V3

1

I'm having an issue with the AWS Cookie-Signer V3 and Custom Policies. I'm currently using @aws-sdk/cloudfront-signer v3.254.0. I have followed the official docs of how to create and handle signed cookies - it works as long as I don't use custom policies.

Setup

I use a custom lambda via an API Gateway to obtain the Set-Cookie header with my signed cookies. These cookies will be attached to a further file-request via my AWS Cloudfront instance. In order to avoid CORS errors, I have set up custom domains for the API Gateway as well as for the Cloudfront instance.

A minified example of the signing and the return value looks as follows:

// Expiration time
const getExpTime = new Date(Date.now() + 5 * (60 * 60 * 1000)).toISOString();

// Cookie-Signer
const signedCookie = getSignedCookies({
  keyPairId: "MY-KEYPAIR-ID",
  privateKey: "MY-PRIVATE-KEY",
  url: "https://cloudfront.example.com/path-to-file/file.m3u8",
  dateLessThan: getExpTime,
});

// Response
const response = {
  statusCode: 200,
  isBase64Encoded: false,
  body: JSON.stringify({ url: url, bucket: bucket, key: key }),
  headers: {
    "Content-Type": "application/json",
    "Access-Control-Allow-Origin": "https://example.com",
    "Access-Control-Allow-Credentials": true,
    "Access-Control-Allow-Methods": "OPTIONS,POST,GET",
  },
  multiValueHeaders: {
    "Set-Cookie": [
      `CloudFront-Expires=${signedCookie["CloudFront-Expires"]}; Domain=example.com; Path=/${path}/`,
      `CloudFront-Signature=${signedCookie["CloudFront-Signature"]}; Domain=example.com; Path=/${path}/`,
      `CloudFront-Key-Pair-Id=${signedCookie["CloudFront-Key-Pair-Id"]}; Domain=example.com; Path=/${path}/`,
    ],
  },
};

This works well if I request a single file from my S3 bucket. However, since I want to stream video files from my S3 via Cloudfront and according to the AWS docs, wildcard characters are only allowed with Custom Policies. I need this wildcard to give access to the entire video folder with my video chunks. Again following the official docs, I have updated my lambda with:

// Expiration time
const getExpTime = new Date(Date.now() + 5 * (60 * 60 * 1000)).getTime();

// Custom Policy
const policyString = JSON.stringify({
  Statement: [
    {
      Resource: "https://cloudfront.example.com/path-to-file/*",
      Condition: {
        DateLessThan: { "AWS:EpochTime": getExpTime },
      },
    },
  ],
});

// Cookie signing
const signedCookie = getSignedCookies({
  keyPairId: "MY-KEYPAIR-ID",
  privateKey: "MY-PRIVATE-KEY",
  policy: policyString,
  url: "https://cloudfront.example.com/path-to-file/*",
});

which results in a Malformed Policy error.

What confuses me is that the getSignedCookies() method requires the url property even though I'm using a custom policy with the Ressource parameter. Since the Resource parameter is optional, I've also tried without which led to the same error.

To rule out that something is wrong with the wildcard character, I've also run a test where I've pointed to the exact file but using the custom policy. Although this works without custom policy, it does fail with the Malformed Policy error when using the custom policy.

Since there is also no example of how to use the Cloudfront Cookie-Signer V3 with custom policies, I'd be very grateful if someone can tell me how I'm supposed to type this out!

Cheers! 🙌

3 個答案
0
已接受的答案

I found the solution and it's pretty embarrassing...

My above example signs cookies via a Custom Policy but uses the Set-Cookie header keys from a Canned Policy. The difference in the docs is not really obvious but its clearly there...

However, instead of

Set-Cookie: CloudFront-Expires= ...

you use

Set-Cookie: CloudFront-Policy=<your policy string>

The keys

Set-Cookie: CloudFront-Expires= ...
Set-Cookie: CloudFront-Signature= ...

are identical.

Hope this helps!

FloRag
已回答 8 個月前
0

Try changing the "DateLessThan" line to:

DateLessThan: { "AWS:EpochTime": Math.floor(getExpTime / 1000) },

AWS:EpochTime expects a value in seconds, not milliseconds.

已回答 1 年前
0

Did you find any solution to this ? I am facing the same issue.

已回答 1 年前

您尚未登入。 登入 去張貼答案。

一個好的回答可以清楚地回答問題並提供建設性的意見回饋,同時有助於提問者的專業成長。

回答問題指南