It's not the same without you

Join the community to find out what other Atlassian users are discussing, debating and creating.

Atlassian Community Hero Image Collage

Trello API: Trello webhook signatures and Python

Ethan Kiczek Mar 06, 2018

Hi Trello,

I’m trying to write some python code inside of an AWS Lambda function to verify the webhook signature from Trello. I’ve tried to follow the directions at https://developers.trello.com/page/webhooks#section-webhook-signatures but I can’t seem to get this working. Here’s what I have:

import os

import hmac

import hashlib

import base64

 

def handler(event, context):

   header = event['headers']['x-trello-webhook']

   sha1_check = base64.b64encode(hmac.new(<MY_TRELLO_API_KEY_TOKEN>, event['body'] + <MY_TRELLO_CALLBACK_URL>, hashlib.sha1).digest())

My code is syntactically correct, but it’s not working. When I attempt to compare header and sha1_check, they are not equal. I confirmed this by echoing their values to the logs. The docs at https://developers.trello.com/page/webhooks#section-webhook-signatures say:

Each webhook trigger contains the HTTP header X-Trello-Webhook. The header is a base64 digest of an HMAC-SHA1 hash. The hashed content is the concatenation of the full request body and the callbackURL exactly as it was provided during webhook creation. The key used to sign this text is your application’s secret.

I think my code takes all of this into account.

Can you help me figure out what is wrong?

Thanks,

Ethan

 

1 answer

1 accepted

1 vote
Answer accepted
Ethan Kiczek Mar 07, 2018

SOLVED: Emailed with Bentley Cook, a Developer Advocate, and discovered that the string you pass in to generate the HMAC is not a token that has been generated, but, instead it is the OAuth application secret that you will find at the bottom of the page at https://trello.com/app-key.

 

Once I used that as the secret... it worked!

Bentley Cook Atlassian Team Mar 08, 2018

👍Awesome!

Would you mind posting the final code snippet that worked? I'd like to add it to that webhooks page as an example on how you'd check signatures in Python.

Ethan Kiczek Mar 08, 2018

I'm happy to share the code!

I also lock down the originating IP to the Trello API IPs (I can't remember where I got that code from, but it's out there on Google), I'm including that code as well:

authorized_ips = """
107.23.104.115
107.23.149.70
54.152.166.250
54.164.77.56
54.209.149.230
"""

def is_authorized_ip(ip):
ips = set()
for x in authorized_ips.strip().split("\n"):
ips.add(x.split('#')[0].strip())

return ip in ips

def base64Digest(secret):
mac = hmac.new(os.environ['TRELLO_OAUTH_SECRET'], secret, hashlib.sha1)
return base64.b64encode(mac.digest())

def is_from_trello(hashed_header, request_body):
logger.info('hashed_header: ' + hashed_header)

double_hashed_header = base64Digest(hashed_header)
logger.info('double_hashed_header: ' + double_hashed_header)

double_hashed_body = base64Digest(base64Digest(request_body + os.environ['TRELLO_CALLBACK_URL']))
logger.info('double_hashed_body: ' + double_hashed_body)

return hmac.compare_digest(double_hashed_header, double_hashed_body)

def handler(event, context):
logger.info('got event{}'.format(event))

if not is_authorized_ip(event['requestContext']['identity']['sourceIp']):
logger.info('Unauthorized IP: ' + event['requestContext']['identity']['sourceIp'])
return { 'statusCode': 403, 'body': 'IP Deny' }

if not is_from_trello(event['headers']['x-trello-webhook'], event['body']):
logger.info('Invalid request signature, denying request')
logger.info('Headers:' + json.dumps(event['headers']))
return { 'statusCode': 403, 'body': 'Invalid request signature' }

Like Constantin Kraft likes this

Suggest an answer

Log in or Sign up to answer
This widget could not be displayed.
This widget could not be displayed.
Community showcase
Published in Trello

My e-portfolio: using Trello to keep track of skills and experiences

The days are flying by so fast, I can’t seem to slow things down no matter how hard I try. My memory is great; however, I can’t seem to remember vivid details or even highlights from each year of my ...

1,123 views 13 17
Read article

Community Events

Connect with like-minded Atlassian users at free events near you!

Find an event

Connect with like-minded Atlassian users at free events near you!

Unfortunately there are no Community Events near you at the moment.

Host an event

You're one step closer to meeting fellow Atlassian users at your local event. Learn more about Community Events

Events near you