Railscast#235 に従い、最小限のFacebook認証を設定しようとしました。
ライアン自身が行ったように、私は最初にTwitter認証を設定しました。それは完璧に機能しました。
次に、Facebookログインの追加に進みました。ただし、アプリを承認した後、/auth/facebook/callback
へのリダイレクトは次のように失敗します。
SSL_connect returned=1 errno=0 state=SSLv3 read server certificate B: certificate verify failed
ローカルホストで作業しています。アプリ内でSSLを設定しませんでした。私は何を間違えていますか?
本当の問題は、ファラデー(Omniauth/OauthがHTTP呼び出しに使用する) ではない OpenSSLのca_path変数を設定していませんでした。少なくともUbuntuでは、ほとんどのルート証明書は「/ etc/ssl/certs」に保存されます。ファラデー以来 ではない この変数を設定していませんでした (そして、現在そうする方法がありません)、OpenSSL ではない FacebookのSSL証明書のルート証明書が見つかりませんでした。
プルリクエストをファラデーに提出した これにより、この変数のサポートが追加され、できればすぐにこの変更を取り込むことができます。それまでは、ファラデーをモンキーパッチして this のようにするか、 my fork of Faraday を使用します。その後、FaradayへのSSLオプションの受け渡しをサポートするGemspecでOAuth2 gemのバージョン0.3.0を指定する必要があります。 ここで必要なのは、ca_path変数の受け渡しをサポートするFaraday 0.6.1へのアップグレードと、OAuth2の適切な依存関係を持つOmniAuth 0.2.2へのアップグレードだけです。その後、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とOmniauthの両方の次のリリースにこのソリューションが組み込まれることを願っています。
私を正しい道に導いてくれた上記のKirylPに感謝します。
私はこの問題を抱えていて、成功せずに: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を使用している場合)、ターミナルから入力するだけです。これにより、パス(OPENSSLDIRを参照)など、SSLセットアップに関する一連の情報が得られます。指定されたパスにcerts/ca-bundle.crtを追加する必要があります。
open-ssl version -a
私はubuntu 10.10(Maverick)にいます...仕事を始める6時間前に苦労し、経験を共有しました
動作するようになった唯一のことは次のことでした(アレックスに感謝)
if Rails.env.development?
OpenSSL::SSL::VERIFY_PEER = OpenSSL::SSL::VERIFY_NONE
end
SSL証明書の検証を行う必要がありました。私のプロジェクトでは、Basecamp統合に37signals IDを使用しています(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
ここで、「CLIENT_ID」、「CLIENT_SECRET」は 7signals.com で取得でき、証明書バンドルファイルGd_bundle.crtから- GoDaddy 37シグナルがCAを使用しているため。
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
私はこれをCAバンドルで解決しました: http://certifie.com/ca-bundle/
そして、私のDeviseイニシャライザーでは:
:client_options => { :ssl => { :ca_file => "#{Rails.root}/config/ca-bundle.crt" } } }
Omniauthは現在、新しいバージョンのFaradayを使用しているように見えます。これは、上記のモンキーパッチが機能しなかった理由を説明しています。もっと良い方法がなければならないことに同意しますが、テストするためにそれを機能させる必要がある他の人のために、更新されたバージョンがあります:
(次のコードを使用して、initializersディレクトリにファイルを作成します)
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
すべての解決策が私にとってうまくいかなかったので、私はこれを見つけました
http://railsapps.github.io/openssl-certificate-verify-failed.html
rvm osx-ssl-certs update all
osx 10.8 Ruby 2.0.0 rvm経由
編集:より関連性があるため、以下の回答を確認してください
これは私のために働いた( 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
私は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' })
これは簡単に聞こえますが、正しいプロトコルを使用していることを確認してください。このエラーが発生し続け、http経由で接続しようとしていることに気付きました。私はバカだから1.5時間も無駄になりました。
私の問題は、openSSLが正しい証明書ディレクトリを使用していることを確認することで解決しました。
私のシステム(ubuntu64)の場合、これはENV ['SSL_CERT_DIR'] = '/ usr/share/ca-certificates /'でした。
これはjruby-opensslをJRuby 1.6.0で使用していました
この設定をdevelopment.rbに追加しました
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
わあ!
Mountain LionでRVMを使用すると、同様のエラーが発生しました。 Rubyは、SSL接続を許可するために必要なCA証明書を見つけることができないようです。インストールする必要があります。このソリューションは、トリックを行いました。
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
これで完了です。
Leopardで特に問題を抱えている場合に私が役立てたのは次のとおりです。
私の証明書は古く、更新する必要がありました。これをダウンロードしました:
http://curl.haxx.se/ca/cacert.pem
次に、Leopardでここで見つかった証明書を置き換えました。
/usr/share/curl/curl-ca-bundle.crt
アクセスしているものは何でもリロードしてください。
やっとMountain Lionの修正が見つかりました。参照: http://coderwall.com/p/f4hyqw
rvm pkg install openssl
rvm reinstall 1.9.3 --with-openssl-dir=$rvm_path/usr
これは1.9.xの問題のようです。 1.8.7に戻すと、問題が修正されました。
私のために働いたもののために指示がわずかに異なっていたという理由だけで、私は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