Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rename headers #477

Closed
tmokmss opened this issue Jul 13, 2024 · 8 comments
Closed

Rename headers #477

tmokmss opened this issue Jul 13, 2024 · 8 comments

Comments

@tmokmss
Copy link
Contributor

tmokmss commented Jul 13, 2024

Feature request: Add option to let LWA to replace HTTP header names before proxying the request to the server.

Use case: When we use Lambda function URL with CloudFront, we often use AWS_IAM auth type for security, and sign each request in Lambda@Edge (ref). This is still a viable option because OAC does not suppot PUT or POST requests (doc). When we sign a request with sigv4, Authorization header is used to pass a signature, which overrides the original Authorization header even if the backend requires it for authentication. This results in the backend not working as expected when used with Lambda fURL.

So this issue proposes LWA to allow to rename headers before proxying the request. Lambda@Edge copies the original Authorization header to other name, and LWA move it back after Lambda function URL used the sigV4 Authorizaton header.

See the below diagram.

Current:
image

If LWA supports renaming headers:
image

I also tried passing the signature via querystring, but that was not ideal, because the backend apps are often so "aware" of querystrings that they behave unexpectedly. (e.g. Next.js router adds all the querystrings to the response header as Next-Router-State-Tree, which exposes all the sigv4 data to the client.)

@bnusunny
Copy link
Contributor

bnusunny commented Jul 13, 2024

Good suggestion! We could configure this behaviour with an env var AWS_LWA_AUTHERIZATION_SOURCE, default to None. When this env var is configured, LWA will take the value from that header to overwrite the Authorization header.

@gsleite
Copy link

gsleite commented Jul 13, 2024

You can execute POST using OAC. Create a SHA-256 hash digest and put it in "x-amz-content-sha256" header.

This is an example of a javascript logic to create the hash:

const hashPayload = async (payload) => {
const encoder = new TextEncoder().encode(payload);
const hash = await crypto.subtle.digest('SHA-256', encoder);
const hashArray = Array.from(new Uint8Array(hash));
return hashArray
.map((bytes) => bytes.toString(16).padStart(2, '0'))
.join('');

}

header["x-amz-content-sha256"] = await hashPayload(payload);

The OAC will use the Authorizer header to send the signed request to lambda, you do not need to create any other logic for sigv4 request. If you would like to inject another token in your application, you can do it in lambda@edge authorizer:

const payload = await verifier.verify(headers["x-access-token"][0].value);
console.log("Token is valid. Payload:", payload);
//Add decoded access token to header
request.headers["x-access-token"][0].value = JSON.stringify(payload);
callback(null, request)

You can find the complete solution in this sample:

https://github.com/aws-samples/serverless-genai-assistant/tree/main/examples/sample_web_application

@tmokmss
Copy link
Contributor Author

tmokmss commented Jul 13, 2024

Thanks @gsleite. So the OAC still overwrites Authorization header and hence the original problem persists (correct me if I misunderstand something!). It is sometimes difficult for a backend app to use a header name other than Authorization.

OAC provides no-override option but it seems it just not work when the browser provides application-specific Authorization header (not sigv4).

Don't override the viewer (client) Authorization header
This setting is named Do not override authorization header in the console, or no-override in the API, CLI, and AWS CloudFormation. Use this setting when you want CloudFront to sign origin requests only when the corresponding viewer request does not include an Authorization header. With this setting, CloudFront passes on the Authorization header from the viewer request when one is present, but signs the origin request (adding its own Authorization header) when the viewer request doesn't include an Authorization header.
https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/private-content-restricting-access-to-lambda.html

But I guess we should use OAC to simplify L@E code. I'll rewrite my current code, thanks.

@bnusunny Thanks! I think your suggestion will work for my use case. One thing to consider is whether we should generalize the solution (e.g. pass a map of old/new header names), or limit this feature only for Authorization header (as you suggested).

@gsleite
Copy link

gsleite commented Jul 13, 2024

@tmokmss, yes, your original problem will persist. If you try to override the Authorization header the Lambda will return 403 as you mentioned.

What i do in my use case is add a custom header ["x-access-token"], (avoiding querystring), and use the lambda@edge to validate the token. If the token is valid i pass it decoded to the backend using the same custom header, this is the same behaviour of Authorization header in API GW with Lambda Proxy.

This solution may save you some time.

@tmokmss
Copy link
Contributor Author

tmokmss commented Jul 13, 2024

I see. So you are using L@E as a Lambda authorizer. In my usecase, though, the user related data is in Aurora, and only the backend can consume Authorization header, which is often the case with a fullstack webapp framework like Next.js.

@bnusunny
Copy link
Contributor

bnusunny commented Jul 14, 2024

@tmokmss I want to keep LWA features at minumum. Let's do this specific thing for Authorization header. If people need to add/remove headers in a flexible way, they always could include Nginx in the package.

@tmokmss
Copy link
Contributor Author

tmokmss commented Jul 15, 2024

@bnusunny That makes sense. I'll submit a PR if you are not working on this :)

@bnusunny
Copy link
Contributor

Go ahead! Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants