24

I'm trying to authenticate a user via Facebook or Twitter, get them to fill out their information, and then click save (thus creating a user record). I'm getting an OpenSSL error on that final step -- after clicking save. This happens at the Devise RegistrationsController#create method.

So I'm getting this error in my Rails application, hosted on Heroku:

2012-07-28T18:25:13+00:00 app[web.1]: OpenSSL::SSL::SSLError (SSL_connect returned=1 errno=0 state=SSLv3 read server certificate B: certificate verify failed)

I've seen plenty of solutions, none of them work. Here are some things I've tried:

1) Installing the certified gem

2) Upgrading the Heroku gem to v2.30, pushing again

3) This:

Rails.application.config.middleware.use OmniAuth::Builder do
  provider :twitter, TWITTER_KEY, TWITTER_SECRET, {:client_options => {:ssl => {:ca_file => "/usr/lib/ssl/certs/ca-certificates.crt"}}}
  provider :facebook, FACEBOOK_KEY, FACEBOOK_SECRET, {:scope => "publish_actions,user_location,email", :client_options => {:ssl => {:ca_file => "/usr/lib/ssl/certs/ca-certificates.crt"}}}
end

It seems like one problem could be that this cert file doesn't actually exist -- I've seen it in several places, and it seems like that is the default path to the ca_cert file for Heroku, but I could be wrong.

Oddly enough, this is happening after I've already authenticated via FB/Twitter, and am trying to create a user's account. Why would this be, and how can I solve/debug this? Sincerely confused.

Update: I added this line to the Omniauth initializer, and now it "works". Thus I've diagnosed the problem is with Omniauth. However, I'd like to still have the SSL verification... this obviously leaves a security gap.

OpenSSL::SSL::VERIFY_PEER = OpenSSL::SSL::VERIFY_NONE

varatis
  • 14,494
  • 23
  • 71
  • 114
  • take a look at my answer below. It still keeps the verification. – Pavel Nikolov Jun 07 '13 at 11:53
  • 1
    @Simone Carletti marked this question as duplicate, but it is not. The other question is about problems to update Ruby Gems and this one is for not being able to call 3rd party https:// services from Heroku. – Pavel Nikolov Feb 25 '15 at 17:03

2 Answers2

41

After some searching here is what I found:

If you’re using Ruby to open connections to an external server over https, eg. the Facebook Graph API, you may run into the following error:

OpenSSL::SSL::SSLError:SSL_connectreturned=1errno=0state=SSLv3readservercertificateB:certificateverifyfailed

This error is due to Ruby not being able to find the certification authority certificates (CA Certs) used to verify the authenticity of secured web servers. The solution is to download the this ca-bundle.crt into your application’s lib/ directory: Then add the following code to config/initializers/fix_ssl.rb:

require 'open-uri'
require 'net/https'

module Net
  class HTTP
    alias_method :original_use_ssl=, :use_ssl=

    def use_ssl=(flag)
      self.ca_file = Rails.root.join('lib/ca-bundle.crt').to_s
      self.verify_mode = OpenSSL::SSL::VERIFY_PEER
      self.original_use_ssl = flag
    end
  end
end

This should force ruby to use the CA bundle from your application’s lib/ directory.

Taken from: http://jimneath.org/2011/10/19/ruby-ssl-certificate-verify-failed.html

UPDATE:

You may need to use self.ca_path= instead of self.ca_file= depending on your system.

