|
| 1 | +import jwt |
| 2 | +import hashlib |
| 3 | +import json |
| 4 | +import os |
| 5 | +from flask import Flask, request, jsonify |
| 6 | +from os.path import join, dirname |
| 7 | +from dotenv import load_dotenv |
| 8 | +from pprint import pprint |
| 9 | + |
| 10 | +#Load the environment |
| 11 | +envpath = join(dirname(__file__),'../.env') |
| 12 | +load_dotenv(envpath) |
| 13 | + |
| 14 | +app = Flask(__name__) |
| 15 | + |
| 16 | +port = os.getenv('PORT') |
| 17 | +api_key = os.getenv('NEXMO_API_KEY') # there may be multiple api_key/sig_secret pairs |
| 18 | +sig_secret = os.getenv('NEXMO_SIG_SECRET') |
| 19 | + |
| 20 | +@app.route("/webhooks/inbound", methods=['POST']) |
| 21 | +def inbound(): |
| 22 | + # Need token after 'Bearer' |
| 23 | + parts = request.headers['authorization'].split() |
| 24 | + token = parts[1].strip() |
| 25 | + |
| 26 | + # Extract api_key from token payload |
| 27 | + k = jwt.decode(token, verify=False)["api_key"] |
| 28 | + # Use k to look up corresponding sig secret |
| 29 | + |
| 30 | + #### 1. Verify request |
| 31 | + try: |
| 32 | + decoded = jwt.decode(token, sig_secret, algorithms='HS256') |
| 33 | + except Exception as e: |
| 34 | + print(e) |
| 35 | + r = '{"msg": "' + str(e) +'"}' |
| 36 | + return (r, 401) |
| 37 | + |
| 38 | + #### 2. Verify payload (only needed if using HTTP rather than HTTPS) |
| 39 | + |
| 40 | + # Obtain transmitted payload hash |
| 41 | + payload_hash = decoded["payload_hash"] |
| 42 | + |
| 43 | + # generate hash of request payload |
| 44 | + payload = request.data # Obtains request data as binary string |
| 45 | + h = hashlib.sha256(payload) # requires binary string |
| 46 | + hd = h.hexdigest() # Use hexdigest() and NOT digest() |
| 47 | + |
| 48 | + # Check the payload hash matches the one we created ourselves from request data |
| 49 | + if (hd != payload_hash): |
| 50 | + return ('{"msg": "Invalid payload"}', 401) |
| 51 | + else: |
| 52 | + print("Verified payload") |
| 53 | + return "OK" |
| 54 | + |
| 55 | +@app.route("/webhooks/status", methods=['POST']) |
| 56 | +def status(): |
| 57 | + data = request.get_json() |
| 58 | + return (jsonify(data)) |
| 59 | + |
| 60 | +if __name__ == '__main__': |
| 61 | + print("Running locally") |
| 62 | + app.run(host="localhost", port=port) |
0 commit comments