developer tip

OmniAuth 및 Facebook : 인증서 확인 실패

copycodes 2020. 11. 17. 08:21
반응형

OmniAuth 및 Facebook : 인증서 확인 실패


저는 Railscast # 235 를 따라 최소한의 Facebook 인증을 설정했습니다.

Ryan 자신이 한 것처럼 먼저 Twitter 인증을 설정했습니다. 완벽하게 작동했습니다.

그런 다음 Facebook 로그인을 추가했습니다. 그러나 앱을 승인 한 후 리디렉션 /auth/facebook/callback은 다음과 같이 실패합니다.

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

나는 localhost에서 일하고 있습니다. 앱 내에서 SSL을 설정하지 않았습니다. 내가 도대체 ​​뭘 잘못하고있는 겁니까?


실제 문제는 Faraday (Omniauth / Oauth가 HTTP 호출에 사용) OpenSSL에 대해 ca_path 변수를 설정하지 않았다는 것입니다. 적어도 우분투에서는 대부분의 루트 인증서는 "/ etc / ssl / certs"에 저장됩니다. Faraday 가이 변수를 설정 하지 않았기 때문에 (현재이를위한 방법 이 없음 ) OpenSSL Facebook의 SSL 인증서에 대한 루트 인증서를 찾지 못했습니다.

나는 한 패러데이에 끌어 오기 요청 제출 이 변수에 대한 지원을 추가하고 잘하면 그들이 곧 변화를 가져옵니다. 그 때까지, 당신처럼 보이도록 패러데이 monkeypatch 수 있습니다 사용하거나 패러데이의 내 포크 . 그런 다음, SSL 옵션을 Faraday로 전달하는 것을 지원하는 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

요약하자면 :

  1. SSL ca_path를 지원하려면 Faraday를 업데이트해야합니다. Faraday 0.6.1 설치
  2. 앱은 OAuth2 버전 0.3.0을 사용해야합니다. 현재 0.2.x 트리에 부 버전 종속성이 있기 때문에 omniauth를 포크해야 할 수도 있습니다. OmniAuth 0.2.2로 업그레이드
  3. 시스템의 인증서 경로를 가리 키도록 공급자 이니셜 라이저를 수정합니다 (Ubuntu 등에서는 "/ etc / ssl / certs").

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를 사용하는 경우)의 경로를 얻으려면 터미널에서 입력하기 만하면됩니다. 경로를 포함하여 SSL 설정에 대한 많은 정보를 제공합니다 (OPENSSLDIR 참조). 제공된 경로에 certs / ca-bundle.crt를 추가해야합니다.

open-ssl version -a

저는 우분투 10.10 (Maverick)을 사용 중입니다 ... 출근 6 시간 전에 고생하면서 경험을 공유했습니다.

  1. 원숭이 패치를 시도하지 않았다
  2. {: client_options => {: ssl => {: ca_path => "/ etc / ssl / certs"}} 시도했지만 여전히 작동하지 않습니다.
  3. 루비 1.8.7을 시도했지만 여전히 작동하지 않습니다.
  4. omniauth 및 faraday의 다른 버전을 시도했지만 여전히 운이 없습니다.

작동하게 만든 유일한 것은 다음과 같습니다. (Alex에게 감사드립니다)

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'에서 37signals.com 에서 얻을 수 있으며 37signals 가 CA를 사용하고 있기 때문에 GoDaddy의 인증서 번들 파일 gd_bundle.crt얻을 수 있습니다 .


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

http://certifie.com/ca-bundle/ 에서 CA 번들로이 문제를 해결했습니다 .

그리고 내 Devise 이니셜 라이저에서 :

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

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

모든 솔루션이 저에게 효과가 없었습니다.

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

rvm osx-ssl-certs update all

rvm을 통한 osx 10.8 루비 2.0.0


편집 : 더 관련성이 있으므로 아래 답변을 확인하십시오.

이것은 나를 위해 일했습니다 ( https://github.com/jspooner의 수정 제공 ).

다음 monkey 패치를 사용하여 이니셜 라이저의 디렉토리에 파일을 만듭니다.

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를 사용하고 있습니다 (단독, 아무것도 감싸지 않음). 이것은 저에게 문제를 해결하기에 충분했습니다 (젠투에서는 우분 토에서 작동해야합니다)

이것을 돌려

  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' })

내 문제는 openSSL이 올바른 인증서 디렉토리를 사용하고 있는지 확인하여 해결되었습니다.

내 시스템 (ubuntu64)의 경우 : ENV [ 'SSL_CERT_DIR'] = '/ usr / share / ca-certificates /'

This was using jruby-openssl with JRuby 1.6.0

I just added this setting to development.rb


I know this sounds trivial, but make sure you are using the right protocol. I kept getting this error and then realized that I was trying to connect via http. 1.5 hours wasted because I am an idiot.


This seems to be a 1.9.x issue. Reverting to 1.8.7 fixed the issue.


Here's what I did that helped if you are specifically having a problem on Leopard.

My cert was old and needed to be updated. I downloaded this:

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

Then replaced my cert which was found here on Leopard:

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

Reload whatever you have that's accessing it and you should be good to go!


Just because instructions were a slight bit different for what worked for me, I thought I add my 2 cents:

I'm on OS X Lion and using macports and rvm

I installed curl-ca-bundle:

sudo port install curl-ca-bundle

Then I adjusted my omniauth config to be this:

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

On Ubuntu, all I had to do was update /environments/development.rb to:

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

and then:

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

wola!


I finally found a fix for Mountain Lion. See: http://coderwall.com/p/f4hyqw

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

I encountered a similar error using RVM on Mountain Lion. It seems that Ruby can't find the CA certificate it needs to authorise the SSL connection. You need to install one. This solution did the trick:

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

(Although I couldn't actually load that page in my browser, I had to find it in the Google cache.)

Here's the short answer:

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

And you're done.

참고URL : https://stackoverflow.com/questions/3977303/omniauth-facebook-certificate-verify-failed

반응형