How to authenticate Monzo Webhook?


I’m building an application using Monzo Webhooks. In a nutshell, I have an AWS Lambda with a function URL. The webhook will be posting to the function URL. However, I need to leave the function open to the public in order for Monzo to call it. I’m looking for a way to stop this URL being abused by anyone and therefore incur high AWS costs. Has anyone done something similar? How do you protect your endpoints?

When I build there’s a few ways, one is locking it down to the referrer so that only certain domains can call it. Or locking it down to fixed IPs if they are permanently static.

Or when you can set the calling side inside the script you can simply check a param matches a secret key you make up.

Inside the script or middleware as a first thing check that key equals 12345 or deny.

Oh, I hadn’t realised you could restrict IPs without API Gateway. Do you have any code samples?

Well in my daily code I would do something like the following in Laravel.

Essentially just make a middleware that’s added to whatever route I’m protecting. Instead of blockips read that as $whitelist and add a ! before the in array check. So if you’re not on the list your not coming in.

If I’m making an API service I’m using using the built in OAuth for server>server

With what you’re trying to achieve this post might be useful

1 Like

Ah, I thought there was a way to add allowed IP addresses to a Policy or something. I understand what you’re doing here. While this would invoke the lambda, the run time would be very low if unauthorised. Thanks for this

1 Like

A secret query param in the webhook URL is my go-to, which I then verify on the server. I imagine basic auth credentials in the webhook URL would also work, but I haven’t tried it myself.

I’d be hesitant to doing any IP whitelisting. AFAIK Monzo don’t publish a list of static IP addresses from which your webhooks will be called from. So, it’s very likely that those calling IP addresses will change, and you’ll reject/miss any events originating from the new, non-whitelisted IPs.

EDIT: Just tried it. Basic auth appears to work just fine. The username and/or password in the webhook URL get passed through in the Authorization header of the request.