Omniauth Service Unavailable Error for Twitter - ruby-on-rails

I am using omniauth and twitter login for my site. However, whenever I try to login, it gave this error:
Started GET "/auth/failure?message=service_unavailable" for 98.83.218.118 at 2011-11-12 11:27:58 -0500
Processing by SessionsController#failure as HTML
Parameters: {"message"=>"service_unavailable"}
The only clue I have is that it might be an SSL error.
However, I have no idea on how to debug the cause of the error.
Here is my current configuration for twitter:
Rails.application.config.middleware.use OmniAuth::Builder do
provider :twitter, 'REDACTED', 'REDACTED'
end

It looks like ssl issue in my project.
For development mode you can off ssl. Then you can work without this issue.
add this in develoment.rb:
OpenSSL::SSL::VERIFY_PEER = OpenSSL::SSL::VERIFY_NONE
And about how fix SSL certificates:
Twitter API SSL Root CA Certificate

I don't really like the solution suggested in at twitter dev support (as linked by Yahor Zhuchkou), which suggest downloading just a bunch of certificates from an unsecure server.
And while turning of verify peer will work in production that isn't really a solution. What you need to do is to point omniauth to the correct PEM file, which should contain something like, the Verisign Root Certificate which backs Twitter's own certificate (i:/C=US/O=VeriSign, Inc./OU=Class 3 Public Primary Certification Authority - G2/OU=(c) 1998 VeriSign, Inc. - For authorized use only/OU=VeriSign Trust Network):
-----BEGIN CERTIFICATE-----
MIIDAjCCAmsCEH3Z/gfPqB63EHln+6eJNMYwDQYJKoZIhvcNAQEFBQAwgcEx
CzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UE
CxMzQ2xhc3MgMyBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhv
cml0eSAtIEcyMTowOAYDVQQLEzEoYykgMTk5OCBWZXJpU2lnbiwgSW5jLiAt
IEZvciBhdXRob3JpemVkIHVzZSBvbmx5MR8wHQYDVQQLExZWZXJpU2lnbiBU
cnVzdCBOZXR3b3JrMB4XDTk4MDUxODAwMDAwMFoXDTI4MDgwMTIzNTk1OVow
gcExCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoG
A1UECxMzQ2xhc3MgMyBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1
dGhvcml0eSAtIEcyMTowOAYDVQQLEzEoYykgMTk5OCBWZXJpU2lnbiwgSW5j
LiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MR8wHQYDVQQLExZWZXJpU2ln
biBUcnVzdCBOZXR3b3JrMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDM
XtERXVxp0KvTuWpMmR9ZmDCOFoUgRm1HP9SFIIThbbP4pO0M8RcPO/mn+SXX
wc+EY/J8Y8+iR/LGWzOOZEAEaMGAuWQcRXfH2G71lSk8UOg013gfqLptQ5GV
j0VXXn7F+8qkBOvqlzdUMG+7AUcyM83cV5tkaWH4mx0ciU9cZwIDAQABMA0G
CSqGSIb3DQEBBQUAA4GBAFFNzb5cy5gZnBWyATl4Lk0PZ3BwmcYQWpSkU01U
bSuvDV1Ai2TT1+7eVmGSX6bEHRBhNtMsJzzoKQm5EWR0zLVznxxIqbxhAe7i
F6YM40AIOw7n60RzKprxaZLvcRTDOaxxp5EJb+RxBrO6WVcmeQD2+A2iMzAo
1KpYoJ2daZH9
-----END CERTIFICATE-----
(If you're using Ubuntu you may find it here: /etc/ssl/certs/Verisign_Class_3_Public_Primary_Certification_Authority_-_G2.pem )
Don't know why omniauth or ruby openssl implementation isn't finding this, but you can explicitly link to this pem file with the following option:
provider :twitter, 'REDACTED', 'REDACTED', {
:client_options => {:ca_file => '/etc/ssl/certs/Verisign_Class_3_Public_Primary_Certification_Authority_-_G2.pem'}
}

Related

Rails SSL certificate error on valid certificate

I have small Rails app that performs various checks on our platform and sends me an email in case of an issue. Everything was running fine until today i started getting alerts about the following error:
SSL_connect returned=1 errno=0 state=error: certificate verify failed (certificate has expired)
Now the problem is the certificate in question is valid, it gets automatically renewed (Let's encrypt) and this code has been untouched for a couple of years and never had any issues before and suddenly this started to happen.
The code that throws the exception:
def get_request url
uri = URI.parse(url)
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
#more than 10 seconds this is too slow
http.open_timeout = 10
http.read_timeout = 10
request = Net::HTTP::Get.new(uri.request_uri)
response = http.request(request)
if response.code.to_i == 200
return true
else
puts "Failed to GET #{url}: #{response.code.to_i}"
return false
end
end
If i open the site in the browser, it shows the secure connection without issues and shows that is using a valid certificate, furthermore if i check with certbot i get the following: Expiry Date: 2021-11-22 17:48:58+00:00 (VALID: 52 days) so clearly the certificate is valid, why suddenly rails is throwing a tantrum about it?
Note that i have restarted Nginx just in case, that didn't help.
Additional info: Ubuntu 16.04.5, OpenSSL 1.0.2g 1 Mar 2016, Rails 4.2, Ruby 2.6.5
EDIT:
This error also happens with a different url, which also has a valid certificate.
EDIT 2:
I've isolated the problem, it is related to Let's Encrypt DST Root CA X3 that has expired. A lot of people are dealing with this issue, i'll report my solution once i find one.
So after reading through this long thread of the Let's Encrypt community, the solution for my case ended up being to remove the DST Root CA X3 certificate:
sudo rm /usr/share/ca-certificates/mozilla/DST_Root_CA_X3.crt
sudo update-ca-certificates
After that no more errors from openssl.

Ruby - Connect with SSL and authenticate via client certificate - sslv3 alert bad certificate

I'm trying to connect a webcrawler that accesses a certain site via SSL and queries my data on that site. The authentication of this site is via a self-signed Digital Certificate. At the moment I want to access the site, I upload this certificate in .pfx format to my api, convert it to .pem, and when I try to access the site with this certificate, the response comes with status 403 (forbidden ).
However, when I try to access the site through a browser with the certificate in .pfx format I usually get it.
I already tried using Mechanize, and it worked for a while (until a few months ago it worked), but then it started to give the error:
SSL_connect returned = 1 errno = 0 state = SSLv3 read finished A: sslv3 alert bad certificate
The site is old, it does not receive updates frequently.
After that I already tried to use the net / http lib and the error persisted, I tried to use the httprb gem and lastly I tried with Faraday. All attempts ended either in that error quoted above or with the response status == 403.
What can I do to be able to connect? Is there something wrong with my script? Is it missing any information I need to get through?
Code:
# Faraday customs method:
class FaradayHttp
def with_openssl
system "openssl pkcs12 -in my-certificate-path -out certificate-output-path -nodes -password pass:certificate-password"
def cert_object
OpenSSL::X509::Certificate.new File.read("certificate-output-path")
end
# create PKey
def key_object
OpenSSL::PKey.read File.read("certificate-output-path")
end
faraday = Faraday::Connection.new 'https://example-site.com',
:ssl => {
certificate: cert_object,
private_key: key_object,
version: :SSLv3,
verify: false
}
faraday
end
end
# Controller that try to connect with the ssl server:
agent = FaradayHttp.new.with_openssl
page = agent.get '/login_path'
# mypki will prompt you for certificates
require 'mypki'
# faraday will use certificates from mypki
require 'faraday'
faraday = Faraday::Connection.new 'https://example-site.com'
faraday.get '/login_path'

ActionMailer SMTP "certificate verify failed"

I want to send emails from my Rails web application, and I do not want to disable TLS certificate verification. However for some reason, it always fails with "SSLv3 read server certificate B: certificate verify failed", even though the server certificate is valid.
I doubled checked with openssl s_client (using /etc/ssl/certs/ca-certificates.crt), and running the following in the rails console also works, delivering successfully.
smtp = Net::SMTP.new(host, port)
smtp.enable_tls
smtp.start("localhost", username, password, :login) do |smtp|
smtp.send_message msgstr, from, to
end
The server has Rails 4.2.6 and Ruby 2.3.0
config.action_mailer.smtp_setting = {
address:
port: 465,
user_name:
password:
authentication: :login,
openssl_verify_mode: OpenSSL::SSL::VERIFY_PEER,
enable_starttls_auto: false,
ssl: true
}
From the described behavior I am quite sure that peer verification has not been done in the console and that you need to explicitly set the certificate store for verifying peer certificates in your Rails configuration.
Why it "works" in the console and how to actually verify peers there:
The observation that it works from the console but does not from Rails code is caused by the fact that smtp.enable_tls in your console code does not force peer verification whereas your Rails configuration apparently does. Indeed, when you write the command to the console, you get the SSLContext printed out:
smtp.enable_tls
# => #<OpenSSL::SSL::SSLContext:0x000000064043d0 #cert=nil, #key=nil,
#client_ca=nil, #ca_file=nil, #ca_path=nil, #timeout=nil,
#verify_mode=nil, #verify_depth=nil, #renegotiation_cb=nil,
#verify_callback=nil, #cert_store=nil, #extra_chain_cert=nil,
#client_cert_cb=nil, #session_id_context=nil, #tmp_dh_callback=nil,
#session_get_cb=nil, #session_new_cb=nil, #session_remove_cb=nil,
#tmp_ecdh_callback=nil, #servername_cb=nil, #npn_protocols=nil,
#alpn_protocols=nil, #alpn_select_cb=nil, #npn_select_cb=nil>
Note that #verify_mode is nil so there is no peer verification enabled by default on the SSLContext.
To force peer verification in console, so that you can play with the SSL settings manually, you need to use a custom SSLContext and pass it to enable_tls:
ssl_context = Net::SMTP.default_ssl_context
ssl_context.set_params
smtp.enable_tls(ssl_context)
# => #<OpenSSL::SSL::SSLContext:0x000000063c27c8 #cert=nil, #key=nil,
#client_ca=nil, #ca_file=nil, #ca_path=nil, #timeout=nil,
#verify_mode=1, #verify_depth=nil, #renegotiation_cb=nil,
#verify_callback=nil, #cert_store=#<OpenSSL::X509::Store:0x00000002894408 #verify_callback=nil, #error=nil, #error_string=nil, #chain=nil, #time=nil>, #extra_chain_cert=nil,
#client_cert_cb=nil, #session_id_context=nil, #tmp_dh_callback=nil,
#session_get_cb=nil, #session_new_cb=nil, #session_remove_cb=nil,
#tmp_ecdh_callback=nil, #servername_cb=nil, #npn_protocols=nil,
#alpn_protocols=nil, #alpn_select_cb=nil, #npn_select_cb=nil>
Watch closely the differences: the SSLContext now has verify_mode set to 1 and has a certificate store for the verifications defined. This is (among other things) what the set_params method in SSLContext does.
How to configure the certificate store in Rails
Now, Rails does not call the set_params methods when constructing the SSLContext for SMTP connection. Instead, it sets the individual attributes on it according to the options (see here and here in the source code). You have properly configured Rails that you want to verify peer certificates but you have not configured a certificate store to verify peers against.
This can be done using the ca_file or ca_path options, so the following Rails configuration should work for you:
config.action_mailer.smtp_setting = {
...
ssl: true
enable_starttls_auto: false,
openssl_verify_mode: OpenSSL::SSL::VERIFY_PEER,
ca_file: "/etc/ssl/certs/ca-certificates.crt",
...
}
I have no idea why this is not properly documented in the Rails Guides...
This Rails configuration works for me (using Ruby 2.2.2 and Rails 5):
ActionMailer::Base.smtp_setting = {
...
enable_starttls_auto: true,
openssl_verify_mode: OpenSSL::SSL::VERIFY_PEER,
openssl_verify_depth: 3, # if your CA is a sub signer
ca_file: "/etc/ssl/certs/ca-certificates.crt",
...
}

Ruby verify the certificate of secure ldap server

I am using https://github.com/ruby-ldap/ruby-net-ldap (net-ldap) gem to verify the authenticity of a user in my rails app. But before passing data to the ldap server, I need to verify that I am talking with the same secure server.
Is there a workaround which allows me to verify the certificate in ruby
Additional details: (things I have tried)
The certificate which is passed on to me is same as the one I see when I run
openssl s_client -showcerts -connect "<host>:<port>" </dev/null 2>/dev/null|openssl x509 -outform PEM
I used http://www.ldapsoft.com/ to connect to client's server
Unless I add the certificate file given to me in Security > Manage server certificates, I get a warning saying unknown security certificate
I tried do it manually first in plain ruby (without gem)
But i get following error
test-ssl.rb:23:in `connect': SSL_connect returned=1 errno=0 state=SSLv3 read server certificate B: certificate verify failed (OpenSSL::SSL::SSLError)
Code:
cert_store = OpenSSL::X509::Store.new
cert_store.add_file "server-wildcard.crt"
io = TCPSocket.new("SECURELDAP.MYSITE.EDU","636")
ctx = OpenSSL::SSL::SSLContext.new
#ctx.cert = OpenSSL::X509::Certificate.new(File.read("server-wildcard.crt"))
#ctx.client_ca = OpenSSL::X509::Certificate.new(File.read("server-wildcard.crt"))
#ctx.ca_file = "server-wildcard.crt"
#ctx.ca_path = "./"
ctx.verify_mode = OpenSSL::SSL::VERIFY_PEER | OpenSSL::SSL::VERIFY_FAIL_IF_NO_PEER_CERT
ctx.cert_store = cert_store
conn = OpenSSL::SSL::SSLSocket.new(io, ctx)
conn.connect
I am posting my solution here for the sake of completeness.
net-ldap gem override to support certificate validation
https://gist.github.com/mintuhouse/9931865
Ideal Solution:
Maintain list of trusted root CAs on your server
(If you are lazy like me, have a cron job which will download (weekly maintained by curl) copy from http://curl.haxx.se/ca/cacert.pem)
Override Net::HTTP to always use this trusted certificate list
As of today (late 2016), ruby-net-ldap supports this upstream! However, tls_options needs to be passed with verify_mode set to a value other than the default VERIFY_NONE.
# optional: create/pass your own cert_store
cert_store = OpenSSL::X509::Store.new
cert_store.set_default_paths # or add your own CAdir, &c.
# attributes documented for OpenSSL::SSL::SSLContext are valid here
tls_options = {
verify_mode: OpenSSL::SSL::VERIFY_PEER
cert_store: cert_store
}
ldap = Net::LDAP.new(
:host => host,
:port => port,
:encryption => {
:method => :simple_tls, # could also be :start_tls
:tls_options => tls_options
}
)

OpenSSL problems using oAuth2 gem and facebook

So I've upgraded an app from rails 2.2 to 2.3.12 and my last remaining issue is the problem of facebook connect integration.
I am using the oauth2 gem for this and well I keep getting the following error
OpenSSL::SSL::SSLError (SSL_connect returned=1 errno=0 state=SSLv3 read server certificate B: certificate verify failed):
I've tried to follow the descriptions on the oauth2 wiki page just to end up with anohter error that was solved by forking the project and adapting the code. read here.
I do not have the issue on my development server but only in production.
my client code looks as follows
def client
ca_file = File.join('/etc/ssl/cacert.pem')
#client ||= OAuth2::Client.new( 'app_id', 'app_secret', {
:site => {
:url=>'https://graph.facebook.com',
:ssl=>{
:verify => OpenSSL::SSL::VERIFY_PEER,
:ca_file => ca_file
}
},
:adapter => :NetHttp
})
#client
end
I've confirmed about a hundred times now that my cacert.pem file is there and that
the rights are ok.
Any ideas on where to begin debugging are welcome.
SOLVED
I moved this site on to a new server running Debian 6.0 (sqeeze) instead of 5.0 (etch) and this solved my problem. My take on this is that I got a newer version of OpenSSL:
Debian 6.0: OpenSSL 0.9.8o 01 Jun 2010
Debian 5.0: OpenSSL 0.9.8g 19 Oct 2007
I can't guarantee that this was the issue but since it's now working with no code changes. I assume it is.

Resources