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
질문됨 2년 전1599회 조회
2개 답변
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
전문가
답변함 2년 전
  • 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
답변함 2년 전
profile picture
전문가
검토됨 일 년 전

로그인하지 않았습니다. 로그인해야 답변을 게시할 수 있습니다.

좋은 답변은 질문에 명확하게 답하고 건설적인 피드백을 제공하며 질문자의 전문적인 성장을 장려합니다.

질문 답변하기에 대한 가이드라인

관련 콘텐츠