5

Is it possible to use IAM Roles Authentication to an API Gateway endpoint via Cloudfront?

Here is a basic use case:

  • /api -> API Gateway
  • /* -> S3 HTML/Javascript

I've been able to get this working without Authentication similar to the following setup: https://www.codeengine.com/articles/process-form-aws-api-gateway-lambda/

How do you add CloudFront in front of API Gateway

Of particular note is to NOT forward the HOST header from Cloudfront...

When I enable IAM Authentication in the API, I receive the following response:

OPTIONS: 200

POST: 403

{"message":"The request signature we calculated does not match the signature you provided. Check your AWS Secret Access Key and signing method. Consult the service documentation for details.\n\nThe Canonical String for this request should have been\n'POST\n/test/create\n\naccept:application/json\ncontent-type:application/json\nhost:*****.execute-api.ap-****-2.amazonaws.com\nx-amz-date:20170328T044253Z\n\naccept;content-type;host;x-amz-date\na57656a9def890d9de2b637789f7e5917f4b2823765ae0122087d08f89a97380'\n\nThe String-to-Sign should have been\n'AWS4-HMAC-SHA256\n20170328T044253Z\n20170328/ap-southeast-2/execute-api/aws4_request\ncae7fd6b4cabd593ad2ec6ce7091c94dc8cba306e81da95d567873eea8f981a5'\n"}

The host in the Canonical String is that of the API Gateway...

Community
  • 1
  • 1
atlas_scoffed
  • 3,542
  • 30
  • 46
  • 1
    You'll need to sign the request as if you were going to send it directly to API Gateway... then change the hostname in the request after signing. It's counter-intuitive, perhaps, but since CloudFront is going to change it back, again, this seems like the only solution. – Michael - sqlbot Mar 28 '17 at 13:00
  • Possible duplicate of [Does API Gateway behind CloudFront not support AWS\_IAM authentication?](https://stackoverflow.com/questions/48815143/does-api-gateway-behind-cloudfront-not-support-aws-iam-authentication) – Reed Hermes Jan 22 '19 at 16:23
  • @HungryTuna That question was asked Feb 15 '18... Can you please elaborate? – atlas_scoffed Jan 22 '19 at 23:08

2 Answers2

3

As noted in comments, you'll run into difficulties due to the change of the HOST header. In theory signing the request with the API Gateway exceute-api domain as the value of HOST in theory should work, assuming CloudFront is not changing the payload in any other way.

Bob Kinney
  • 8,870
  • 1
  • 27
  • 35
  • 1
    Thanks Bob, I can confirm that by manually setting the Host header to that of the API gateway endpoint, prior to signing, sig4 authentication works via Cloudfront. – atlas_scoffed Mar 28 '17 at 20:00
  • 1
    CloudFront generates it's own x-amz-date request header and headers that begin with X-Amz- cannot be forwarded to your origin so although the Host header can be changed for signing, the request will fail if the client request is not within the same second as the origin request as the value for the x-amz-date request header will not match the header's value at the time of signing the request. The 'date' header will not work as an alternative to 'x-amz-date' as the sigV4 process only checks for a 'date' header if there is no 'x-amz-date' provided. – Kenneth Rory Dunn Jul 05 '18 at 07:27
  • @KennethRoryDunn Unless you forward all headers (using "*" in CloudFormation / serverless .yml _Headers_ _ForwardValues_). But in this case you lose caching. – ElFitz Oct 29 '18 at 16:45
  • @ElFitz, Headers that begin with X-Amz-* are part of the list of headers CloudFront cannot forward to the origin. https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/forward-custom-headers.html#forward-custom-headers-blacklist – Kenneth Rory Dunn Nov 20 '18 at 06:30
  • 1
    @KennethRoryDunn Maybe that's what the documentation says. But setting to forwarding all headers, using \*, I could nonetheless authenticate via Cognito Federated Identities with an API Gateway behind Cloudfront. Cloudfront caching wouldn't work anymore, because it used the headers, one of which is a timestamp, and another a signature based on that timestamp, as caching keys, but the forwarding did work. You can't specifically forward X-Amz-* headers, but forwarding all headers will get those forwarded as well. – ElFitz Nov 22 '18 at 16:51
0

This is a difficult one to debug, I wrote a blog here going into more detail on the solution, hope it helps someone else. Thanks @Bob for putting me on the right track: https://www.rehanvdm.com/serverless/cloudfront-reverse-proxy-api-gateway-to-prevent-cors/index.html

DR.
  • 573
  • 6
  • 20