Rails: activating SSL support gets Chrome confused - ruby-on-rails

There is a nice option to config for the Rails app:
config.force_ssl = true
However it seems that just putting that to true doesn't get the HTTPS connections working. Even more - after trying (and failing) to connect to https://localhost:3000 with Chrome, I've set this option to false, and Chrome still tries to open https, even if I write http.
So, couple of questions:
--How to force Chrome not to try https anymore?
--What is the proper way of enabling SSL on my Rails app?
Update: The app is run on Heroku, and it seems that https is supported there automagically. Can I test SSL also locally? Like when running rails server?

First, I should say that I haven't tried this, but there are mainly two possibly reasons for Chrome still using HTTPS:
Using HTTP Strict Transport Security headers: if the server sets them, the client (supporting HSTS, like Chrome) is meant to stick to HTTPS for all subsequent requests to that host.
Permanent redirects. If the initial redirect you got was using "301 Moved Permanently" (and not 302 for example) to make the redirection,(*) the browser is meant to remember it ("The requested resource has been assigned a new permanent URI and any future references to this resource SHOULD use one of the returned URIs").
A likely solution to this would be to clear the cache in your browser.
(*) This question seems to indicate this is the case for Ruby on Rails with this config).

I had the same issue. What I did is using an ssl enforcer gem which adds a middleware that handles ssl and redirects. It has a strict option which enforces the configured protocols.
in your Gemfile add:
gem 'rack-ssl-enforcer'
in production.rb add:
config.middleware.use Rack::SslEnforcer, only: %r{your_regex_condition}, strict: true
This will force the requested pages to be secured and the rest to be non secured. It disables the HSTS header which is problematic in chrome (redirect caching issue).
You can also expire the cache for all cleints (if it already exist) to make sure you'll not get infinite redirect:
config.middleware.use Rack::SslEnforcer, only: %r{your_regex_condition}, :hsts => { :expires => 1, :subdomains => false }
also remove the ssl enforcement in production.rb (otherwise it might conflict with this middleware):
config.force_ssl = false

Let's see what happened once you updated your config file with:
config.force_ssl = true
This has caused Rack SSL Middleware to be loaded as the first middleware. As you can see in the code, Rack SSL sets an HSTS header by adding this line to the headers :
Strict-Transport-Security
It tells supported browsers such as Chrome to use HTTPS only to access your website.
So once you set back :
config.force_ssl = false
Chrome will still uses HTTPS to access your website and causes an error.
To solve this problem, you need to empty the HSTS cache. You can to that by going to the following url in your chrome browser :
chrome://net-internals/#hsts

Open your Chrome Developer Tools when you're at localhost: Then you can right click the refresh button ↻ and select "Empty cache and hard reload".
This error might also happens to you, if you start your server in the production environment, where HSTS is enabled.
Chrome redirects you to https://localhost:3000/ and says "SSL connection error".

Related

How to test if Rails rack-cors gem is working