Pavel Nikolov
  • 9,401
  • 5
  • 43
  • 55
  • I tried this and it didn't work. How is the .crt file kept up to date? – netwire Jun 30 '13 at 15:48
  • 4
    You have to keep it up to date manually. If you are hosting on Heroku I think you can use their CA file `/usr/lib/ssl/certs/ca-certificates.crt` – Pavel Nikolov Jul 01 '13 at 01:53
  • 2
    Worked for me on Heroku using /usr/lib/ssl/certs/ca-certificates.crt - thanks! – Todd Jul 23 '13 at 17:55
  • This worked for me on Windows 7 using the exact code posted. – Nicola Peluchetti Aug 29 '14 at 00:51
  • @nicola-peluchetti when you say you got this to work on Windows 7, where exactly did you find the file in question? Or did you create it? If so, if which location? Thanks! – Gary Ewan Park Sep 11 '14 at 19:41
  • @GaryEwanPark as th OP said, copy the certificate in the `/lib` folder and create the ruby file in `config/initializers`. Restert the server obviously. – Nicola Peluchetti Sep 12 '14 at 00:07
  • @nicola-peluchetti That is the thing, in my installation of Ruby, (which was done using Chocolatey, and not RubyInstaller) I don't have a ```config/initializers``` folder, so I was looking for some help on where, in my installation, I can implement this solution. Thanks! – Gary Ewan Park Sep 12 '14 at 06:10
  • @GaryEwanPark this solution is for Ruby on Rails. – Nicola Peluchetti Sep 16 '14 at 18:29
  • 1
    I just started getting this error on Heroku - nothing has changed in my app... I tried Pavel's solution with self.ca_path and self.ca_file and the hardwired path to the certs - did not work for me. I'm using ruby 1.9.3 and Rails 3.2.12. The OpenSSL version is OpenSSL 0.9.8k 25 Mar 2009. Any other ideas? – craic.com Feb 13 '15 at 16:51
  • @craic.com are you using the path to Heroku CA certificates `/usr/lib/ssl/certs/ca-certificates.crt`? – Pavel Nikolov Feb 13 '15 at 17:36
  • If hosting on heorku, how are we referencing path? `self.ca_file = Rails.root.join('/usr/lib/ssl/certs/ca-certificates.crt').to_s` – DaynaJuliana Mar 25 '15 at 00:58
  • @DaynaJuliana no need to use `Rails.root` here since this is an absolute file path not relative to the root of the project. – Pavel Nikolov Mar 26 '15 at 11:18
  • @PavelNikolov this solution doesn't work anymore...I had a recent Windows update on both my laptop and desktop. Tried both `self.ca_path=` and `self.ca_file`. – Ka Mok Aug 12 '16 at 02:19
  • @KaMok The provided answer is not tested on Windows, only on Linux. Unfortunately, I do not have a Windows machine where I can test : ( – Pavel Nikolov Aug 12 '16 at 05:00
  • On heroku, I tried all the variations mentioned and still have no luck. The things I tried were replacing `lib/ca-bundle.crt` with `/usr/lib/ssl/certs/ca-certificates.crt`, and using `ca_path` and `ca_file`, but nothing seems to work. I had never had this error before - it arose somewhat randomly. I will use [this](https://stackoverflow.com/a/33669869/5783745) solution as an imperfect work around for now. – stevec May 31 '20 at 19:30
7

It sounds like you've got the right openssl configuration in OmniAuth, but perhaps your CA certs path isn't correct?

You can check that on your heroku servers by running:

heroku run bash

... and then running openssl to display the proper path:

$ openssl version -a
OpenSSL 1.0.0e 6 Sep 2011
OPENSSLDIR: "/usr/lib/ssl"

... You should find the ca_certificates.crt file at $OPENSSLDIR/certs/ca-certificates.crt

I would confirm that path an update your code to match.

Winfield
  • 18,985
  • 3
  • 52
  • 65
  • 1
    Yup ca-certificates is there... (in `/usr/lib/ssl/certs`). Thanks for `heroku run bash`.. didn't know about that – varatis Jul 30 '12 at 21:04
  • Is this something that Omniauth requires, or every external request? Maybe that's the problem... I'm making another external request that isn't working? – varatis Jul 30 '12 at 21:05
  • Yeah, can you provide more context from your logs about where it's throwing the SSL error? Perhaps a stack trace? – Winfield Jul 30 '12 at 22:21
  • Unfortunately, that's all it gave me so far, I'll try to set the debug level higher and let you know. But also, check the update -- it's sort of helpful. – varatis Jul 31 '12 at 01:58