Stripe TLS 1.2 Webhook issue
Asked Answered
P

3

5

I am developing an API connected to Stripe using Node.js and express framework. My API is running in a container (FROM node:10.1.0), and I am running the container on a Ubuntu 16 VM using docker-compose:

version: '2.2'

services:
  api:
    image: my-image:latest
    expose:
      - 80

  nginx:
    image: nginx
    ports:
      - "80:80"
      - "443:443"
    links:
      - api
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf

and with an nginx.conf file:

events {
    worker_connections 1024;
}

http {
  server {
    listen 80;

    location / {
      return 301 https://$host$request_uri;
    }
  }

  server {
    listen 443 ssl;

    ssl_certificate     /etc/nginx/ssl/fullchain.pem;
    ssl_certificate_key /etc/nginx/ssl/privkey.pem;
    ssl_protocols TLSv1.3 TLSv1.2 TLSv1.1 TLSv1;
    ssl_ciphers TLS_CHACHA20_POLY1305_SHA256:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-CCM:ECDHE-ECDSA-AES256-CCM8:ECDHE-ECDSA-ARIA256-GCM-SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-CCM:ECDHE-ECDSA-AES128-CCM8:ECDHE-ECDSA-ARIA128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ARIA256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ARIA128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-CCM:DHE-RSA-AES256-CCM8:DHE-RSA-ARIA256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES128-CCM:DHE-RSA-AES128-CCM8:DHE-RSA-ARIA128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384;
    ssl_ecdh_curve X25519:secp521r1:secp384r1;
    ssl_prefer_server_ciphers on;

    try_files   $uri $uri/ =404;

    location /api/ {
      proxy_pass        http://api:80/;
      proxy_buffering   off;
      proxy_set_header  Host $host;
      proxy_set_header  X-Real-IP $remote_addr;
    }
  }
}

When running curl -XPOST https://my.server.com/api/webhook --tlsv1.2 --verbose I get a nice response that looks like TLS 1.2 is working:

*   Trying 23.100.121.74...
* TCP_NODELAY set
* Connected to my.server.com (23.100.121.74) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* Cipher selection: ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:@STRENGTH
* successfully set certificate verify locations:
*   CAfile: /etc/ssl/cert.pem
  CApath: none
* TLSv1.2 (OUT), TLS handshake, Client hello (1):
* TLSv1.2 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (IN), TLS handshake, Server key exchange (12):
* TLSv1.2 (IN), TLS handshake, Server finished (14):
* TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
* TLSv1.2 (OUT), TLS change cipher, Client hello (1):
* TLSv1.2 (OUT), TLS handshake, Finished (20):
* TLSv1.2 (IN), TLS change cipher, Client hello (1):
* TLSv1.2 (IN), TLS handshake, Finished (20):
* SSL connection using TLSv1.2 / ECDHE-RSA-CHACHA20-POLY1305
* ALPN, server accepted to use http/1.1
* Server certificate:
*  subject: OU=Domain Control Validated; CN=*.server.com
*  start date: Sep  7 16:29:45 2018 GMT
*  expire date: Sep  7 16:29:45 2019 GMT
*  subjectAltName: host "my.server.com" matched cert's "*.server.com"
*  issuer: C=US; ST=Arizona; L=Scottsdale; O=GoDaddy.com, Inc.; OU=http://certs.godaddy.com/repository/; CN=Go Daddy Secure Certificate Authority - G2
*  SSL certificate verify ok.
> POST /api/webhook HTTP/1.1
> Host: my.server.com
> User-Agent: curl/7.54.0
> Accept: */*
> 
< HTTP/1.1 400 Bad Request
< Server: nginx/1.15.7
< Date: Fri, 22 Mar 2019 17:50:33 GMT
< Content-Type: application/json; charset=utf-8
< Content-Length: 68
< Connection: keep-alive
< X-Powered-By: Express
< Vary: Origin
< ETag: W/"44-HsiDCuzDBw0t2vb7UevWXjyvmIo"
< 
* Connection #0 to host api.server.com left intact
{"message":"Unable to extract timestamp and signatures from header"}

However, I don't receive any webhook on my server (using ngrok locally works) and when checking on the webhook on Stripe plateform, I can see this error for my server webhook trials:

Status Pending (2 tries)
Next retry around 2019/03/22 18:38 (1 attempt left)
Retry history
[2019/03/22 17:08 to https://my.server.com/api/webhook]: (TLS error) ERR
[2019/03/22 17:38 to https://my.server.com/api/webhook]: (TLS error) ERR

I have tried https://support.stripe.com/questions/how-do-i-upgrade-my-openssl-to-support-tls-1-2 on the linux VM but nothing changed. Also https://support.stripe.com/questions/upgrade-your-node-integration-from-tls-1-0-to-tls-1-2 tells me TLS 1.2 is supported so not sure where it goes wrong

Peacemaker answered 22/3, 2019 at 18:7 Comment(0)
P
10

I managed to resolve the issue by using https://whatsmychaincert.com/ to create the missing "chain", then used the following command to add to the certificate taken from the Azure App Service Cerificate:

cat fullchain.pem example.com.chain.crt > example.com.chained.crt

and used example.com.chained.crt in nginx for the ssl_certificate instead. Now ssllab is telling me the chain is complete, and Stripe is given me a 200 success

Peacemaker answered 4/4, 2019 at 14:17 Comment(3)
Solved it this way as well from a Letsencrypt cert. Thanks @Guillaume!!Spitsbergen
@Spitsbergen how exactly can this be achived with LE certs? How does it work with auto-renewal?Alvita
My cert file was fine (it contained certficate and chain data), but I was missing intermediate certificate in my device (router). I installed chain.pem in my device and now it is okAlvita
P
0

Stripe requires valid TLS certificates for HTTPS webhook endpoints and most often these issues occur when your site is missing an intermediate SSL certificate. Specifically, on your SSL Labs results you will see one of the items in the Certificate Path section marked as "Extra download.". You can confirm this here: https://www.ssllabs.com/ssltest/analyze.html

If you see this issue I recommend visiting your certificate issuer (or the reseller you purchased your certificate from), and re-installing your SSL certificate, including any CA certificate 'bundle' that comes with it. If you're having trouble with this, I'd suggest sharing your SSL Labs results with the issuer and your web host directly, they can guide you in locating this intermediary certificate and resolving this.

Piazza answered 23/3, 2019 at 0:25 Comment(3)
hum I see it says "This server's certificate chain is incomplete. Grade capped to B." so I guess that means there is something missing. It's a certificate exported from Azure App Service Certificates, I'll contact them first to see if they can helpPeacemaker
Ah yes @koopajah, I ran into this problem as well. So I used whatsmycertchain.com and they created a proper chain with the missing intermediate cert for me! So auto renew will likely be a manual process 😣. However, I was going to look at command line switches to check if there's a way to tell LE to include it.Spitsbergen
See @qba-dev's answer above as well. Maybe it's just a matter off the right file!Spitsbergen
T
0

If you're having this issue when running a server setup with a NGINX proxy server, you can solve this issue (because of the SSL chain issue) as described in this excellent blog post from Sectigo.

It has a great step-by-step description of how to install the intermediate certificate to get the chain issue resolved:

https://support.sectigo.com/Com_KnowledgeDetailPage?Id=kA01N000000zFJQ

Tara answered 30/3, 2021 at 10:41 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.