OmniAuth e Facebook: verifica certificato non riuscita

Ho seguito Railscast # 235 per provare e impostare un’autenticazione Facebook minima.

Per prima cosa ho impostato un’autenticazione su Twitter, come fatto da Ryan stesso. Funzionava perfettamente.

Poi sono passato ad aggiungere un login di Facebook. Tuttavia, dopo aver autorizzato l’applicazione, il reindirizzamento a /auth/facebook/callback esito negativo con:

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

Sto lavorando su localhost. Non ho impostato alcun SSL all’interno dell’app. Che cosa sto facendo di sbagliato?

Il vero problema è che Faraday (che Omniauth / Oauth usa per le loro chiamate HTTP) non stava impostando la variabile ca_path per OpenSSL. Almeno su Ubuntu, la maggior parte dei certificati di root sono memorizzati in “/ etc / ssl / certs”. Dato che Faraday non lo era, non stava impostando questa variabile (e al momento non ha un metodo per farlo) , OpenSSL non stava trovando il certificato di root per il certificato SSL di Facebook.

Ho inviato una richiesta di pull a Faraday che aggiungerà il supporto per questa variabile e speriamo che inseriranno presto questa modifica. Fino ad allora, puoi fare una monkeypatch di faraday per assomigliare a questo o usare la mia forchetta di Faraday . Dopodiché, dovresti specificare la versione 0.3.0 della gem OAuth2 nel tuo Gemspec che supporta il passaggio delle opzioni SSL fino a Faraday. Tutto quello che devi fare ora è l’aggiornamento a Faraday 0.6.1, che supporta il passaggio della variabile ca_path e l’aggiornamento a OmniAuth 0.2.2, che ha le dipendenze appropriate per OAuth2. Sarai quindi in grado di correggere correttamente questo problema aggiungendo semplicemente quanto segue al tuo inizializzatore Omniauth:

 Rails.application.config.middleware.use OmniAuth::Builder do provider :facebook, FACEBOOK_KEY, FACEBOOK_SECRET, {:client_options => {:ssl => {:ca_path => "/etc/ssl/certs"}}} end 

Quindi, per riassumere:

  1. Faraday deve essere aggiornato per supportare SSL ca_path. Installa Faraday 0.6.1
  2. La tua app deve utilizzare OAuth2 versione 0.3.0. Potrebbe essere necessario eseguire il fork di omniauth poiché attualmente ha una dipendenza di versione secondaria nell’albero 0,2.x. Eseguire l’aggiornamento a OmniAuth 0.2.2
  3. Modifica l’inizializzatore del tuo provider in modo che punti al percorso del certificato del tuo sistema (“/ etc / ssl / certs” su Ubuntu et al)

Speriamo che le prossime versioni di Faraday e Omniauth incorporeranno questa soluzione.

Grazie a KirylP sopra per avermi messo sulla strada giusta.

Stavo avendo questo problema e ho provato ad usare l’argomento: ca_path senza successo. Dopo aver esaminato Github per un po ‘, mi sono imbattuto in un suggerimento che menzionava l’utilizzo di: ca_file e punto direttamente alla certificazione.

 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 

Se è necessario ottenere il percorso per i file di certificazione dei sistemi (e per l’utilizzo di linux), digitare semplicemente dal terminale. Questo ti darà un sacco di informazioni sulla tua configurazione SSL, incluso il percorso (vedi OPENSSLDIR). Dovrai aggiungere certs / ca-bundle.crt al percorso fornito.

 open-ssl version -a 

