OmniAuth & Facebook: проверка сертификата не выполнена
Я следил за Railscast # 235, чтобы попытаться установить минимальную аутентификацию Facebook.
Сначала я настроил аутентификацию Twitter, как это сделал сам Райан. Это работало безупречно.
Затем я перешел к добавлению входа в Facebook. Однако после авторизации приложения перенаправление на /auth/facebook/callback
не выполняется:
SSL_connect returned=1 errno=0 state=SSLv3 read server certificate B: certificate verify failed
Я работаю над localhost. Я не установил SSL в приложении. Что я делаю неправильно?
Ответы
Ответ 1
Реальная проблема заключается в том, что Faraday (который использует Omniauth/Oauth для своих HTTP-вызовов) is not не задавал переменную ca_path для OpenSSL. По крайней мере, на Ubuntu большинство корневых сертификатов хранятся в "/etc/ssl/certs". Поскольку Faraday не не устанавливал эту переменную (и в настоящее время не имеет метода для этого), OpenSSL не wasn 't найти корневой сертификат для SSL-сертификата Facebook.
Я отправил запрос на передачу в Faraday, который добавит поддержку этой переменной, и, надеюсь, они скоро потянут это изменение, До тех пор вы можете monkeypatch faraday выглядеть как this или использовать мою вилку Фарадей. После этого вы должны указать версию 0.3.0 из OAuth2 gem в Gemspec, которая поддерживает передачу опций SSL до Faraday. Теперь вам нужно обновить до Faraday 0.6.1, который поддерживает передачу переменную ca_path и обновление до OmniAuth 0.2.2, которая имеет соответствующие зависимости для OAuth2. Затем вы сможете правильно исправить эту проблему, просто добавив следующее в свой инициализатор Omniauth:
Rails.application.config.middleware.use OmniAuth::Builder do
provider :facebook, FACEBOOK_KEY, FACEBOOK_SECRET, {:client_options => {:ssl => {:ca_path => "/etc/ssl/certs"}}}
end
Итак, чтобы повторить:
-
Faraday необходимо обновить, чтобы поддерживать SSL ca_path. Установить Faraday 0.6.1
-
Ваше приложение должно использовать OAuth2 версии 0.3.0. Возможно, вам понадобится fork omniauth, так как в настоящее время он имеет незначительную версию зависимости в дереве 0.2.x. Обновление до OmniAuth 0.2.2
- Измените инициализатор поставщика, чтобы указать путь к вашему системному сертификату ( "/etc/ssl/certs" в Ubuntu и др.)
Будем надеяться, что в следующих версиях как Faraday, так и Omniauth будет включено это решение.
Спасибо KirylP выше, чтобы установить меня на правильный путь.
Ответ 2
У меня возникла эта проблема и я попытался использовать аргумент: ca_path без успеха. Посмотрев через Github некоторое время, я наткнулся на предложение, которое упоминалось с использованием: ca_file и прямо указывает на сертификацию.
Rails.application.config.middleware.use OmniAuth::Builder do
provider :facebook, 'secret_key', 'secret_key',
:client_options => {:ssl => {:ca_file => '/etc/pki/tls/certs/ca-bundle.crt'}}}
end
Если вам нужно получить путь к файлам системной сертификации (и вашему использованию linux), просто введите из терминала. Это даст вам кучу информации о вашей настройке SSL, включая путь (см. OPENSSLDIR). Вам нужно добавить certs/ca-bundle.crt к предоставленному пути.
open-ssl version -a
Ответ 3
Я на ubuntu 10.10 (Maverick)... боролся около 6 часов, прежде чем я получил его на работу, поделился своим опытом
- не пробовал патч обезьяны
- try {: client_options = > {: ssl = > {: ca_path = > "/etc/ssl/certs" }}, но все еще не работает
- попробовал ruby 1.8.7 все еще не работал
- попробовал разные версии omniauth и faraday, до сих пор не повезло.
Единственное, что заставило его работать, было следующее (спасибо Alex)
if Rails.env.development?
OpenSSL::SSL::VERIFY_PEER = OpenSSL::SSL::VERIFY_NONE
end
Ответ 4
Удалось пройти проверку SSL-сертификата, как и должно быть.
Мой проект использует идентификатор 37signals для интеграции Basecamp (Ruby 1.9.2-p130, Rails 3.0.4).
RAILS_ROOT/конфигурации/Инициализаторы/omniauth.rb
require 'omniauth/oauth'
Rails.application.config.middleware.use OmniAuth::Strategies::ThirtySevenSignals,
'CLIENT_ID', 'CLIENT_SECRET', {client_options: {ssl: {ca_file: Rails.root.join('gd_bundle.crt').to_s}}}
module OAuth2
class Client
def initialize(client_id, client_secret, opts = {})
adapter = opts.delete(:adapter)
self.id = client_id
self.secret = client_secret
self.site = opts.delete(:site) if opts[:site]
self.options = opts
self.connection = Faraday::Connection.new(site, {ssl: opts.delete(:ssl)})
self.json = opts.delete(:parse_json) # ^ my code starts here
if adapter && adapter != :test
connection.build { |b| b.adapter(adapter) }
end
end
end
end
Где 'CLIENT_ID', 'CLIENT_SECRET' вы можете получить 37signals.com и файл пакета сертификатов gd_bundle.crt из GoDaddy, поскольку 37signals используют свой CA.
Ответ 5
Если вы развертываете в Heroku, вы хотите указать на конкретное расположение файла. Это работает для меня (в config/initializers/omniauth.rb):
Rails.application.config.middleware.use OmniAuth::Builder do
# This cert location is only for Heroku
provider :facebook, APP_ID, APP_SECRET, {:client_options => {:ssl => {:ca_file => "/usr/lib/ssl/certs/ca-certificates.crt"}}}
end
Ответ 6
Я решил это с помощью пакета CA из: http://certifie.com/ca-bundle/
И в моем инициализаторе Devise:
:client_options => { :ssl => { :ca_file => "#{Rails.root}/config/ca-bundle.crt" } } }
Ответ 7
Похоже, Omniauth теперь использует более новую версию Faraday, которая объясняет, почему надпись на обезьяне выше не работала для меня. Я согласен, что должен быть лучший способ, но для тех, кому просто нужно заставить его работать, чтобы проверить, здесь обновленная версия:
(создайте файл в каталоге инициализаций со следующим кодом)
require 'faraday'
module Faraday
class Adapter
class NetHttp < Faraday::Adapter
def call(env)
super
url = env[:url]
req = env[:request]
http = net_http_class(env).new(url.host, url.inferred_port)
if http.use_ssl = (url.scheme == 'https' && env[:ssl])
ssl = env[:ssl]
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
http.cert = ssl[:client_cert] if ssl[:client_cert]
http.key = ssl[:client_key] if ssl[:client_key]
http.ca_file = ssl[:ca_file] if ssl[:ca_file]
http.cert_store = ssl[:cert_store] if ssl[:cert_store]
end
http.read_timeout = http.open_timeout = req[:timeout] if req[:timeout]
http.open_timeout = req[:open_timeout] if req[:open_timeout]
if :get != env[:method]
http_request = Net::HTTPGenericRequest.new \
env[:method].to_s.upcase, # request method
!!env[:body], # is there data
true, # does net/http love you, true or false?
url.request_uri, # request uri path
env[:request_headers] # request headers
if env[:body].respond_to?(:read)
http_request.body_stream = env[:body]
env[:body] = nil
end
end
begin
http_response = if :get == env[:method]
# prefer `get` to `request` because the former handles gzip (ruby 1.9)
http.get url.request_uri, env[:request_headers]
else
http.request http_request, env[:body]
end
rescue Errno::ECONNREFUSED
raise Error::ConnectionFailed, $!
end
http_response.each_header do |key, value|
response_headers(env)[key] = value
end
env.update :status => http_response.code.to_i, :body => http_response.body
@app.call env
end
end
end
end
Ответ 8
все решения не работали для меня, тогда я нашел это
http://railsapps.github.io/openssl-certificate-verify-failed.html
rvm osx-ssl-certs update all
osx 10.8 ruby 2.0.0 через rvm
Ответ 9
Изменить: проверьте ответ ниже, поскольку он более релевантен
Это сработало для меня (исправить любезно https://github.com/jspooner):
Создайте файл в каталоге инициализатора со следующим патчем обезьяны:
require 'faraday'
module Faraday
class Adapter
class NetHttp < Faraday::Adapter
def call(env)
super
is_ssl = env[:url].scheme == 'https'
http = net_http_class(env).new(env[:url].host, env[:url].port || (is_ssl ? 443 : 80))
if http.use_ssl = is_ssl
ssl = env[:ssl]
if ssl[:verify] == false
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
else
http.verify_mode = OpenSSL::SSL::VERIFY_NONE # <= PATCH or HACK ssl[:verify]
end
http.cert = ssl[:client_cert] if ssl[:client_cert]
http.key = ssl[:client_key] if ssl[:client_key]
http.ca_file = ssl[:ca_file] if ssl[:ca_file]
end
req = env[:request]
http.read_timeout = net.open_timeout = req[:timeout] if req[:timeout]
http.open_timeout = req[:open_timeout] if req[:open_timeout]
full_path = full_path_for(env[:url].path, env[:url].query, env[:url].fragment)
http_req = Net::HTTPGenericRequest.new(
env[:method].to_s.upcase, # request method
(env[:body] ? true : false), # is there data
true, # does net/http love you, true or false?
full_path, # request uri path
env[:request_headers]) # request headers
if env[:body].respond_to?(:read)
http_req.body_stream = env[:body]
env[:body] = nil
end
http_resp = http.request http_req, env[:body]
resp_headers = {}
http_resp.each_header do |key, value|
resp_headers[key] = value
end
env.update \
:status => http_resp.code.to_i,
:response_headers => resp_headers,
:body => http_resp.body
@app.call env
rescue Errno::ECONNREFUSED
raise Error::ConnectionFailed.new(Errno::ECONNREFUSED)
end
def net_http_class(env)
if proxy = env[:request][:proxy]
Net::HTTP::Proxy(proxy[:uri].host, proxy[:uri].port, proxy[:user], proxy[:password])
else
Net::HTTP
end
end
end
end
end
Ответ 10
Я использую Faraday 0.6.1 и OAUTH2 (один, не обернутый чем-либо). Этого было достаточно, чтобы решить эту проблему для меня (на Gentoo, должен работать на Ubunto)
Поверните это
client = OAuth2::Client.new(FACEBOOK_API_KEY, FACEBOOK_API_SECRET, :site => FACEBOOK_API_SITE)
В этот
client = OAuth2::Client.new(FACEBOOK_API_KEY, FACEBOOK_API_SECRET, :site => FACEBOOK_API_SITE, :ssl => {:ca_path => '/etc/ssl/certs' })
Ответ 11
Моя проблема была решена путем обеспечения того, чтобы openSSL использовал правильный каталог сертификата:
Для моей системы (ubuntu64) это было:
ENV ['SSL_CERT_DIR'] = '/usr/share/ca-certificates/'
Это использовало jruby-openssl с JRuby 1.6.0
Я добавил этот параметр в development.rb
Ответ 12
Я знаю, что это звучит тривиально, но убедитесь, что вы используете правильный протокол. Я продолжал получать эту ошибку, а затем понял, что пытаюсь подключиться через http. 1,5 часа впустую, потому что я идиот.
Ответ 13
Кажется, это проблема 1.9.x. Возврат к 1.8.7 исправил проблему.
Ответ 14
Вот что я сделал, что помогло, если у вас есть проблема с Leopard.
Мой сертификат был старым и нуждался в обновлении. Я скачал это:
http://curl.haxx.se/ca/cacert.pem
Затем заменил мой сертификат, который был найден здесь на Leopard:
/usr/share/curl/curl-ca-bundle.crt
Перезагрузите все, что у вас есть, и вы должны быть добрыми!
Ответ 15
Просто потому, что инструкции были немного разными для того, что сработало для меня, я думал, что добавляю свои 2 цента:
Я нахожусь в OS X Lion и использую macports и rvm
Я установил curl-ca-bundle:
sudo port install curl-ca-bundle
Затем я скорректировал свою конфигурацию omniauth следующим образом:
Rails.application.config.middleware.use OmniAuth::Builder do
provider :google_oauth2, APP_CONFIG['CONSUMER_KEY'], APP_CONFIG['CONSUMER_SECRET'],
:scope => 'https://www.google.com/m8/feeds https://www.googleapis.com/auth/userinfo.profile',
:ssl => {:ca_path => "/share/curl/curl-ca-bundle.crt"}
end
Ответ 16
В Ubuntu все, что мне нужно было сделать, это update/environments/development.rb:
Rails.application.config.middleware.use OmniAuth::Builder do
provider :facebook, FACEBOOK_KEY, FACEBOOK_SECRET, {:client_options => {:ssl => {:ca_path => "/etc/ssl/certs"}}}
end
а затем:
cd /etc/ssl/certs
sudo wget http://curl.haxx.se/ca/cacert.pem
Wola!
Ответ 17
Наконец-то я нашел исправление для Mountain Lion. См.: http://coderwall.com/p/f4hyqw
rvm pkg install openssl
rvm reinstall 1.9.3 --with-openssl-dir=$rvm_path/usr
Ответ 18
Я столкнулся с аналогичной ошибкой, используя RVM на Mountain Lion. Кажется, что Ruby не может найти сертификат CA, которому необходимо разрешить SSL-соединение. Вам нужно установить его. Это решение выполнило трюк:
http://fredwu.me/post/28834446907/fix-openssl-error-on-mountain-lion-and-rvm
(Хотя я не мог загрузить эту страницу в своем браузере, мне пришлось найти ее в кеше Google.)
Вот короткий ответ:
curl http://curl.haxx.se/ca/cacert.pem -o ~/.rvm/usr/ssl/cert.pem
И все готово.