amplify-js icon indicating copy to clipboard operation
amplify-js copied to clipboard

Accessing request cookies header in a AppSync NodeJS Lambda Resolver

Open isi-gach opened this issue 6 years ago • 16 comments

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.

isi-gach avatar Nov 29 '19 18:11 isi-gach

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

jkeys-ecg-nmsu avatar Dec 03 '19 01:12 jkeys-ecg-nmsu

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

isi-gach avatar Dec 04 '19 21:12 isi-gach

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

jkeys-ecg-nmsu avatar Dec 05 '19 01:12 jkeys-ecg-nmsu

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.

isi-gach avatar Dec 05 '19 13:12 isi-gach

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.

jkeys-ecg-nmsu avatar Dec 06 '19 04:12 jkeys-ecg-nmsu

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!

LMulvey avatar Dec 06 '19 19:12 LMulvey

@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.

jkeys-ecg-nmsu avatar Dec 06 '19 23:12 jkeys-ecg-nmsu

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.

LMulvey avatar Dec 06 '19 23:12 LMulvey

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.

tinnou avatar Dec 07 '19 02:12 tinnou

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

isi-gach avatar Dec 07 '19 13:12 isi-gach

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

tinnou avatar Dec 07 '19 19:12 tinnou

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

isi-gach avatar Dec 20 '19 18:12 isi-gach

Thank you for your feedback. :)

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

katzeforest avatar Dec 31 '19 21:12 katzeforest

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

davekiss avatar Feb 10 '20 18:02 davekiss

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.

bitfrost avatar Jul 29 '20 23:07 bitfrost

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...

tsi-davidkam avatar Jul 27 '22 08:07 tsi-davidkam

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

EyeDreamt avatar Aug 19 '22 14:08 EyeDreamt

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

AlessandroVol23 avatar Dec 10 '22 08:12 AlessandroVol23

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

copyhold avatar Oct 24 '23 12:10 copyhold

No news in 3 years?

misha-otto avatar Jan 29 '24 18:01 misha-otto