Sono su ubuntu 10.10 (Maverick) … ho faticato circa 6 ore prima che riuscissi a farlo funzionare, condividendo la mia esperienza

  1. non ho provato la patch di scimmia
  2. provato {: client_options => {: ssl => {: ca_path => “/ etc / ssl / certs”}} ma non ha funzionato
  3. provato Ruby 1.8.7 ancora non ha funzionato
  4. provato diverse versioni di omniauth e faraday, ancora senza fortuna.

L’unica cosa che ha funzionato è stata seguire (grazie Alex)

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

Gestito per passare attraverso la verifica del certificato SSL come deve essere. Il mio progetto utilizza l’ID 37signals per l’integrazione di Basecamp (Ruby 1.9.2-p130, Rails 3.0.4).

RAILS_ROOT / config / initializers / 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 

Dove ‘CLIENT_ID’, ‘CLIENT_SECRET’ puoi ottenere su 37signals.com e sui certificati raggruppa il file gd_bundle.crt da GoDaddy perché 37signals sta usando la loro CA.

Se si sta distribuendo su Heroku, si desidera puntare al percorso del file specifico. Questo funziona per me (in 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 

Ho risolto questo problema con il pacchetto CA da: http://certifie.com/ca-bundle/

E nel mio inizializzatore Devise:

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

Sembra che Omniauth ora usi una versione più recente di Faraday, il che spiega perché la patch della scimmia sopra non funzionasse per me. Sono d’accordo che ci deve essere un modo migliore, ma per chiunque altro abbia solo bisogno di farlo funzionare per testare, ecco una versione aggiornata:

(crea un file nella tua directory di inizializzatori con il seguente codice)

 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 

tutte le soluzioni non hanno funzionato per me, quindi ho trovato questo

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

 rvm osx-ssl-certs update all 

osx 10.8 ruby ​​2.0.0 via rvm

Modifica: controlla la risposta qui sotto perché è più pertinente

Questo ha funzionato per me (correzione per gentile concessione di https://github.com/jspooner ):

Crea un file nella directory del tuo inizializzatore con la seguente patch di scimmia:

 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 

Sto usando Faraday 0.6.1 e OAUTH2 (da solo, non racchiuso da nulla). Questo è stato sufficiente per risolvere il problema per me (su Gentoo, dovrebbe funzionare su Ubunto)

Turn this

  client = OAuth2::Client.new(FACEBOOK_API_KEY, FACEBOOK_API_SECRET, :site => FACEBOOK_API_SITE) 

In questo

  client = OAuth2::Client.new(FACEBOOK_API_KEY, FACEBOOK_API_SECRET, :site => FACEBOOK_API_SITE, :ssl => {:ca_path => '/etc/ssl/certs' }) 

Il mio problema è stato risolto assicurando che openSSL stia usando la giusta directory dei certificati:

Per il mio sistema (ubuntu64) questo era: ENV [‘SSL_CERT_DIR’] = ‘/ usr / share / ca-certificates /’

Questo stava usando jruby-openssl con JRuby 1.6.0

Ho appena aggiunto questa impostazione a development.rb

So che sembra banale, ma assicurati di utilizzare il protocollo giusto. Ho continuato a ricevere questo errore e poi mi sono reso conto che stavo cercando di connettermi tramite http. 1,5 ore sprecate perché sono un idiota.

Questo sembra essere un problema 1.9.x. Il ripristino alla versione 1.8.7 ha risolto il problema.

Ecco cosa ho fatto che mi ha aiutato se hai un problema specifico su Leopard.

Il mio cert era vecchio e doveva essere aggiornato. Ho scaricato questo:

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

Quindi sostituito il mio certificato che è stato trovato qui su Leopard:

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

Ricarica qualsiasi cosa tu stia accedendo e dovresti essere bravo!

Solo perché le istruzioni erano leggermente diverse per quello che ha funzionato per me, ho pensato di aggiungere i miei 2 centesimi:

Sono su OS X Lion e uso macports e rvm

Ho installato curl-ca-bundle:

 sudo port install curl-ca-bundle 

Quindi ho regolato la mia configurazione di omniauth per essere questa:

 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 

Su Ubuntu, tutto ciò che dovevo fare era aggiornare /environments/development.rb in:

 Rails.application.config.middleware.use OmniAuth::Builder do provider :facebook, FACEBOOK_KEY, FACEBOOK_SECRET, {:client_options => {:ssl => {:ca_path => "/etc/ssl/certs"}}} end 

e poi:

 cd /etc/ssl/certs sudo wget http://curl.haxx.se/ca/cacert.pem 

Wola!

Alla fine ho trovato una soluzione per Mountain Lion. Vedi: http://coderwall.com/p/f4hyqw

 rvm pkg install openssl rvm reinstall 1.9.3 --with-openssl-dir=$rvm_path/usr 

Ho riscontrato un errore simile usando RVM su Mountain Lion. Sembra che Ruby non riesca a trovare il certificato CA di cui ha bisogno per autorizzare la connessione SSL. È necessario installarne uno. Questa soluzione ha fatto il trucco:

http://fredwu.me/post/28834446907/fix-openssl-error-on-mountain-lion-and-rvm

(Anche se non potevo effettivamente caricare quella pagina nel mio browser, dovevo trovarla nella cache di Google.)

Ecco la risposta breve:

curl http://curl.haxx.se/ca/cacert.pem -o ~/.rvm/usr/ssl/cert.pem

E hai finito.