I am trying to build a React - Rails API project. I added gem 'rack-cors' and created the config/initializers/cors.rb file:
Rails.application.config.middleware.insert_before 0, Rack::Cors do
allow do
origins "http://localhost:3001"
# The React part will be on port 3001 so thats way we add it
# Change it to the production url when going on production
resource "*",
headers: :any,
methods: [:get, :post, :put, :patch, :delete, :options, :head]
end
end
I would only like to allow the port 3001 since thats the port my React front-end will be served at.
Now I would like to test if this is actually working and blocking other requests.
Up until now, I have been using Postman to test the API (had to download it to work with http). I thought that because I added the filter to only a specific port, it would block the requests from Postman but it is still showing the data requested in the API call.
Also if I try reaching it like this on the browser:
http://localhost:3000/api/v1/users
It is still giving the data, which should be blocked to every port except 3001.
Why is it happening? Is there any other way to double check if it is working? Thanks!
NOTE: I killed the server and restarted it again and it is still behaving the same
To test CORS locally, I found this repo: https://github.com/njgibbon/nicks-cors-test
Just clone it, and click on the html file so it opens in your browser. By default it is calling the github API (https://api.github.com) and fetching info from there. You can open the console and check it.
If you change it to https://google.com it will throw a CORS restriction.
Similarly, you can change it to http://localhost:3000/api/v1/users (in my case) and it will throw a CORS error with the config I have now.
To double-check, just go to cors.rb and put origins "*". Restart the app server and try running again the html file. Now we won't be blocked.
Make an API call from browser (Not from URL and Not from postman). May be through ajax to test.
Postman does not implement the CORS restrictions

Rails server error "bad Request-Line" with HTTPS

I am getting this error when I am starting my server
[2016-01-06 18:57:00] ERROR bad Request-Line `\x16\x03\x01\x00�\x01\x00\x00�\x03\x03B0�c�ezc�*�[S'.
[2016-01-06 18:57:00] ERROR bad URI `�\x00�7���\x04^\b��\x02W'���U��1lH|�A�t\x00\x00\x1E�+�/\x00��\x14�\x13�'.
[2016-01-06 18:57:00] ERROR bad Request-Line `\x16\x03\x01\x00�\x01\x00\x00�\x03\x02�\x05\x01\x1D��~�-\x01Lω\x01���L"��\f� ����[�\x0F�\x00\x00\x14�'.
[2016-01-06 18:57:00] ERROR bad Request-Line `\x16\x03\x01\x00�\x01\x00\x00�\x03\x01
\x0E�|�s��(�9��4V:��*\f'\fh^衜&���-�\x00\x00\x14�'.
I disabled config.force_ssl = false and I also uninstalled thin... But every time when I open localhost:3000, it is automatically opening the HTTPS version https://localhost:3000/.
There are two possible reasons:
The https may be in the browser cache. Clear the browser cache, close the browser and retry.
As I explained in this article, the force_ssl configuration also sets the HSTS header. This header tells the browser that any subsequent request must for that domain be sent to HTTPS instead of HTTP (until the previously set expiration which by default is 1 year). You will have to also remove that domain from the browser HTTP list. How you delete the domain depends on the specific browser. Here's an example with Chrome and Firefox.

website is redirected to "https" in firefox(it is normal in other browser)

I am open my website in firefox, but because of something wrong with my website, url is force redirected to https(I think this is because I write config.force_ssl = true in ruby on rails application).
But after I redeploy another ruby on rails application, firefox still force redirect to https, how can I make firefox do not redirect to https?
This is a browser caching issue.
Rails redirects to the HTTPS site using HTTP Status 301 (moved permanentely), the redirect is cached by Firefox.
Because the Host is always localhost, Firefox cannot differentiate between the individual Rails applications.
To resolve this problem try emptying the cache and/or use private browsing mode for testing.
I don't know about Firefox but in Chrome there's the option to completely deactivate caching for as long the dev tools are open.
Try to clear the cache. Firefox may remember http 302 - redirect permanently, and it does not know when you are using different rails application (as you probably run both on localhost:3000).

How to disable SSL for custom subdomain

I've got a non wildcard SSL certificate for my root domain (example.com), and I'm using the heroku ssl endpoint add on. I'm using routing constraints so subdomain.example.com matches various controller actions, and I reroute the subdomain with CNAME records to the root domain. This all works fine in development, and it works fine in Tor browser if I disable https, but I can't get it to work in any ordinary browser.
I've tried using gem SSL-enforcer to enforce SSL except on host with subdomain as such:
config.middleware.use Rack::SslEnforcer, :except_hosts => 'subdomain.mydomain.com', :strict => true
Can I disable the https protocol for subdomain of my rails app? I feel like this might be impossible as I've read that SSL negotiations are made before the server knows the URL.
I would have recommended SSL-enforcer.....
Are you using config.force_ssl and generating a strict transport security header? I would suspect that might be the issue if it works with Tor but not a normal browser. Check the headers; if the HSTS exists, then that's probably the reason. Should be straight forward to change that (changing the max-age attribute to 0)
If not, check the Heroku docs again and make sure your settings and DNS/CNAME are correct....
https://devcenter.heroku.com/articles/ssl-endpoint#subdomain
Hope this helps.

No 'Access-Control-Allow-Origin' header is present on the requested resource

I am using omniauth-facebook with AngularJS and CORS is not working correctly .
My omniauth.rb is
Rails.application.config.middleware.use OmniAuth::Builder do
provider :facebook,"xxxxx", "xxxxx",
:scope => 'email,user_birthday,read_stream', :display => 'popup'
end
Everything works if i use it as rails app and request. But when i try to call 'http:\localhost:3000\users\auth\facebook" via Angular JS
$http.get('/users/auth/facebook').success(function(data, status, headers, config) {
console.log("back in success");
}).
error(function(data, status, headers, config) {
});
}
i see following error in JS console
XMLHttpRequest cannot load
https://www.facebook.com/dialog/oauth?client_id=xxxx&display=popup…thday%2Cread_stream&state=3352c1924bdbc9277f7b1070c38d67acf79b529f198323cb.
No 'Access-Control-Allow-Origin' header is present on the requested
resource. Origin 'http://localhost:3000' is therefore not allowed
access.
(The url is not displayed completely in console)
I added following line
config.middleware.insert_before Warden::Manager, Rack::Cors
but also this didn't work .
What is the best way or how can i override headers for OmniAuth ?
I am using Angularjs and gem devise ,omniauth-facebook
Since you are on your development environment you may want to try a workaround, by allowing you browser to run in a non-secure mode.
For Chrome on Windows, from CMD try:
> cd C:\Program Files (x86)\Google\Chrome\Application
> chrome.exe --user-data-dir="C:/Chrome dev session" --disable-web-security
The --disable-web-security flag will allow you to make cross domain requests. The --user-data-dir flag will allow you to open a new session only for development.
This is just a workaround for you development work! Don't use this in production or navigate to other sites in this session!
The issue is Javascript cannot make cross-domain requests. This is done for security reasons so that a script cannot call a remote server and expose sensitive data.
Below is a link to a very good and simple explanation with a few options on how to get around it:
http://developer.yahoo.com/javascript/howto-proxy.html
And here is a previous answer which has some good information as well:
Why am I seeing an "origin is not allowed by Access-Control-Allow-Origin" error here?
If they don't have the header set then you can't force them to have the headers. Perhaps you should look at using JSONP. However, mirroring through the server wouldn't be all that bad since you'll only have to deal with it at most once per visit, and more than likely once per user since so few people ever delete cookies.
Set 'Access-Control-Allow-Origin' in server will make the track.
Like:
ruby
headers['Access-Control-Allow-Origin'] = '*'
In rails.
The problem is you are getting the data from the https secure site that is facebook to your site which is http so the latest browsers are not supporting cross allow origin.
The only solution is make your site support https.
In your ApplicationController.rb add
def set_access_control_headers
headers['Access-Control-Allow-Origin'] = 'http://localhost:3000'
end
For CORS you have to whitelist the domain you want to access from cross origin request on the server side
headers['Access-Control-Allow-Origin'] = '*'
//star will allow all the domain you can specify also which url u want to access
on the client side,you have to set the header in config() as
$httpProvider.defaults.xsrfHeaderName = 'X-CSRFToken';
$httpProvider.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
some times that problem occurs because of browser.IE by default allow cross origin request. In chrome you will required to add one plugin that is "Allow-Control-Allow-Origin: *"and enabled it.

Resources