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
posta 2 anni fa1599 visualizzazioni
2 Risposte
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
ESPERTO
con risposta 2 anni fa
  • 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
con risposta 2 anni fa
profile picture
ESPERTO
verificato un anno fa

Accesso non effettuato. Accedi per postare una risposta.

Una buona risposta soddisfa chiaramente la domanda, fornisce un feedback costruttivo e incoraggia la crescita professionale del richiedente.

Linee guida per rispondere alle domande