We are using AWS API Gateway with a custom domain. When we try https: it works fine. But we try http:
We CloudFront distribution, with configurations:
Origin Domain Name:
Minimum Origin SSL Protocol: TLSv1.2
Origin Protocol Policy: HTTPS
Viewer Protocol Policy: Redirect HTTP to HTTPS
Allowed HTTP Methods: GET, HEAD, OPTIONS, PUT, POST, PATCH, DELETE
With this, it redirects all the GET requests from HTTP to HTTPS.
But if we send a POST request to https://, cloudfront doesn't redirect and it just throws an error.
We need a way to redirect http: requests to https: for the API gateway
This behaviour of cloudfront is explained in this post redirect-http-requests-to-https-on-aws-api-gateway-using-custom-domains
quoting from the post
There is not a particularly good way to do this for APIs in general, because redirection of a POST request from HTTP to HTTPS is actually a little bit pointless -- the data have already been sent insecurely by the time the redirect is generated, unless the client has asked the server to inspect the request headers before the body is sent, with Expect: 100-continue.
You can create a CloudFront distribution, and configure it to redirect GET and HEAD requests from HTTP to HTTPS... but if you send a POST request to such distribution, CloudFront doesn't redirect -- it just throws an error, since (as noted) such redirection would be more harmful than helpful.
Related
An IoT device is sending data:
by POST method
by HTTP (not HTTPS)
and doesn't follow redirects
I created an end-point on AWS API GateWay and I created an AWS CloudFront and configured like this:
Origin Domain Name: myAPIgw.execute-api.us-west-1.amazonaws.com
Origin Protocol Policy: HTTPS Only
Viewer Protocol Policy: Redirected HTTP to HTTPS
Allowed HTTP Methods: GET, HEAD, OPTIONS, PUT, POST, PATCH, DELETE
Cache Policy: Managed-CachingDisabled
When I send request by Postman (auto follow redirect turned off) these are responses:
POST https://myAPIgw.execute-api.us-west-1.amazonaws.com --> 200 Success
POST https://Mycloudfront.cloudfront.net --> 200 Success
POST http://Mycloudfront.cloudfront.net --> 307 Temporary Redirect
Any idea to get 200 by HTTP ?
If you want to use HTTP, then you should set:
Viewer Protocol Policy: HTTP and HTTPS
and
Origin Protocol Policy: HTTPS Only
This way you can query the CloudFront endpoint either using HTTP or HTTPS, and no redirection is required from HTTP to HTTPS.
I use an Application Load Balancer in AWS as an API Gateway: for forwarding requests to different applications running in AWS. I have configured it with both support for HTTP and HTTPS. A HTTPS listener contains all logical rules for requests forwarding. And a HTTP listener is configured with a single rule: to redirect all traffic to the HTTPS listener ({host}:443/#{path}?#{query}) and to return 301.
HTTPS works perfectly. And HTTP works fine for GET requests. But I found that POST requests to HTTP are converted to GET requests when being redirected to HTTPS, which obviously ends up with 404.
I found online that the problem is in 301 status (https://rtfm.co.ua/en/http-redirects-post-and-get-requests-and-lost-data/#The_root_cause_3xx_redirects_and_HTTP_RFC). But unfortunately there is no option in AWS ALB rules to redirect requests and to return 307 instead of 301.
So does anyone know how I can fix this issue?
Thank you!
We have a similar setup. What we do is let the HTTP request pass through to the application server There the application detects the HTTP protocol and does a software-based 301 redirect as a POST to HTTPS. This moves the specialized protocol handling from the ALB to the application itself. Works great. Any application server would be easy to set up in this way.
I also faced the same issue when the http to https redirection is enabled. Just disable automatic https redirection and directly hit the https route.
Could not find any alternate solution other than this.
When we access backend api of ELB an https url, throws an error
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at https://abcde-1xx8x3xx3x.ap-south-1.elb.amazonaws.com/api/auth/testapi. (Reason: CORS request did not succeed).
Frontend:
We are using Cloudfront to deliver frontend from S3. The cloudfront URL link works and the page loads fine.
On cloudfront side in behaviour section,
whitelisted the headers [Accept, Access-Control-Allow-Origin, Access-Control-Request-Headers, Access-Control-Request-Method, Authorization, Content-Type, Referer, X-Access-Token, X-HTTP-Method-Override, X-Requested-With]
Viewer Prorocol Policy - Redirect HTTP to HTTPS
Allowed HTTP Methods - GET, HEAD, OPTIONS, PUT, POST.....
Backend:
Backend nodejs rest api is in EC2 and delivered via Classic Load Balancer internet facing. EC2 is within VPC. We are using ELB URL for API testing. The API works in Postman. Here, we have used Load balancer protocol as HTTPS and instance protocol as HTTP. There is a SSL certificate attached to this.
on the nodejs application, we are setting headers as below
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Request-Method', '*');
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');
res.header('Access-Control-Allow-Headers','Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With, Access-Control-Allow-Origin, Origin, X-HTTP-Method-Override, Accept, X-Access-Token');
res.setHeader('Access-Control-Allow-Credentials', 'true');
on the fontend code while using fetch api, we are setting mode: 'cors'
Tried looking in to other similar cors issues, but nothing helped.
Can anyone suggest me on how to solve this cors issue, what am i missing here? Or is there a better way to handle this for production?
This isn't actually a CORS error. It's a connectivity problem that happens to involve a CORS request.
Reason: CORS request did not succeed
The HTTP request which makes use of CORS failed because the HTTP connection failed at either the network or protocol level. The error is not directly related to CORS, but is a fundamental network error of some kind.
https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS/Errors/CORSDidNotSucceed
You have presumably modified the URL https://abcde-1xx8x3xx3x.ap-south-1.elb.amazonaws.com/api/auth/testapi somewhat, but note that it is impossible to use HTTPS on a URL ending with .elb.amazonaws.com. This is because it is impossible to get an SSL certificate for an amazonaws.com domain name -- that is Amazon's domain name, not your domain name. You can't get an SSL certificate for a domain you don't really control. You need your own domain, here, and an SSL certificate to match it, attached to the balancer.
You should find that by punching this API URL directly into the address bar of your browser, you also get an error. That error will not be a CORS error, and it is the actual error that you need to resolve.
Note also that your S3 and CloudFront settings are not involved in the error you have described.
I'm using AWS API Gateway with a custom domain. When I try to access https://www.mydomain.com it works perfectly, but when i try http://www.mydomain.com it can't connect.
Is there a way to redirect the http -> https with the custom domain in API Gateway? If not, is there a way to get the http:// links to work just like the https:// links?
API Gateway doesn't directly support http without TLS, presumably as a security feature, as well as for some practical considerations.
There is not a particularly good way to do this for APIs in general, because redirection of a POST request from HTTP to HTTPS is actually a little bit pointless -- the data is has already been sent insecurely by the time the redirect is generated, unless the client has asked the server to inspect the request headers before the body is sent, with Expect: 100-continue.
You can create a CloudFront distribution, and configure it to redirect GET and HEAD requests from HTTP to HTTPS... but if you send a POST request to such a distribution, CloudFront doesn't redirect -- it just throws an error, since (as noted) such a redirection would be more harmful than helpful.
However... if GET is your application, then it's pretty straightforward: first, deploy your API with a Regional (not Edge-Optimized) API endpoint with a system-assigned hostname, not a custom domain.
Then, create a CloudFront distribution that uses this regional API endpoint as its origin server, and configure the CloudFront distribution's behavior to redirect HTTP to HTTPS. Associate your custom domain name with the CloudFront distribution, rather than with API Gateway directly.
I have my website like this "https://hr.mywebsite.com", I am able to go to my website when i type the whole url(https://hr.mywebsite.com).
But I want to go to my website without typing "https://".
That is if i type "hr.mywebsite.com" it should open my website. My website is hosted on AWS CloudFront.
You need to set an HTTP to HTTPS redirect on your CloudFront distribution. CloudFront has a setting for this.
To configure CloudFront to require HTTPS between viewers and CloudFront
Sign in to the AWS Management Console and open the CloudFront console at https://console.aws.amazon.com/cloudfront/.
In the top pane of the CloudFront console, choose the ID for the distribution that you want to update.
On the Behaviors tab, choose the cache behavior that you want to update, and then choose Edit.
Specify one of the following values for Viewer Protocol Policy:
Redirect HTTP to HTTPS
Viewers can use both protocols. HTTP GET and HEAD requests are automatically redirected to HTTPS requests. CloudFront returns HTTP status code 301 (Moved Permanently) along with the new HTTPS URL. The viewer then resubmits the request to CloudFront using the HTTPS URL.
Important
CloudFront doesn't redirect DELETE, OPTIONS, PATCH, POST, or PUT requests from HTTP to HTTPS. If you configure a cache behavior to redirect to HTTPS, CloudFront responds to HTTP DELETE, OPTIONS, PATCH, POST, or PUT requests for that cache behavior with HTTP status code 403 (Forbidden).
When a viewer makes an HTTP request that is redirected to an HTTPS request, CloudFront charges for both requests. For the HTTP request, the charge is only for the request and for the headers that CloudFront returns to the viewer. For the HTTPS request, the charge is for the request, and for the headers and the object that are returned by your origin.
From http://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/using-https-viewers-to-cloudfront.html