How to secure a webhook in Django using Stripe - python

I have a webhook view which receives POST requests from a payment gateway. It identifies the customer and updates the amount with the provided data.
This can be exploited very easily if the webhook URL somehow gets leaked.
For e.g.
curl --data "cust_no=xxxxxxxxxx&amount=1000" https://example.com/wallet/payment_webhook/
How can I make it secure so that it doesn't accept such requests? It should validate that the request is coming only from the payment gateway.
Update:
The webhook request contains transaction details along with the customer number.

It's explicitly documented on the webhooks documentation:
Best practices
[...]
For optimum security, you can confirm the event data with Stripe before acting upon it. To do so:
Parse the JSON data as above.
Grab the received Event object ID value.
Use the Event object ID in a retrieve event API call.
Take action using the returned Event object.
See also Webhook-Mailer for a working example. Pay particular attention to this line:
# Retrieving the event from the Stripe API guarantees its authenticity
event = Stripe::Event.retrieve(data[:id])

Related

Retrieving the wallet balances on MECX - API Authentication in Python (Signature)

I'm trying to retrieve the wallet balances from the mexc.com cryptocurrency exchange. It works well on others such as Gate.io or Huobi thanks to their awesome documentation. I'm stuck on mexc.com however and confused on how to authenticate myself there.
Based on their documentation, I'd need to send a GET request to /open/api/v2/account/info. I'd also need to sign the request and this is where I'm stuck.
When a request requires a signature, I need to pass the api key, unix time stamp and a calculated signature as url parameters. I have no clue though how to calculate that signature. Also I'd need to sign a string and pass it into the header.
This is their description:
Image

make a decision based on response of webhook in mautic

I was wondering if there is any way to make decisions based on webhook responses in Mautic. To elaborate, I post a request via webhook and the corresponding API responds with an error (e.g. 411). I want to create a campaign that has a block depending on the response of that webhook if it receives 200 decision 1 is made and if it receives 411, another decision is made.
how can I implement this?
I don't think such feature exists by default, but there can be alternative ways to do this.
sending an api call from the system in question(like on success make a call do set some tag or field) same goes for error. However this is practical as long as you have control over that system.
Create a custom campaign Decision node which will listen to the responses of the webhook(in this case you will need to send the webhook using campaign only), Again the block here is that you will need to know how to code a custom campaign decision or will need to look for a developer who can do it.

Get and parse data from the last message of a specific sender with python and Gmail API

Everyday, a sender "sender#sender.com" send me a message with a number inside.
I need to save this number everyday.
I want to write a python script with gmail API to get data from last mail from this sender, and then parse it.
I followed the Gmail API "Quickstart Guide" : here
I also check the page about User.message : here
However, I don't understand how to synchronize all of this to get the data.
Could someone explain me the process ?
If you where you able to complete the Gmail API quickstart, then you already have a GCP project, credentials and have authorized some Gmail API scopes for you app.
The above is the first step (being able to authenticate and be allowed to make requests for the API scope you need).
Since you need to pass a message's Id as a parameter for Users.messages.get you need to first retrieve it using listing messages for example.
So the next step is to make a request to Users.messages.list to list all messages from a user.
You could use the query (q) parameter to filter the messages by user like: q="from:someuser#example.com is:unread".
This will return a list of messages from someuser#example.com that are unread.
Try things out in the API explorer sidebar from the documentation until you have defined the request as you want, and then implement it into you app.
As aerials said.
users().messages().list(userId='me',q=("<parameters>"))).execute()
The above code will fulfill the exact same function as typing in a search request on the gmail website. You dont actually have to worry about labels or anything if you are operating at a small scale. Just follow the same syntax as the search bar on gmail.
However, I am not sure about the usage quotas on the q parameter for list. It may be more expensive for a bigger scale operation to use the q parameter instead of using the other api methods.

How can I configure a Flask API to allow for token-protected user-specific responses?

