How to use Cloudfront with basic auth? - ruby-on-rails

I am implementing a cloudfront solution and would like to test / run it on my staging server, however staging is "protected" from the outside world by basic_auth.
I have tried entering a URL with the basic_auth username / password in it e.g user:pass#example-staging.com but CloudFront rejects this URL.
How can I allow Cloudfront / an origin to access my staging server?
(I am hosting on heroku, using rails 4)

Because of the way web content caching works, most HTTP request headers are not forwarded from CloudFront to the origin server by default, including the Authorization header needed for basic auth.
You'll need to whitelist the Authorization header in the appropriate cache behavior(s).
http://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/distribution-web-values-specify.html#DownloadDistValuesWhitelistHeaders

Related

AWS Cloudfront drops custom domain name and redirects to Elastic Beanstalk

I have an elastic beanstalk environment with CloudFront serving SSL (ASP.Net MVC). CloudFront has a custom domain name. Everything works fine until the user's session cookie expires or the user tries to access a secured area without logging in and is redirected to the login page. When either of these two things happens, the user is somehow redirected to the actual elastic beanstalk environment and it also drops SSL, so if the user doesn't notice they'll be sending their login credentials without SSL. For example, if the user accesses https://custom.domain.com/admin without being logged in they get redirected to http://aws.elasticbeanstalkcontainer.com, same for session expiration. It worked fine on IIS10 before migrating to AWS. It seems that when EC2 sends the redirect back somehow CloudFront is missing it and not changing it to the custom domain name. Any help will be greatly appreciated. Thanks in advance.
It is not CloudFront's job to monitor for redirect responses coming from your server and rewrite them with a different domain name. That's not something it does. You have to configure your application running on Elastic Beanstalk to be aware of the correct domain name it should use when it sends redirect responses back to the client.

ASPNET MVC 5: Anti-forgery cookie not present

I've got an app that uses antiforgerytoken to secure all forms. the app is hosted on a web site that has the http binding set to the 8080 abd the https set to the 443 (default https port). Until now, I made sure that all the requests were made through https (The MVC app was using the required https filter, web config had the cookies entry requiressl set to true and owin had the auth cookies also set to https).
Recently, we had to change things because now we've got a firewall which handles the https requests for us. it will always serve the response through https to the final client, but I had change my app so that it could be called through http.
I've removed the required https filter, the required ssl for the cookies from the config and changed the owin auth cookies settings, and thought everything would be ok. Unfortunately, that didn't happen and I've started getting the anti forgery token cookie missing exception during validation. Now, the thing is that everything works out if I use https, but it will break if i change to http (which is in port 8080).
I've ended up changing the anti forgery configuration settings from within the global asax, but I'm not able to find a good explanation for the previous problem. in other words, why does the https access work without any problems but the http access ends up throwing an exception saying it can't find the anti forgery cookie...
any ideas?
Thanks,
Luís
More likely than not, you're using secure cookies (cookies sent with the Secure tag). These will only ever survive on HTTPS connections. As soon as SSL is dropped, so are any secure cookies. You could turn it off, but that actually opens up an attack vector on your users, allowing their cookies to be exposed in plain text through protocol-switching.
The best thing you could do is keep it secure all the way. Just because SSL is being provided by the firewall, doesn't mean you can't implement SSL on your site as well. The only difference is that you would need a self-signed cert, since obviously the external domain will not apply. Other than that there should be no problem proxying to a secure site internally, rather than an unsecure one.

Rails S3 - CloudFront 401 error triggers Basic Auth popup

