Why isn't my lambda function URL returning CORS headers for my preflight requests?

0

I am playing around with lambda function URLs, which seem like a perfect fit for my use case.

I have a lambda configured with function URL turned on, Auth type of AWS_IAM, and CORS turned on with default settings (Allow Origin *, nothing else set). From Javascript running in Chrome I am sending a signed request to the lambda with code that looks like:

  const url = new URL(rawUrl)

  const signer = new SignatureV4({
    credentials: *******,
    sha256: Sha256,
    service: "lambda",
    region: region,
  })

  const request = new HttpRequest({
    hostname: url.hostname,
    path: url.pathname,
    body: JSON.stringify({}),
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      host: url.hostname,
    }
  })

  const send = async () => {
    const {headers, body, method} = await signer.sign(request)
    console.log('send.headers', headers)
    const result = await fetch(rawUrl, { headers, body, method })
      .then((res) => res.json())
    return result
  }

  send()
    .then((data) => {
      console.log('success', data)
    })
    .catch((reason) => {
      console.log('error', reason)
    })

When this code runs it generates a request that fails CORS because the preflight is not validated. The curl equivalents of the requests Chrome is sending are

curl 'https://**********.lambda-url.us-west-2.on.aws/' \
  -H 'sec-ch-ua: "Google Chrome";v="105", "Not)A;Brand";v="8", "Chromium";v="105"' \
  -H 'sec-ch-ua-mobile: ?0' \
  -H 'authorization: AWS4-HMAC-SHA256 Credential=*******/*******/us-west-2/lambda/aws4_request, SignedHeaders=content-type;host;x-amz-content-sha256;x-amz-date;x-amz-security-token, Signature=***********' \
  -H 'Content-Type: application/json' \
  -H 'x-amz-content-sha256: ************' \
  -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Safari/537.36' \
  -H 'x-amz-security-token: ********' \
  -H 'Referer: http://localhost:3000/' \
  -H 'x-amz-date: 20220916T035331Z' \
  -H 'sec-ch-ua-platform: "macOS"' \
  --data-raw '{}' \
  --compressed

for the request and

curl 'https://*******.lambda-url.us-west-2.on.aws/' \
  -X 'OPTIONS' \
  -H 'Accept: */*' \
  -H 'Accept-Language: en-US,en;q=0.9' \
  -H 'Access-Control-Request-Headers: authorization,content-type,x-amz-content-sha256,x-amz-date,x-amz-security-token' \
  -H 'Access-Control-Request-Method: POST' \
  -H 'Connection: keep-alive' \
  -H 'Origin: http://localhost:3000' \
  -H 'Referer: http://localhost:3000/' \
  -H 'Sec-Fetch-Dest: empty' \
  -H 'Sec-Fetch-Mode: cors' \
  -H 'Sec-Fetch-Site: cross-site' \
  -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Safari/537.36' \
  -H 'dnt: 1' \
  -H 'sec-gpc: 1' \
  --compressed

for the preflight.

If I run that preflight in a terminal I get the following response:

HTTP/1.1 200 OK
Date: Fri, 16 Sep 2022 03:41:24 GMT
Content-Type: application/json
Content-Length: 0
Connection: keep-alive
x-amzn-RequestId: 80fc5a73-6f60-4315-b0bf-f3a63c7e6050

Note that there aren't valid CORS headers being sent back, which results in Chrome not making the actual request. If I run the request itself in a terminal and bypass the preflight, then it runs successfully.

Is there an error in the way that I am making a request or how I've configured the lambda (I've tried various combinations)?

Thanks for your help!

profile picture
asked 2 years ago1582 views
2 Answers
0

I've just done some testing on my own Lambda function.

The CORS headers are returned if the Origin in the request exactly matches the CORS Allow Origin parameter in your Lambda function; or if there is a wildcard in that parameter.

In this case, you might configure * as the Allow Origin for testing.

profile pictureAWS
EXPERT
answered 2 years ago
  • Thanks @Brettski-AWS. I think I mentioned it above, I do have Allow Origin set to "*" in the lambda config. To test things out I tried the same preflight request via curl with Allow Origin set to "http://localhost:3000" and to "http://remotehost:3000" to check for an exact match and an explicit mismatch. In all cases I got the exact same response back:

    HTTP/1.1 200 OK Date: Fri, 16 Sep 2022 xx:xx:xx GMT Content-Type: application/json Content-Length: 0 Connection: keep-alive x-amzn-RequestId: xxxxxxxxxx

    Any other ideas?

  • I tested mine with Allow Origin set to "*" but I used a "real" (non-localhost) address and I got a CORS response back.

0

After a lot of trying different setting, I did manage to get everything working.

All the CORS configuration values default to being locked down. During testing to try and open everything up, I had tried * for all the values, but did not set the Max age configuration value (which defaults to blank). A blank max age by the spec should be equivalent to a 0 value, but that doesn't seem to be the case.

With all setting properly filled out to the origins, methods, and headers that I am using AND Max age set to 0 everything started behaving itself.

profile picture
answered 2 years ago
profile picture
EXPERT
reviewed 10 months ago

You are not logged in. Log in to post an answer.

A good answer clearly answers the question and provides constructive feedback and encourages professional growth in the question asker.

Guidelines for Answering Questions