If I have a server end point that say does a simple task like initializes an API with a token that I generate client side, and then print the users account info.
Can I initialize() the API globally so the user can do other tasks after printing account info?
and
How does that affect other users initializing() and printing info if they do it at the same time?
I don't understand how this server works and any help would be great. Thank you!
If I'm understanding you correctly, it sounds like the easiest way to accomplish what you're trying to do is to use the flask-login module.
You will want to create an endpoint / Flask route (for example, '/login') that the user will send a POST request to with a username (and usually also a password). When the login is successful, the user's browser will have a cookie set with a token that will allow them to access Flask routes that have a #login_required decorator attached.
In your Python code for those routes, you will be able to access the "current_user", which will allow you to tailor your response to the particular user sending the request.
This way of doing things will allow you to deal with your first question, which seems to be about saving a user's identity across requests, and it will also allow you to deal with your second question, which seems to be about the problem of having different users accessing the same endpoint while expecting different responses.
Nathan's answer points you in the right direction, but I'll make a comment about state and scope because you asked about multiple users.
Firstly, the normal way to do this would be for the server to generate the random token and send it back to the user.
client request 1 > init > create token > store along with init data > return token to user
client request 2 > something(token) > find data related to token > return data to user
When you run Flask (and most webapps) you try to make it so that each request is independent. In your case, the user calls an endpoint and identifies themselves by passing a token. If you make a record of that token somewhere (normally in a database) then you can identify that user's data by looking up the same token they pass on subsequent requests.
Where you choose to store that information is important. As I say a database is the normal recommended approach as it's built to be accessed safely by multiple people at the same time.
You might be tempted to not do the database thing and actually store the token / data information in a global variable inside python. Here's the reason why that's (probably) not going to work:
Flask is a wsgi server, and how it behaves when up and running depends on how it's configured. I generally use uwsgi with several different processes. Each process will have its own state that can't see one another. In this (standard / common) configuration, you don't know which process is going to receive any given request.
request 1 > init(token) > process 1 > store token in global vars
request 2 > other(token) > process 2 > can't find token in global vars
That's why we use a database to store all shared information:
request 1 > init(token) > process 1 > store token in db
request 2 > other(token) > process 2 > can find token db

Testing Django Responses to Stripe Webhooks

I'm trying to figure out an effective way to test how my server handles webhooks from Stripe. I'm setting up a system to add multiple subscriptions to a customer's credit card, which is described on Stripe's website:
https://support.stripe.com/questions/can-customers-have-multiple-subscriptions
The issue I'm having is figuring out how to effectively test that my server is executing the scripts correctly (i.e., adding the correct subscriptions to the invoice, recording the events in my database, etc.). I'm not too concerned about automating the test right now, I'm just struggling to effectively run any good test on the script. Has anyone done this with Django previously? What resources and tools did you use to run these tests?
Thanks!
I did not use any tools to run the tests. Impact the stripe has a FULL API REFERENCE which display the information you have send to them and they also display the error. Stripe is very easy to setup, cheap, and have full details in documentation.
What I did is?
First I create a stripe account. In that account, they will give you:
TEST_SECRET_KEY: use for sending payment and information in stripe (for testing)
TEST_PUBS_KEY: identifies your website when communicating with Stripe (for testing)
LIVE_SECRET_KEY: use for sending payment and information in stripe (for live)
LIVE_PUBS_KEY: identifies your website when communicating with Stripe (for live)
API_VERSION: "2012-11-07" //this is the version for testing only
When you login you will see Documentation at the top. Click the documentation and they will give you step by step tutorial on how to create a form, how to create subscription, how to handle errors and many more.
To check if your script is executing and connecting to stripe. Click FULL API REFERENCE then choose Python. In that page you will see the information you have send and error that you have encountered.
What I really like is, if the Stripe detect an error the system will point out that and give you a solution. The solution is in the left side and checking the information send is on the right side.
Stripe is divided into two worlds: the test mode and the live. In test mode, you can perform creating new customer, add new invoices, set up your subscription, and many more. What ever you do in test mode, is the same when your Stripe is live.
I really love that stripe provides the logs for the web hooks, however, it is difficult to view the error responses from them, so I set up a script using the Requests library. First, I went to the Stripe dashboard and copied one of the requests they were sending.
Events & Webhooks --> click on one of the requests --> copy the entire request
import requests
data = """ PASTE COPIED JSON REQUEST HERE """
# insert the appropriate url/endpoint below
res = requests.post("http://localhost:8000/stripe_hook/", data=data).text
output = open("hook_result.html", "w")
output.write(res)
output.close()
Now I could open hook_result.html and see any django errors that may have come up (given DEBUG=True in django).
In django-stripe-payments I have a test suite that while far from comprehensive is meant to be a start at getting there. What I do is just copy a real webhook's data, scrub it for sensitive data and add it as a data to the test.
testing stripe webhooks is a pain. I don't use Django, so my answer will be more general.
My php webhook handler parses the webhook data and dispatches handler functions accordingly. In my handler class, I set up class properties with legitimate data for all the ids that the test webhooks mangles. Then I have a condition in each of my handler functions that tests for livemode. If false, I replace the mangled ids with legit test ids.
I also have another class property called $fakeLiveMode, which I set to true when I'm testing. This allows me to force the code to process as though in live mode.
So, for example, when testing the customer.subscription.updated event, the plan id and customer id get botched. So in that handler I would do this:
if ($event->livemode === true || $this->fakeLivemode)
{
if ($this->fakeLivemode)
{
// override botched data returned by test webhook
$event->data->object->plan->id = $this->testPlanId;
$event->data->object->customer = $this->testCustomerId;
}
// process webhook
}
Does that help?

Categories

Resources