I have a Rails app with carrierwave uploaders configured to use carrierwave-aws on an S3 bucket.
The permissions for that bucket WERE bad, but hopefully I fixed them and now uploads seem to work fine (and I checked the permissions of a single file, public read is checked)
The Rails app is using cloudfront, which has been configured to handle "normal" assets (css, js, etc.) and with carrierwave-aws.
However I am still getting 401 errors, and worse, when this happens a HTTP Basic auth popu appears on screen, asking for a password for my distribution
"NetworkError: 401 Unauthorized - https://xxxxxxx.cloudfront.net/uploads/user/avatar/xxxxxx/thumb_avatar.jpg"
The above error triggers an HTTP Basic auth windows asking for the user/pw for xxx.cloudfront.net
If this is linked, it turns out I indeed do have this kind of auth on my Rails website itself (before we move on to production).
On CloudFront, I have configured two origins : my Rails server (and css/js are ok so I guess this ons is fine) and The S3 Bucket (don't know how I can really test this one though)
So
How can I check My Rails -> Carrierwave-aws -> CloudFront pipeline is working fine ? (Uploads are fine, I just can't read from the browser after an upload)
How can I disable HTTP Basic Auth from the website in case a 401 error appears ?
EDIT : I setup Basic Auth in Rails ApplicationController
def authenticate
if ENV["HTTP_BASIC_AUTH"] == "true"
authenticate_or_request_with_http_basic do |username, password|
username == "wxx" && password == "xxx!" or
end
end
end
A 401 HTTP response is, of course, supposed to trigger a browser pop-up prompt. If you don't want that, your solution is not to require auth in your application.
But, it seems like the solution that would be most helpful to you at this point would be to go ahead and enable pass-through of the browser's attempt to send credentials back to the origin server. To do this, CloudFront needs to forward the Authorization: header to your origin. By default, this request header (like most request headers) us discarded by CloudFront and not sent to the origin.
Whitelist this header in the appropriate cache behavior so that CloudFront will forward it and your access control mechanism should work as expected.
Remember that changes to CloudFront distributions take a few minutes. Wait for the distribution to return to the deployed status before testing.

How to force Spring Security to make https redirect requests when behind a load balancer

We are currently using AWS ELB -> Apache in front of our Tomcat instance running Grails. We use Apache to redirect http requests to https requests. This works fine for us on our regular site. The issue arrives when trying to embed our site within an iframe on Chrome. Chrome does not like an https site redirecting to an http page (even if that page subsequently redirects to https). The reason this happens is that to Spring Security it looks like we're on http because we're behind a load balancer. Here is the network ping pong from Developer Tools:
Here is the problem when putting that same page within an iframe on Chrome.
We have found many solutions that will allow the Spring Security Grails plugin to redirect http requests to https request for certain URL patterns. Here and here are two of these examples. We have already solved this issue by having Apache intercepting http requests and redirecting to https.
The issue is that Chrome won't even make the http request within the iframe. We need an ability to tell Spring Security that even though the saved request you receive is using http, we need you to change that to https once you complete the authentication.
One solution we thought may work was changing to a relative URL using contextRelative instead of the absolute URL, which Spring Security views as http because of the ELB proxy. This post seemed to suggest the same, but the solution also did not change the URL generated when changing contextRelative to "true".
How can we tell the Grails Spring Security plugin to always either format the URLs as relative or force them to an https scheme so that we can run the application within an iframe in Chrome?
If you want to modify the SavedRequest then you can implement your own SavedRequestAwareAuthenticationSuccessHandler that will override the protocol when it pulls the saved request out of the cache and force it to be https.

Amazon cloudfront custom origin rails with authentication

As far I understand, custom origin server with cloudfront only works if cloudfront is able to access files from my website url:
eg: www.domain.com/hello.html
However, my website has a login requirement in order to view hello.html. How can I have the login mechanism and still cache my real hello.html page in cloudfront using custom origin server?
I am using Ruby on Rails btw, but this is applicable to other stacks as well.
I'm pretty sure this is not possible. As you said, CloudFront has be to able to access the file to serve and cache it. I never saw an option to tell CloudFront to use a password to access the file.
An idea: maybe you can check in your Rails app, before you require the user to enter a password, if the request comes from CloudFront (I'm sure there are some headers indicating that) and, if so, bypass the login requirement?
Edit:
It says in the docs:
Do not configure your origin server to request client authentication.
One thing I'm pretty sure set though is the User Agent. Check for user_agent =~ /cloudfront/iand bypass authentication?

Resources