Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Fail to validate URL in Facebook webhook subscription with python flask on the back end and ssl

I'm trying to start using new messenger platform from FB. So i have server with name (i.e.) www.mysite.com I got a valid SSL certificate for that domain and apache is setup correctly - all good.

I have a python code on my server which runs flask and i point it to these certificates I got for the server:

from flask import Flask, request
from pymessenger.bot import Bot
import requests
import ipdb
from OpenSSL import SSL
app = Flask(__name__)
TOKEN = "<access_token>"
bot = Bot(TOKEN)

@app.route("/webhook", methods = ['GET', 'POST'])
def hello():
    if request.method == 'GET':
        if (request.args.get("hub.verify_token") == "my_awesome_token"):
                return request.args.get("hub.challenge")
    if request.method == 'POST':
        output = request.json
        event = output['entry'][0]['messaging']
        for x in event:
            if (x.get('message') and x['message'].get('text')):
                message = x['message']['text']
                recipient_id = x['sender']['id']
                bot.send_text_message(recipient_id, message)
            else:
                pass
        return "success"


if __name__ == "__main__":
    # tried this - no luck
    #context = SSL.Context(SSL.SSLv23_METHOD)
    #context.use_privatekey_file('/home/mysite.com.key')
    #context.use_certificate_file('/home/intermediate.crt')

    # tried this - also same result
    context = ('/mysite.com.crt', '/mysite.com.key')

    app.run(host='www.mysite.com',port=5002, debug=True, ssl_context=context)

It starts without error and if I navigate with my browser - i see it gets connections.

enter image description here

port 5002 is open inf my firewall.

But when I go to FB and try to subscribe to that URL - it keeps failing with this error:

enter image description here

The URL couldn't be validated. 
Callback verification failed with the following errors: curl_errno = 60;
curl_error = SSL certificate problem: unable to get local issuer certificate;
HTTP Status Code = 200; 
HTTP Message = Connection established

I've read half the internet on the possible reasons and saw many different suggestions, but I can't make any of those work - i end up with the same result 95% of the time. 5% - some other error due to Flask bugging out with some "crazy" settings I try.

What can be wrong? I'm using certificate files which I got from COMODO. Also tried in the call back url to use /webhook - no luck either. same error.

like image 968
GeekSince1982 Avatar asked Apr 15 '16 08:04

GeekSince1982


1 Answers

As mentioned in the answer above, the issue is that you do not have the issuer certificate which means that a secure connection can not be established. These certificates can be downloaded from your certificate provider, in your case Comodo. Once you have them you need to serve both to the user so a SSL connection can be established. There are multiple ways to do depending on how you are hosting but the easiest way to do it is to concat the certificates together. The order they are concated in IS important and will cause a Key Mismatch error if done in the incorrect order. Your certificate should be first, followed by the issuer certificate and the root certificate, like this:

-----BEGIN CERTIFICATE-----
(Your Primary SSL certificate: your_domain_name.crt)
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
(Your Intermediate certificate: Intermediate.crt)
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
(Your Root certificate: TrustedRoot.crt)
-----END CERTIFICATE-----

This can easily be done from the CLI like this:

cat your_domain_name.crt Intermediate.crt TrustedRoot.crt > combined.crt

This command combines the 3 files in the proper order and stores the output in a new file called combined.crt. See here for more details.

like image 156
user3282276 Avatar answered Sep 21 '22 07:09

user3282276