Guide · 3 min read

Is my SSL certificate configured correctly?

Short answer: it is configured correctly when the certificate is trusted (full chain), covers every name you use (with and without www), renews automatically well before expiry, only TLS 1.2 and 1.3 are enabled, every http:// request redirects to https://, and HSTS is set. The padlock alone only proves the first point.

Updated · HackGrade

Quick steps

  1. Check the chain is trusted. Open the site in a private window on a phone and a desktop; no warning should appear.
  2. Check the names. The certificate must list both yourdomain.com and www.yourdomain.com if you use both.
  3. Check expiry and renewal. Read notAfter and test that automatic renewal works.
  4. Check TLS versions. Allow only TLS 1.2 and TLS 1.3.
  5. Check the redirect. http:// must redirect permanently to https://.
  6. Check HSTS. Send Strict-Transport-Security once HTTPS works everywhere.

1. A trusted, complete chain

Servers must send the intermediate certificate too. A missing intermediate often works on desktop browsers but fails on phones and API clients.

Terminal
openssl s_client -connect yourdomain.com:443 -servername yourdomain.com -showcerts </dev/null 2>/dev/null | grep -E 's:|i:|Verify return'

Look for Verify return code: 0 (ok). In nginx, ssl_certificate should point to the full-chain file (for Let’s Encrypt: fullchain.pem, not cert.pem).

2. Every name is covered

Terminal
openssl s_client -connect yourdomain.com:443 -servername yourdomain.com </dev/null 2>/dev/null \
  | openssl x509 -noout -ext subjectAltName

3. Expiry and automatic renewal

Terminal
openssl s_client -connect yourdomain.com:443 -servername yourdomain.com </dev/null 2>/dev/null \
  | openssl x509 -noout -enddate
sudo certbot renew --dry-run   # if you use certbot

HackGrade flags a certificate as medium risk within 21 days of expiry, high within 14 days, and critical once it has expired or isn’t trusted.

4. Only TLS 1.2 and 1.3

nginx
ssl_protocols TLSv1.2 TLSv1.3;
Apache
SSLProtocol -all +TLSv1.2 +TLSv1.3

Test that an old version is refused (the command should fail to connect):

Terminal
openssl s_client -connect yourdomain.com:443 -servername yourdomain.com -tls1_1 </dev/null

5. HTTP redirects to HTTPS

nginx
server {
    listen 80;
    server_name yourdomain.com www.yourdomain.com;
    return 301 https://$host$request_uri;
}
.htaccess
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

6. HSTS

Once every page and subdomain works over HTTPS, add Strict-Transport-Security. Read the HSTS guide first: start with a short max-age and raise it. Then fix any mixed content.

Frequently asked questions

Is a free certificate (Let’s Encrypt) less secure than a paid one?

No. The encryption is the same. Paid certificates differ in validation type, support and warranty, not in how well they encrypt.

Why does my site show a warning on some phones only?

Usually a missing intermediate certificate. Configure the server with the full-chain file.

Should I still support TLS 1.0 or 1.1?

No. Both are deprecated (RFC 8996) and modern browsers have removed support for them.

Sources

Related guides

Free · Instant · No sign-up

Find out your grade before someone else does.

Passive scan. Nothing is attacked without your permission.

Free to start. Paid plans from $12 a month, or a one-time report for $29. See pricing