2010-10-20 10 views
64

Я следил за Railscast #235, чтобы попытаться установить минимальную аутентификацию Facebook.OmniAuth & Facebook: подтверждение сертификата не удалась

Я сначала установил аутентификацию в Twitter, как это сделал Райан. Это работало безупречно.

Затем я перешел к добавлению входа в систему Facebook. Однако после авторизации приложения редирект на /auth/facebook/callback терпит неудачу с:

SSL_connect returned=1 errno=0 state=SSLv3 read server certificate B: certificate verify failed 

Я работаю на локальном хосте. Я не установил SSL в приложении. Что я делаю не так?

+5

Есть ли надежда этого 1.9. 2 вопрос «официально» разрешен? Я мог бы неправильно понять ответ ниже, но утверждение 'if' с« PATCH или HACK »кажется бесполезным (почему вообще есть оператор' if'?), И нет никаких объяснений о том, какова цель общего кода, кроме предотвращая ошибку. – ClosureCowboy

+0

@closurecowboy, если вы посмотрите на ответ Алексея Кремера, он тщательно объясняет, почему эта ошибка происходит. Вы действительно хотите избежать решения, помеченного как ответ в вашем производственном коде, поскольку использование VERIFY_NONE отключает проверку сверток SSL-сертификатов. Я адаптировал его решение на странице wiki для Omniauth (https://github.com/intradea/omniauth/wiki/Setting-up-SSL-certificate-locations-in-Linux). Если вам или кому-то еще есть что добавить к нему, отредактируйте его, чтобы улучшить его. –

+0

Общее решение для всех приложений Rails здесь http://stackoverflow.com/a/16983443/11792 –

ответ

74

Настоящая проблема заключается в том, что Faraday (который использует Omniauth/Oauth для своих HTTP-вызовов) не не устанавливал переменную ca_path для OpenSSL. По крайней мере, на Ubuntu большинство корневых сертификатов хранятся в «/ etc/ssl/certs». Поскольку Faraday не не устанавливал эту переменную (и в настоящее время не имеет способа сделать это) , OpenSSL не не нашел корневой сертификат для SSL-сертификата Facebook.

У меня есть submitted a pull request to Faraday, который добавит поддержку этой переменной, и мы надеемся, что они скоро потянут за это изменение. До тех пор вы можете monkeypatch faraday выглядеть как this или использовать my fork of Faraday. После этого вы должны указать версию 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 

Итак, повторим:

  1. Фарадея должен быть обновлен для поддержки SSL ca_path. Установите Faraday 0.6.1
  2. Ваше приложение должно использовать OAuth2 версии 0.3.0. Возможно, вам понадобится fork omniauth, так как в настоящее время он имеет незначительную версию зависимости в дереве 0.2.x. Обновление до OmniAuth 0.2.2
  3. Измените поставщика инициализатор, чтобы указать путь сертификата вашей системы («/ и т.д./SSL/сертификаты» на Ubuntu и др)

Надеюсь, следующие выпуски как Фарадей и Omniauth будет включать это решение.

Благодаря KirylP выше для установки меня на правильный путь.

+6

работает и на героику! – digitalWestie

+0

Работает как шарм. r1.8.7, omniauth0.2.2 Спасибо большое –

+0

Как вы исправите эту ошибку в среде разработки, где у меня нет SSL-сертификатов на моей машине? – mindtonic

0

Это, кажется, проблема 1.9.x. Возврат к 1.8.7 исправил проблему.

+2

Но все равно стоит найти исправление Ruby 1.9.2 .... –

+0

У меня есть эта ошибка с Ruby 1.8.7 и jRuby - - Это проблема установки и конфигурации. Проверьте другие ссылки выше. – will

3

Edit: Проверьте ответ ниже, как это более актуально

Это работает для меня (исправить любезность https://github.com/jspooner):

Создать файл в каталоге вашего Initializer со следующей обезьяной патч:

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 
+0

Работал для меня в Heroku.thanks – Gady

+3

Не относится к новой версии Faraday. проверьте ответ ниже ... –

+2

Отключение проверки SSL - это плохой способ решить эту проблему. Вместо этого укажите OpenSSL на правильные сертификаты. – eric

7

Удалось пройти проверку 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.

4

Похоже, что 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 
+1

Я также согласен, что должен быть лучший способ, но ваше сообщение помогло мне из тонны. Мой код ранее работал с Omniauth 0.2.0 (который использовал Faraday 0.5.7 вместо 0.6.0), поэтому я просто поместил 'gem 'omniauth 0.2.0'' в свой gemfile, и это позволит мне закончить разработку некоторых функции сначала. –

+1

Я заметил, что это не работает для Faraday 0.6.1, вы можете обновить код, пожалуйста? –

+0

Randles Не работает, давая ошибку: 'No Method error: undefined method' response_headers 'для # 'можете ли вы предложить какое-либо дополнение этого или любые изменения, необходимые в этом, чтобы сделай так, чтоб это работало? – Surya

12

Я на Ubuntu 10.10 (Maverick) ... боролись около 6 часов, прежде чем я получил его на работу, поделиться своим опытом

  1. не пробовал обезьяны патч
  2. пытался {: client_options => { : = SSL> {: ca_path => "/ и т.д./SSL/сертификаты"}}, но до сих пор не работал
  3. пытался рубин 1.8.7 еще не работал
  4. пробовал разные версии OmniAuth & Фарадея, до сих пор не повезло.

Единственное, что сделал это, чтобы работа была следующая (спасибо Alex)

if Rails.env.development? 
    OpenSSL::SSL::VERIFY_PEER = OpenSSL::SSL::VERIFY_NONE 
end 
+0

Работал на OS X, а также для меня! Благодаря! Поскольку проверка происходит только в среде разработки, это не должно быть риском безопасности при производстве –

+0

То же самое! Я собираюсь с этим решением, потому что ни один из существующих не работает для меня = ( – PeaceDefener

+0

Плохая идея отключить проверку SSL! Не делайте этого! – Dennis

1

Моя проблема была решена путем обеспечения того, OpenSSL использует правильный каталог сертификатов:

Для моей системы (ubuntu64) это было: ENV [ 'SSL_CERT_DIR'] = '/ USR/доли/CA-сертификаты /'

Это был использованием JRuby-OpenSSL с JRuby 1.6.0

Я просто добавил эту настройку в development.rb

18

У меня была эта проблема и я попытался использовать аргумент: 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 
+0

Тысяча благодаря вам Emerson! У меня была эта проблема в Cent OS. : ca_file, Cent OS, Redhat, Fedora, pki, TLS, SSL. thx –

+1

Это сработало для меня, где 'ca_path' не было, на Amazon Linux. – lawrence

+0

Большое вам спасибо. В EC2 это сделало трюк. –

2

Я использую 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' }) 
+0

Это помогло мне. Для Oauth2 0.5.1 это примерно так: oauth_client = OAuth2 :: Client.new (fb_app_id, fb_app_secret, { : site => 'https: //graph.facebook. com ', : token_url =>'/oauth/access_token ', : connection_opts => {: ssl => {: ca_path => "/ etc/ssl/certs}} }) – forresto

6

При развертывании на Heroku, вы хотите укажите конкретное расположение файла. Это работает для меня (в конфигурации/инициализаторов/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 
+0

Итак, как вы это нашли? – Alex

5

Я решил это с CA пачке из: http://certifie.com/ca-bundle/

И в моем DEViSE инициализаторе:

:client_options => { :ssl => { :ca_file => "#{Rails.root}/config/ca-bundle.crt" } } } 
0

Вот что Я сделал это, если у вас возникли проблемы с Leopard.

Мой сертификат был старый и нуждается в обновлении. Я скачал это:

http://curl.haxx.se/ca/cacert.pem

Затем заменил мой сертификат, который был найден здесь на Леопарда:

/usr/share/curl/curl-ca-bundle.crt

Reload что вы имеете это доступ к нему, и вам должно быть хорошо идти!

0

Просто потому, что инструкции были незначительные немного отличается за то, что работал для меня, я думал, что я добавляю мои 2 цента:

Я на OS X Lion и с помощью MacPorts и RVM

Я установил curl- ч-расслоение:

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 
0

В Ubuntu, все, что я должен был сделать обновление /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 

Вола!

0

я встретил подобную ошибку, используя 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

И вы сделали.

1

Я знаю, это звучит тривиально, но убедитесь, что вы используете правильный протокол. Я продолжал получать эту ошибку, а затем понял, что пытаюсь подключиться через http. 1,5 часа впустую, потому что я идиот.

4

все решения не работали для меня, то я нашел этот

http://railsapps.github.io/openssl-certificate-verify-failed.html

rvm osx-ssl-certs update all 

OSX 10,8 рубин 2.0.0 с помощью РВМ

+2

Я нашел это решение самостоятельно, и я собирался закончить ответы, чтобы написать его. +1 от меня. – sufleR

+1

Это сработало для меня, и все просто. –

 Смежные вопросы

  • Нет связанных вопросов^_^