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: Xxx, xx Xxx 2022 xx:xx:xx GMT
Content-Type: application/json
Content-Length: 0
Connection: keep-alive
x-amzn-RequestId: xxxxxxxxx
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!
CodePudding user response:
Not sure whether you were trying to edit an existing lambda, but I have observed, creating a new lambda function URL from scratch returns the expected headers in the OPTIONS response vs editing an existing one.
I am not certain what could be the reason for this behavior, but you may want to try creating a function URL from scratch, if you didn't do it already.
CodePudding user response:
Thanks to the comment from @jub0bs above I figured out the answer.
All the CORS configuration values default to being locked down. I had tried *
for all the values, but did not set the Max age configuration value. 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.