I'm developing a mobile application for a client that sells digital courses on a service called Teachable that hosts their website and handles the purchase process for them. My client wants to keep using this service for the purchase process and when a user bought a course, he should have access to it on my app.

Now I did some research on Teachable. To my knowledge, it does not a provide a API or some sort of oAuth provider. However it does offer webhooks.

I though about a way to implement this behaviour but I have some concerns about my idea, so I would like to hear opinions from more experienced developers in the security field. My Idea goes like this:

  1. Lets assume Alice buys a course called "Awesome Course 1".
  2. The Teachable webhooks sends me a json object to my server, that include the following properties: { email: Alice@gmail.com, courseName: Awesome Course 1, courseId: 123}
  3. Now In my Database, I create a random Id and add this json object to it. So I have something like this: RandomKey987: { email: Alice@gmail.com, courseName: Awesome Course 1, courseId: 123}
  4. I send Alice a mail that contains the Id RandomKey987
  5. Alice goes to my app, creates an account/logs into her account (that is completely independent of the Teachable Mail/Account she used to buy the course) and enters the Id RandomKey987 in a form, to unlock her course in my app
  6. On my Server, I create a Database entry under Alice's field to mark that she bought the course associated with the Database Entry RandomKey987, which in this case is the course "Awesome Course 1"
  7. I delete the Database Entry RandomKey987, so no one can unlock this course a second time.

Now my concers are:

  1. An Adverary could just send a similar Json Object to like in Step 2., that doesn't come from Teachable. The Attacker would need to know the http endpoint of my webhook and a valid courseId, wich I'm not sure if I can keep these private. Teachable does not provide an API where I could make a request, to validate, that the Json Object indeed refers to a valid purchase. Would be an imaginable solution, to just keep the http enpoint and the courseIDs private?

  2. It won't be possible to guess the Id for a purchase in my database but could there be another way to get the key I send via email? Assuming no other person then Alice can read this email, this should not be a problem right?

Whats your opinion on this? Did I overlook an imporant security apect? Is there a better way to handle this problem?


tl/dr: If money is involved then you need a way to verify your webhook transactions. Your security keys, however, are probably fine, although in the end that is a business decision for you to make.

Private webhook endpoint

Your concerns over a private webhook endpoint are quite valid. In fact, this is one of the biggest dangerous for webhook endpoints - you need to verify that the person calling your endpoint is the person who is supposed to be calling the endpoint, and not an attacker. It's especially critical for online ordering or anything that costs money. Some systems verify the call by providing an API call where you send back the request you received to the intended sender for verification (aka a triple handshake), and some perform it with cryptographic signatures. There are probably more ways to verify it, but verification is very important.

Obviously you can and should keep your webhook endpoint a secret, but this is more akin to a "security through obscurity" step, and not a super secure one either. After all, any developer who has access to the code base will be able to find out what the webhook endpoint is. You're also in trouble if your application code becomes public or accessible to an attacker, or if one of your own developers becomes an attacker. Since half of all data breaches start internally, this is a very real concern.

Unfortunately there isn't anything you can do unless the provider gives you options. I would push hard with them to see if they have any options for webhook verification.

Leaked purchase key

Leaked purchase keys are a danger but also a more fixable one. You do want to make sure your keys are long enough that they can't be easily brute-forced. That has the disadvantage that it makes them hard to type into an app, so you might try to figure out a solution where users can enter the key into the app without having to type it out (QR Codes, links, etc...).

Of course email itself isn't always the most secure channel, but for most businesses it is "secure enough". Inventing a new delivery mechanism for more secure code delivery will likely cause more problems than it will solve.

Fortunately the worst-case scenario of a leaked application key is probably not too bad. After all, someone actually purchased the key, so if an attacker manages to intercept and make use of a single-use case key, the original purchaser will likely be contacting you wondering, "Why isn't my key working?!". Presuming they can provide proof-of-purchase it will be simple enough for you to revoke the app access for the current user and grant it to the new user.

This does create the risk that someone may use social engineering tactics to trick your staff into giving them someone else's subscription, and it also runs the risk of grumpy customers. However, since the marginal cost for you sounds low (i.e. it is relatively cheap for you to give someone else access to the system), the loss is low even if someone occasionally ends up with a free subscription.

That was a bit of a ramble, but the most important part is just the thought process. Security isn't binary. It isn't secure/insecure. It is only ever "secure enough". The more effort you put into security measures the more likely you are to cause trouble for your legitimate customers, and at some point in time it is more cost effective to stop adding security layers and accept that an attacker may occasionally succeed in stealing a subscription or two. As a result the trick isn't to make things secure, but rather secure enough.

| improve this answer | |
  • Yes, it would definitely be worth looking into whether they HMAC-sign (or similar) the webhook data. – multithr3at3d Jan 24 at 2:16
  • 1
    Thank you, this way very helpful! Unfortunatly I don't think I will get Teachable to offer an API or use Mac signing, but I will try. I found another way, that might be more secure. Teachable offers a Zapier integration. I can authenticate my Teachable Account and "Database Account" in Zapier, and when a purchase was made, they automatically add a Database entry for me. This should eliminate the risk of having a Webhook enpoint. – Jonas Jan 24 at 9:05
  • @Jonas you may have a simpler option, presuming that the company has a standard API where you can fetch order details. When the webhook call comes in, take the order id and look it up through their normal API system. If it doesn't check out then you Know it is fraud, and either way use the response from their API instead of whatever came through the webhook – Conor Mancone Jan 30 at 0:51
  • @ConorMancone the problem is, I didn't find an API I can use – Jonas Jan 30 at 8:58

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.