web-dev-qa-db-fra.com

OmniAuth et Facebook: échec de la vérification du certificat

J'ai suivi Railscast # 235 pour essayer de configurer une authentification Facebook minimale.

J'ai d'abord configuré une authentification Twitter, comme l'a fait Ryan lui-même. Cela a parfaitement fonctionné.

Je suis ensuite passé à l'ajout d'une connexion Facebook. Cependant, après avoir autorisé l'application, la redirection vers /auth/facebook/callback échoue avec:

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

Je travaille sur localhost. Je n'ai configuré aucun SSL dans l'application. Qu'est-ce que je fais mal?

65
shmichael

Le vrai problème est que Faraday (qu'Omniauth/Oauth utilise pour ses appels HTTP) n'est pas ne définissait pas la variable ca_path pour OpenSSL. Au moins sur Ubuntu, la plupart des certificats racine sont stockés dans "/ etc/ssl/certs". Depuis Faraday n'est pas ne définissait pas cette variable (et n'a actuellement pas de méthode pour le faire), OpenSSL n'est pas n'a pas trouvé le certificat racine du certificat SSL de Facebook.

J'ai soumis une demande d'extraction à Faraday qui ajoutera le support pour cette variable et j'espère qu'ils introduiront bientôt ce changement. Jusque-là, vous pouvez monkeypatch faraday pour ressembler à this ou utiliser ma fourchette de Faraday . Après cela, vous devez spécifier la version 0.3.0 de la gemme OAuth2 dans votre Gemspec qui prend en charge le passage des options SSL à Faraday. Il ne vous reste plus qu'à passer à Faraday 0.6.1, qui prend en charge le passage de la variable ca_path et à passer à OmniAuth 0.2.2, qui possède les dépendances appropriées pour OAuth2. Vous pourrez ensuite résoudre correctement ce problème en ajoutant simplement ce qui suit à votre initialiseur Omniauth:

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

Donc, pour récapituler:

  1. Faraday doit être mis à jour pour prendre en charge SSL ca_path. Installer Faraday 0.6.1
  2. Votre application doit utiliser OAuth2 version 0.3.0. Vous devrez peut-être créer un omniauth car il a actuellement une dépendance de version mineure dans l'arborescence 0.2.x. Mise à niveau vers OmniAuth 0.2.2
  3. Modifiez l'initialiseur de votre fournisseur pour pointer vers le chemin du certificat de votre système ("/ etc/ssl/certs" sur Ubuntu et al)

Espérons que les prochaines versions de Faraday et d'Omniauth intégreront cette solution.

Merci à KirylP ci-dessus pour m'avoir mis sur la bonne voie.

74
Alex Kremer

J'avais ce problème et j'ai essayé d'utiliser l'argument: ca_path sans succès. Après avoir parcouru Github pendant un certain temps, je suis tombé sur une suggestion qui mentionnait l'utilisation de: ca_file et pointais directement vers la certification.

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 vous devez obtenir le chemin d'accès à vos fichiers de certification de systèmes (et à votre utilisation de Linux), tapez simplement à partir du terminal. Cela vous donnera un tas d'informations sur votre configuration SSL, y compris le chemin d'accès (reportez-vous à OPENSSLDIR). Vous devrez ajouter certs/ca-bundle.crt au chemin fourni.

open-ssl version -a
18
Emerson

Je suis sur Ubuntu 10.10 (Maverick) ... j'ai lutté environ 6 heures avant de le faire fonctionner, partageant mon expérience

  1. n'a pas essayé le patch singe
  2. essayé {: client_options => {: ssl => {: ca_path => "/ etc/ssl/certs"}} mais toujours pas fonctionné
  3. essayé Ruby 1.8.7 toujours pas fonctionné
  4. essayé différentes versions d'omniauth & faraday, toujours pas de chance.

La seule chose qui l'a fait fonctionner était la suite (merci Alex)

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

Géré pour passer par la vérification du certificat SSL comme il se doit. Mon projet utilise 37 ID de signaux pour l'intégration 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

Où 'CLIENT_ID', 'CLIENT_SECRET' vous pouvez obtenir sur 7signals.com et le fichier de paquets de certificats Gd_bundle.crt de - GoDaddy car 37 signaux utilisent leur autorité de certification.

7
KirylP

Si vous déployez sur Heroku, vous souhaitez pointer vers l'emplacement du fichier spécifique. Cela fonctionne pour moi (dans 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
Anand Iyer

J'ai résolu cela avec le bundle CA de: http://certifie.com/ca-bundle/

Et dans mon initialiseur Devise:

:client_options => { :ssl => { :ca_file => "#{Rails.root}/config/ca-bundle.crt" } } }
5
Palo Delinčák

