aws-amplify / amplify-js

A declarative JavaScript library for application development using cloud services.
https://docs.amplify.aws/lib/q/platform/js
Apache License 2.0
9.42k stars 2.13k forks source link

Accessing request cookies header in a AppSync NodeJS Lambda Resolver #4486

Open isi-gach opened 4 years ago

isi-gach commented 4 years ago

How can I get the request cookies in an AppSync Javascript Lambda Resolver? It seems that it could be done using a Request Body Mapping Template https://faragta.com/aws-api-gateway/pass-cookie-values-from-api-gateway.html With this VTL call $util.escapeJavaScript($input.params().header.Cookie) but I don't know what's the equivalent for Amplify/AppSync

Ideally using configuration files instead of the AWS Console UI.

The use case is reading a request cookie with the HttpOnly flag (so it's not accessible in the browser), apply sha256 to that cookie and make a new Http request.

jkeys-ecg-nmsu commented 4 years ago

Have you tried logging the event to the lambda and checking CloudWatch to see the structure of the input? @isi-gach

isi-gach commented 4 years ago

hi @jkeys-ecg-nmsu With this lambda function:

exports.handler = function (event, context) {
  console.log(`JSON.stringify(event) = ${JSON.stringify(event)}`);
  context.done(null, 'Hello World');
};

and this in Before mapping template:

## [Start] Stash resolver specific context.. **
$util.qr($ctx.stash.put("typeName", "Query"))
$util.qr($ctx.stash.put("fieldName", "getRRBanners"))
{ "test": "$input.params().header.Cookie" }
## [End] Stash resolver specific context.. **

the request:

Screenshot 2019-12-04 at 21 15 45

This is what I see on CloudWatch:

Screenshot 2019-12-04 at 21 00 22

The Cookie entry is missing in the headers object and using $input doesn't seems to work

jkeys-ecg-nmsu commented 4 years ago

This seems like a problem with AppSync's implementation of Lambda resolvers. Have you tried sending your cookie under a different header?

isi-gach commented 4 years ago

hi @jkeys-ecg-nmsu Other headers are visible, for instance, you can see my custom header "x-isi": "foo" in the screenshot above. But the cookie that I need has the HttpOnly flag, so I cannot read it in the browser to send it as a custom header.

jkeys-ecg-nmsu commented 4 years ago

I would contact the AppSync service team if possible.

The fact that basic support plan accounts can't submit bug reports to service teams is unfortunate.

LMulvey commented 4 years ago

Hey there! I'm seeing that you're using the mapping template directly from the API Gateway tutorial, however, AppSync's mapping templates work a little differently.

If you use this as your request VTL template on your resolver:

{
    "version": "2018-05-29",
    "operation": "Invoke",
    "payload": {
        "request": $util.toJson($context.request)
    }
}

You'll be able to access the cookie inside the event parameter inside the Lambda:

exports.handler = function (event, context) {
  console.log({ request: event.request }); // request.cookie will have the cookies delimited by semi-colons
  context.done(null, 'Hello World');
};

Hope that helps!

jkeys-ecg-nmsu commented 4 years ago

@LMulvey sorry about not noticing that before telling OP to contact you.

On the other hand, that was very insightful and I would like to put in my vote for more samples like that in the AppSync documentation. Common resolver use cases and detailed examples on composing complex resolvers would go a long way towards eliminating these kind of questions on the Amplify issues pages.

LMulvey commented 4 years ago

Don't apologize to me, heh–I'm not part of the AppSync team. Just someone who's been working on it the last few months and has spent a lot of time in the docs.

I agree that there should definitely be more use case examples in the docs. This was pulled from here and tested locally: https://docs.aws.amazon.com/appsync/latest/devguide/resolver-context-reference.html but it actually makes no mention of cookies–I had to validate that myself.

tinnou commented 4 years ago

You're right, AppSync currently does not expose Cookies via the $ctx.request object. It is good feedback and I will take this to the team. In the meantime, would you be able to extract the cookie header on the client and use a different header to pass it through AppSync?

I'm also taking a note on updating the documentation to reflect that Cookies are not available.

isi-gach commented 4 years ago

hi @tinnou The cookie has the HttpOnly flag so it's not accessible on the client. This is a big blocker for us to use AppSync. Is there any other workaround or the only alternative is to use API Gateway instead of GraphQL?

Screenshot 2019-12-07 at 13 30 07
tinnou commented 4 years ago

@isi-gach, in that case there is no workaround to date.

isi-gach commented 4 years ago

hi @tinnou Are there any plans to fix this issue?

katzeforest commented 4 years ago

Thank you for your feedback. :)

I will +1 on your behalf of this request to the AWS AppSync team.

davekiss commented 4 years ago

Also running into this on my end, seems like it'd be an easy implementation for the AppSync team no?

bitfrost commented 4 years ago

Please consider adding support for this directly in $cts.request we have use cases around httpOnly cookies will not work by playing the header switching game in the client via javascript. Adding something like cloudfront + edge lambdas just for this is ...terrible.

tsi-davidkam commented 2 years ago

Any updates on this? Not having access to the cookie basically makes it impossible to implement anti side-jacking of JWT - https://cheatsheetseries.owasp.org/cheatsheets/JSON_Web_Token_for_Java_Cheat_Sheet.html#token-sidejacking

Might have to switch back to running apollo on EC2 or AppRunner...

EyeDreamt commented 2 years ago

Seems this is still an issue. Pretty pathetic really and it's not mentioned anywhere.

AlessandroVol23 commented 1 year ago

+1 on that. This is blocking us from moving to AppSync completely unfortunately 🙁

copyhold commented 12 months ago

Please consider adding support for this directly in $cts.request we have use cases around httpOnly cookies will not work by playing the header switching game in the client via javascript. Adding something like cloudfront + edge lambdas just for this is ...terrible.

Hello

I tried to do this either - put a cloudfront + lambda in front of appsync, but it does not work with websocket ( for rest like http requests it does , but not for subscription ).

Did you try this also? Was it successful?

thanks in advance regards, Ilya

misha-otto commented 8 months ago

No news in 3 years?