ruby on rails - OmniAuth y Facebook: verificación de certificado fallida
ruby-on-rails railscasts (18)
El hecho de que las instrucciones fueran un poco diferentes para lo que funcionó para mí, pensé que agregué mis 2 centavos:
Estoy en OS X Lion y uso macports y rvm
Instalé curl-ca-bundle:
sudo port install curl-ca-bundle
Luego ajusté mi configuración de omniauth para que sea esto:
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
Esta pregunta ya tiene una respuesta aquí:
Seguí Railscast # 235 para intentar configurar una mínima autenticación de Facebook.
Primero configuré una autenticación de Twitter, como lo hizo Ryan mismo. Eso funcionó a la perfección.
Luego pasé a agregar un inicio de sesión de Facebook. Sin embargo, después de autorizar la aplicación, la redirección a /auth/facebook/callback
falla con:
SSL_connect returned=1 errno=0 state=SSLv3 read server certificate B: certificate verify failed
Estoy trabajando en localhost. No configuré ningún SSL dentro de la aplicación. ¿Qué estoy haciendo mal?
El verdadero problema es que Faraday (que Omniauth / Oauth usa para sus llamadas HTTP) no estaba configurando la variable ca_path para OpenSSL. Al menos en Ubuntu, la mayoría de los certificadores de raíz se almacenan en "/ etc / ssl / certs". Como Faraday no está configurando esta variable (y actualmente no tiene un método para hacerlo) , OpenSSL no estaba buscando el certificado raíz para el certificado SSL de Facebook.
He enviado una solicitud de extracción a Faraday que agregará soporte para esta variable y es de esperar que aprovechen este cambio pronto. Hasta entonces, puedes hacer un parche en el tablero de Faraday para que se vea así o usar mi tenedor de Faraday . Después de eso, debe especificar la versión 0.3.0 de la gema OAuth2 en su Gemspec que admite el paso de las opciones SSL a Faraday. Todo lo que necesita hacer ahora es actualizar a Faraday 0.6.1, que admite el paso de la variable ca_path y actualizar a OmniAuth 0.2.2, que tiene las dependencias adecuadas para OAuth2. Entonces podrá corregir este problema de manera adecuada agregando lo siguiente a su inicializador Omniauth:
Rails.application.config.middleware.use OmniAuth::Builder do
provider :facebook, FACEBOOK_KEY, FACEBOOK_SECRET, {:client_options => {:ssl => {:ca_path => "/etc/ssl/certs"}}}
end
Entonces, para recapitular:
-
Faraday debe actualizarse para admitir SSL ca_path.Instalar Faraday 0.6.1 -
Tu aplicación necesita usar OAuth2 versión 0.3.0.Es posible que tenga que bifurcar omniauth ya que actualmente tiene una dependencia de versión menor en el árbol 0.2.x.Actualizar a OmniAuth 0.2.2 - Modifique su inicializador de proveedor para que apunte a la ruta del certificado de su sistema ("/ etc / ssl / certs" en Ubuntu et al)
Esperemos que los próximos lanzamientos de Faraday y Omniauth incorporen esta solución.
Gracias a KirylP más arriba por ponerme en el camino correcto.
En Ubuntu, todo lo que tuve que hacer fue actualizar /environments/development.rb a:
Rails.application.config.middleware.use OmniAuth::Builder do
provider :facebook, FACEBOOK_KEY, FACEBOOK_SECRET, {:client_options => {:ssl => {:ca_path => "/etc/ssl/certs"}}}
end
y entonces:
cd /etc/ssl/certs
sudo wget http://curl.haxx.se/ca/cacert.pem
Wola!
Encontré un error similar al usar RVM en Mountain Lion. Parece que Ruby no puede encontrar el certificado de CA que necesita para autorizar la conexión SSL. Necesitas instalar uno. Esta solución hizo el truco:
http://fredwu.me/post/28834446907/fix-openssl-error-on-mountain-lion-and-rvm
(Aunque no podía cargar esa página en mi navegador, tenía que encontrarla en la memoria caché de Google).
Aquí está la respuesta corta:
curl http://curl.haxx.se/ca/cacert.pem -o ~/.rvm/usr/ssl/cert.pem
Y tu estas listo.
Estaba teniendo este problema y traté de usar el argumento: ca_path sin éxito. Después de mirar a través de Github por un tiempo, encontré una sugerencia que mencionaba usar: ca_file y apuntaba directamente a la certificación.
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
Si necesita obtener la ruta a los archivos de certificación de su sistema (y su uso de linux) simplemente escriba desde la terminal. Esto le dará un montón de información sobre su configuración de SSL, incluida la ruta (consulte OPENSSLDIR). Deberá agregar certs / ca-bundle.crt a la ruta proporcionada.
open-ssl version -a
Esto es lo que hice que ayudó si tienes un problema específico con Leopard.
Mi certificado era viejo y necesitaba ser actualizado. Descargué esto:
http://curl.haxx.se/ca/cacert.pem
Luego reemplacé mi certificado que se encontró aquí en Leopard:
/usr/share/curl/curl-ca-bundle.crt
Recarga lo que tengas que esté accediendo a él y ¡deberías estar listo!
Esto parece ser un problema 1.9.x. Revertir a 1.8.7 solucionó el problema.
Estoy en Ubuntu 10.10 (Maverick) ... luché unas 6 horas antes de que funcionara, compartiendo mi experiencia
- no intenté el parche de mono
- intenté {: client_options => {: ssl => {: ca_path => "/ etc / ssl / certs"}} pero aún no funcionó
- intentado ruby 1.8.7 todavía no funcionó
- intenté diferentes versiones de omniauth y faraday, todavía no tuve suerte.
Lo único que lo hizo funcionar fue seguir (gracias Alex)
if Rails.env.development?
OpenSSL::SSL::VERIFY_PEER = OpenSSL::SSL::VERIFY_NONE
end
Estoy usando Faraday 0.6.1 y OAUTH2 (solo, no envuelto por nada). Esto fue suficiente para resolver el problema para mí (en Gentoo, debería funcionar en Ubunto)
Convertir esto
client = OAuth2::Client.new(FACEBOOK_API_KEY, FACEBOOK_API_SECRET, :site => FACEBOOK_API_SITE)
Dentro de esto
client = OAuth2::Client.new(FACEBOOK_API_KEY, FACEBOOK_API_SECRET, :site => FACEBOOK_API_SITE, :ssl => {:ca_path => ''/etc/ssl/certs'' })
Finalmente encontré una solución para Mountain Lion. Ver: http://coderwall.com/p/f4hyqw
rvm pkg install openssl
rvm reinstall 1.9.3 --with-openssl-dir=$rvm_path/usr
Lo resolví con CA bundle desde: http://certifie.com/ca-bundle/
Y en mi inicializador de Devise:
:client_options => { :ssl => { :ca_file => "#{Rails.root}/config/ca-bundle.crt" } } }
Logré pasar por la verificación de certificado SSL como debe ser. Mi proyecto usa 37signals ID para la integración de 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
Donde ''CLIENT_ID'', ''CLIENT_SECRET'' puede obtener 37signals.com y los certificados agrupan el archivo gd_bundle.crt de GoDaddy porque 37signals están usando su CA.
Mi problema se resolvió asegurándome de que openSSL usaba el directorio correcto de certificados:
Para mi sistema (ubuntu64) esto fue: ENV [''SSL_CERT_DIR''] = ''/ usr / share / ca-certificates /''
Esto estaba usando jruby-openssl con JRuby 1.6.0
Acabo de agregar esta configuración a development.rb
Parece que Omniauth ahora usa una versión más nueva de Faraday, lo que explica por qué el parche de mono anterior no funcionaba para mí. Estoy de acuerdo en que debe haber una manera mejor, pero para cualquier otra persona que solo necesite que funcione para probar, aquí hay una versión actualizada:
(crea un archivo en tu directorio de inicializadores con el siguiente código)
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
Sé que esto suena trivial, pero asegúrate de estar usando el protocolo correcto. Seguí recibiendo este error y luego me di cuenta de que estaba tratando de conectarme a través de http. 1.5 horas perdidas porque soy un idiota.
Si se está implementando en Heroku, quiere señalar la ubicación del archivo específico. Esto funciona para mí (en 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
todas las soluciones no funcionaron para mí, entonces he encontrado esto
http://railsapps.github.io/openssl-certificate-verify-failed.html
rvm osx-ssl-certs update all
osx 10.8 ruby 2.0.0 vía rvm
Editar: compruebe la respuesta a continuación, ya que es más relevante
Esto funcionó para mí (solución cortesía de https://github.com/jspooner ):
Crea un archivo en el directorio de tu inicializador con el siguiente parche de mono:
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