Question
Fix OpenSSL Certificate Verify Failed in Ruby on Rails
Question
I am using Authlogic-Connect to provide third-party sign-ins. After running the required migrations, Twitter, Google, and Yahoo logins work, but Facebook login raises this exception:
SSL_connect returned=1 errno=0 state=SSLv3 read server certificate B: certificate verify failed
The development log shows:
OpenSSL::SSL::SSLError (
SSL_connect returned=1 errno=0 state=SSLv3 read server certificate B: certificate verify failed
):
app/controllers/users_controller.rb:37:in `update'
What does this certificate verification error mean, and how can it be diagnosed and fixed safely in a Ruby on Rails application?
Short Answer
This error occurs when Ruby/OpenSSL connects to an HTTPS service but cannot prove that the server certificate is trustworthy. You will learn how TLS certificate verification works, why one provider can fail while others work, how to inspect the failing certificate chain, and how to correct the trusted CA configuration without disabling security.
Concept
When a Ruby application makes an HTTPS request, OpenSSL performs two jobs:
- It encrypts traffic between the application and the remote server.
- It verifies that the remote server is really the service it claims to be.
For verification, the server sends a certificate and usually one or more intermediate certificates. OpenSSL attempts to build a chain from that certificate to a trusted certificate authority (CA) in Ruby's configured CA bundle or CA directory.
certificate verify failed means that this trust check could not be completed. Encryption may be available, but Ruby refuses the connection because it cannot safely authenticate the server.
Common reasons include:
- The operating system or Ruby installation has an old or missing CA bundle.
- Ruby/OpenSSL is configured to look in the wrong CA file or directory.
- The remote service sends an incomplete certificate chain.
- A corporate proxy intercepts HTTPS and presents its own certificate, whose CA is not trusted by Ruby.
- The machine date and time are incorrect, so an otherwise valid certificate appears expired or not yet valid.
The text state=SSLv3 is from OpenSSL's internal, older-style state label. It does not by itself prove that the application is using the obsolete SSLv3 protocol. The important part is certificate verify failed.
Mental Model
Think of HTTPS as entering a secured office building.
- Encryption is the locked conversation inside the building.
- The server certificate is the receptionist's ID card.
- Trusted CA certificates are the list of organizations allowed to issue valid ID cards.
Ruby checks whether the receptionist's ID was issued through a trusted chain of organizations. If a link is missing, expired, or unknown, Ruby does not enter—even if the receptionist has an ID card and the door can be locked.
Disabling certificate verification is like accepting any ID without checking it. It may make the error disappear, but it also makes impersonation attacks possible.
Syntax and Examples
Ruby commonly raises this exception when an HTTPS client verifies a peer certificate:
require "net/http"
require "uri"
uri = URI("https://example.com/")
response = Net::HTTP.get_response(uri)
puts response.code
By default, a correctly configured modern Ruby HTTPS client verifies the server certificate. If OpenSSL cannot find a trusted path from example.com's certificate to a trusted CA, the request raises OpenSSL::SSL::SSLError.
You can inspect which CA locations Ruby/OpenSSL knows about:
require "openssl"
puts OpenSSL::X509::DEFAULT_CERT_FILE
puts OpenSSL::X509::DEFAULT_CERT_DIR
To inspect a remote certificate chain from a terminal, use OpenSSL:
openssl s_client -connect api.example.com:443 -servername api.example.com -showcerts </dev/null
Look near the end of the output for Verify return code. A result of 0 (ok) means the OpenSSL command was able to verify the chain using its current trust store. Test the actual hostname and port used by the failing OAuth or API request, not a placeholder hostname.
Do not use this as a permanent fix:
# Unsafe: accepts an untrusted or impersonated server certificate.
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
The correct solution is to repair the trust chain or CA configuration.
Step by Step Execution
Consider this simplified HTTPS request:
require "net/http"
require "uri"
uri = URI("https://login.example.test/token")
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_PEER
response = http.get(uri.request_uri)
puts response.code
Execution proceeds as follows:
URI(...)separates the hostname (login.example.test), port (443by default), and request path (/token).Net::HTTP.newprepares a network client for that host and port.use_ssl = truetells the client to make a TLS-protected connection.VERIFY_PEERrequires the server certificate to be validated against trusted CAs. This is the secure setting.http.getstarts the TLS handshake before sending the HTTP request.- The server sends its certificate chain.
- OpenSSL checks signatures, dates, hostname, certificate purpose, and whether the chain ends at a trusted CA.
- If a required CA or intermediate certificate is unavailable or invalid, OpenSSL raises
OpenSSL::SSL::SSLError. The HTTP request is never sent.
This explains why the error can appear on a controller line: that line probably triggers an OAuth token exchange or profile request, but the underlying failure happens during the HTTPS connection.
Real World Use Cases
Certificate verification is used whenever an application calls an HTTPS service, including:
- OAuth sign-in: Exchanging an authorization code for an access token or fetching a user profile from an identity provider.
- Payment APIs: Verifying the identity of a payment gateway before sending payment details.
- Webhook delivery: Sending signed event data to another service over authenticated HTTPS.
- Background jobs: Downloading feeds, calling partner APIs, or uploading files to cloud storage.
- Internal services: Connecting a Rails app to company APIs that use certificates issued by an internal CA.
If Twitter or Google works while another provider fails, the application can probably make HTTPS requests generally. The difference may be the failing provider's certificate chain, hostname, endpoint, or the particular CA needed to validate it.
Real Codebase Usage
In a real Rails codebase, certificate errors are usually handled by fixing deployment configuration rather than changing controller code.
Typical practices include:
- Keep OS CA certificates current. Install or update the system
ca-certificatespackage according to the operating system's documented process. - Use a maintained Ruby and OpenSSL build. Older runtime installations may ship with outdated trust-store paths or old root certificates.
- Configure the CA bundle explicitly when necessary. In containers or custom Ruby builds, set the runtime's CA file/path using the supported deployment configuration, rather than hard-coding a random certificate file in application logic.
- Add a private CA only when required. If an organization uses HTTPS inspection or internal certificates, install the organization's root CA into the trusted store through approved infrastructure tooling.
- Log safe diagnostic details. Record the target hostname, exception class, and deployment environment. Do not log access tokens, authorization codes, or secrets.
- Use retries carefully. Retrying can help transient network failures, but it does not fix an untrusted certificate. Treat certificate failures as configuration or server-chain problems.
A useful separation is: application code requests https://service.example/...; platform configuration provides the CA trust store that lets OpenSSL verify that service.
Common Mistakes
Disabling verification
# Do not use as a production fix.
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
This bypasses identity verification and can expose OAuth credentials or user data to a man-in-the-middle attacker. Fix the CA bundle, chain, proxy certificate, clock, or remote server configuration instead.
Assuming errno=0 means nothing is wrong
errno=0 means there was no ordinary operating-system socket error reported. The TLS verification failed at a higher layer, so the connection is still unusable.
Treating SSLv3 in the message as the root cause
The state text is not enough to diagnose the active protocol version. Focus first on the explicit verification failure. Use current Ruby/OpenSSL tooling to inspect supported and negotiated TLS versions if protocol compatibility is actually suspected.
Updating only the application gem
Updating an OAuth library may be useful for endpoint or protocol changes, but it does not automatically update the operating system's trusted CA certificates. Check both application dependencies and the server's CA store.
Testing only in a browser
A browser can have a different trust store and may fetch missing intermediates automatically. Test from the same server, container, and Ruby runtime that runs the Rails application.
Installing a certificate without validating its source
Do not download and trust a certificate from an unverified webpage. Obtain private CA certificates through the service owner or your organization's approved security process.
Comparisons
| Situation | What it means | Appropriate response |
|---|---|---|
VERIFY_PEER succeeds | The server chain reaches a trusted CA and passes checks. | Keep verification enabled. |
VERIFY_PEER fails | Ruby cannot establish trust in the server certificate. | Inspect the chain, CA store, proxy, and system clock. |
VERIFY_NONE succeeds | The connection can be encrypted, but the server identity was not checked. | Do not treat this as a fix; it is insecure. |
| Browser works, Ruby fails | Browser and Ruby may use different CA stores or chain-building behavior. | Test with the deployed Ruby/OpenSSL environment. |
| One OAuth provider fails | The failing endpoint may use a different chain or CA, or be affected by a proxy rule. | Inspect the exact failing hostname and endpoint. |
| Related error | Typical meaning |
|---|---|
certificate verify failed | The trust chain, dates, hostname, or trusted CA validation failed. |
hostname does not match the server certificate | The certificate does not identify the requested hostname. |
certificate has expired | The server certificate, intermediate, or local clock is outside its valid date range. |
unable to get local issuer certificate | The local trust store lacks a needed trusted CA or intermediate path. |
Cheat Sheet
OpenSSL::SSL::SSLErroris Ruby's TLS/SSL error class.certificate verify failedmeans Ruby could not trust the remote server certificate.- Keep peer verification enabled:
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_PEER
- Check Ruby's default CA locations:
require "openssl"
puts OpenSSL::X509::DEFAULT_CERT_FILE
puts OpenSSL::X509::DEFAULT_CERT_DIR
- Inspect the exact remote endpoint from the affected host:
openssl s_client -connect host.example:443 -servername host.example -showcerts </dev/null
-
Check these first:
- System date and time
- OS/Ruby CA bundle availability and freshness
- Complete server certificate chain
- Corporate HTTPS-inspection proxy
- Correct hostname and endpoint
-
Never permanently fix the issue with
OpenSSL::SSL::VERIFY_NONE.
FAQ
Why does only one login provider fail with a certificate error?
Each provider can use different hostnames, certificate chains, and CAs. A missing or outdated trust entry may affect one endpoint while other HTTPS requests still work.
Is state=SSLv3 proof that my application uses SSLv3?
No. It is commonly an OpenSSL state-string detail in older error output. The explicit problem is certificate verification. Check negotiated protocol details separately if needed.
Can I set VERIFY_NONE temporarily to make OAuth work?
It may bypass the error, but it disables server identity checks and is unsafe. Use it neither as a production fix nor as a substitute for diagnosis.
How do I know whether the problem is on my server or the remote service?
Run openssl s_client from the same machine or container using the exact hostname. Also compare results with a current environment. A failing public chain may indicate a remote configuration issue; a failure only in your environment often indicates a local CA or proxy issue.
Could an incorrect system clock cause this error?
Yes. Certificates have validity dates. A clock that is far in the past or future can make valid certificates appear invalid.
Does updating Rails fix certificate verification failures?
Not necessarily. Rails may be unrelated. The relevant components are the HTTP client, Ruby/OpenSSL build, operating system CA store, network proxy, and the remote server's certificate chain.
What should I provide when reporting the issue to an API provider?
Provide the hostname, timestamp, OpenSSL verification result, and whether the issue reproduces from another current environment. Do not include OAuth tokens, client secrets, or authorization codes.
Mini Project
Description
Build a small Ruby command-line HTTPS certificate checker. It connects to a hostname using peer verification and reports whether the server certificate is trusted. This mirrors the TLS stage that occurs before an OAuth client can call a provider API.
Goal
Verify an HTTPS endpoint securely and print useful certificate details or a clear verification error.
Requirements
Use Ruby's Net::HTTP and OpenSSL libraries.
Require a hostname argument, such as ruby check_https.rb example.com.
Connect using HTTPS with OpenSSL::SSL::VERIFY_PEER.
Print the HTTP status and certificate subject when verification succeeds.
Catch OpenSSL::SSL::SSLError and print a safe diagnostic message.
Keep learning
Related questions
Add a Default Value to an Existing Column in a Rails Migration
Learn how to add or change a default value on an existing database column using Rails Active Record migrations safely.
Calling a Class Method from an Instance in Ruby
Learn how to call a class method from an instance in Ruby using self.class, with examples, pitfalls, and practical usage patterns.
Calling an Overridden Monkey-Patched Method in Ruby
Learn how to call the original method when monkey patching in Ruby, including alias_method patterns, examples, pitfalls, and practical usage.