On dirait qu'Omniauth utilise désormais une version plus récente de Faraday, ce qui explique pourquoi le patch singe ci-dessus ne fonctionnait pas pour moi. Je suis d'accord qu'il doit y avoir un meilleur moyen, mais pour toute autre personne qui a juste besoin de le faire fonctionner pour tester, voici une version mise à jour:

(créez un fichier dans votre répertoire initialiseurs avec le code suivant)

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
4
Zac Randles

toutes les solutions n'ont pas fonctionné pour moi, alors j'ai trouvé ça

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

rvm osx-ssl-certs update all

osx 10.8 Ruby 2.0.0 via rvm

4
antpaw

Modifier: vérifiez la réponse ci-dessous car elle est plus pertinente

Cela a fonctionné pour moi (correction avec l'aimable autorisation de https://github.com/jspooner ):

Créez un fichier dans le répertoire de votre initialiseur avec le patch singe suivant:

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
2
Jack Kinsella

J'utilise Faraday 0.6.1 et OAUTH2 (seul, pas enveloppé par quoi que ce soit). Cela a suffi à résoudre le problème pour moi (sur Gentoo, devrait fonctionner sur Ubunto)

Tourne ça

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

Dans ce

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

Je sais que cela semble trivial, mais assurez-vous que vous utilisez le bon protocole. J'ai continué à recevoir cette erreur, puis j'ai réalisé que j'essayais de me connecter via http. 1,5 heure perdue parce que je suis un idiot.

1
jhamm

Mon problème a été résolu en s'assurant que openSSL utilisait le bon répertoire de certificats:

Pour mon système (ubuntu64), c'était: ENV ['SSL_CERT_DIR'] = '/ usr/share/ca-certificate /'

Cela utilisait jruby-openssl avec JRuby 1.6.0

Je viens d'ajouter ce paramètre à development.rb

1
Daniel Honig

Sur Ubuntu, tout ce que j'avais à faire était de mettre à jour /environments/development.rb pour:

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

et alors:

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

wola!

0
jesal

J'ai rencontré une erreur similaire en utilisant RVM sur Mountain Lion. Il semble que Ruby ne trouve pas le certificat CA dont il a besoin pour autoriser la connexion SSL. Vous devez en installer un. Cette solution a fait l'affaire:

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

(Bien que je ne puisse pas réellement charger cette page dans mon navigateur, je devais la trouver dans le cache Google.)

Voici la réponse courte:

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

Et tu as fini.

0
Lachlan Cotter

Voici ce que j'ai fait pour vous aider si vous rencontrez spécifiquement un problème avec Leopard.

Mon certificat était ancien et devait être mis à jour. J'ai téléchargé ceci:

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

Puis remplacé mon certificat qui a été trouvé ici sur Leopard:

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

Rechargez tout ce que vous avez qui y accède et vous devriez être prêt à partir!

0
Musicalmindz

J'ai finalement trouvé un correctif pour Mountain Lion. Voir: http://coderwall.com/p/f4hyqw

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

Cela semble être un problème 1.9.x. Le retour au 1.8.7 a résolu le problème.

0
shmichael

Juste parce que les instructions étaient légèrement différentes pour ce qui a fonctionné pour moi, j'ai pensé ajouter mes 2 cents:

Je suis sur OS X Lion et j'utilise macports et rvm

J'ai installé curl-ca-bundle:

Sudo port install curl-ca-bundle

Ensuite, j'ai ajusté ma configuration omniauth comme suit:

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
Hortitude