Rails request object contains wrong protocol - ruby-on-rails

I'm running Rails 3.1.2 on Apache with the latest Passenger, 3.0.11. I'm using force_ssl to require a secure connection in a few of my application's actions.
The web browser is warning that although the identity of the site has been verified and the connection is encrypted, the page contains other resources which are not secure. The culprit is a reference to the Google Fonts API being made over plain http. My view contains the following:
= stylesheet_link_tag "#{request.port}fonts.googleapis.com/css?family=Oswald"
I also tried this:
= stylesheet_link_tag "http#{request.ssl? ? 's' : ''}://fonts.googleapis.com/css?family=Oswald"
Both of these result in the stylesheet url having "http://".
I had success doing this in a Rails 3.0.5/Passenger 3.0.7/SslRequirement, but can't get it to work in Rails 3.2.1/Passenger 3.0.11/force_ssl.

put "//fonts.googleapis.com/css?family=Oswald" without the http or https - that way the browser uses the same protocol as the page you are on and doesn't show any warnings.

Related

Rails forms leading to Mixed Content warning

In my Rails app I use both Rails' native form_tag method and the simple_form_for method provided by the simple_form rubygem.
Both of them are leading to the following warning in the chrome console:
Mixed Content: The page at 'https://example.com' was loaded over a secure connection, but contains a form which targets an insecure endpoint 'http://example.com'. This endpoint should be made available over a secure connection.
And indeed, the rendered HTML forms use the http protocol for their action attribute.
What is the reason for that? All my other URL's use the https protocol.
You have not correct protocol set up for your environment.
Your server is running on HTTPS and form creates HTTP URL.
You need to tell your URL helpers to build the URLs with the same protocol as your server is running for your environment.
Development should run on HTTP, staging should be HTTPS and production as well HTTPS.
There are different ways how to do it. The best is to set protocol in your environment config file. So place this line:
Rails.application.routes.default_url_options[:protocol] = 'https'
into your environment config file like production.rb and staging.rb.
Another approach is to set the default protocol per controller action. Check this one for more info.
In case you are using the mailer, also check your mailer protocol settings. As described here.

Grails 2.3.7 HTTPS disable resource hashing for a particular file

I use HAProxy for load-balancing and ssl termination. Behind it I have several Grails apps, one of which is a sort of CMS for semi-technical users.
Problem
When the user links to a Javascript library in the CMS like this:
<link href="/js/fancybox/jquery.fancybox-1.3.4.css" rel="stylesheet" type="text/css" />
They get redirected by Grails to the hashed version:
http://test.com/static/qnzsUX0FP3vbKVmIdNgR3SKbHRAuosgVLRMgegqUyzc.js
The issue is that the browser sees the redirect to an insecure page, and doesn't actually load the javascript.
How do I allow users to access the resources under /web-app/js without having them redirected to the hashed version?
What I think I need is either:
1) Some way of telling Grails that it either should not redirect to the hashed static version via some kind of parameter in the url (?hash=no), it should just serve the Javascript file.
2) Or the request should redirect to the https or http version, depending on what protocol accessed it.
Environment
I am using Grails version is 2.3.7 and resources is 1.2.7.
I do like the benefits that the hashing provides, and it works well anywhere I can use the resource plugin, but would like to skip it in these specific instances.
Updating to Grails 2.4.2 and using the asset pipeline plugin would likely solve this, but also take more time than I want to spend debugging Javascript right now.

X-Frame-Options ALLOW-FROM a specific site allows from all

I'm using a rails application to serve a page from abc.com. In it, I set the response headers in my application controller (for every request through before_filter) so that it can be accessed through an iframe only from a specific site (xyz.com), through the following code:
def set_x_frame_options
response.headers["X-Frame-Options"] = "ALLOW-FROM http://www.xyz.com"
end
The problem is, not only am I able to access the page from abc.com on xyz but also on any other website. I want to limit the access to only xyz.com. When I examine the response headers in chrome console I can see the X-Frame-Options is being passed on correctly. This is happening across all browsers. Am I missing something?
For those looking for a definitive answer: it's not implemented in webkit, but does work in Firefox reportedly as of version 18.0. The following ruby syntax works for me in Firefox 20.0 on OSX:
response.headers["X-Frame-Options"] = "Allow-From http://www.website.com"

Rails: activating SSL support gets Chrome confused

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

how to handle errors like 404 / 500 in rails3

Hey, I hope you can help me.
I am trying to find a way to direct the user to the default error pages 404.html and 500.html in my public folder.
So when there is a routing or nomethod error it should be directed there to.
I already tried some stuff in my application controller but it didnt work.
Many thanks!!
Rails does this for you automatically when running in production mode. When you upload your application to a live server, Rails takes care of handling those exceptions and rendering the correct error pages with the correct header status. If you're trying to see what those pages look like (for testing or something), just access them directly via http://localhost:3000/404.html
Whenever you set up your Rails application on a live server (let's use Apache as an example), you give the site root as the /public folder in your application. Then, whenever a request is made to that server address, Apache first looks in that public folder and tries to serve a static asset (this is a configurable option in [environment].rb). If it can't find the requested page, then the request is forwarded through the Ruby stack.
When in production mode, if Rails encounters an error that isn't handled (i.e begin, rescue), it throws the error the whole way up to the stack, which then tells Apache (again, in my example) to render an appropriate error.
Here are some common errors that you'll see in development mode and what they render in production mode:
ActiveRecord::RecordNotFound => 404 (page not found)
nil.method => 500 (server error) unless you turn off whiny nils
ActionController::RoutingError => 404 (page not found)
Happens automatically if run in production mode - no need that you do that manually.
Have a look at this post to redirect all requests causing a Routing Error.

Resources