Django on Gunicorn/Nginx - Stripe Webhooks Always Getting 400 - django

Production Setup: Django v3.0.5 on Nginx / Gunicorn / Supervisor (i followed directions from here)
(I don't think this is any issue but i am using dj-stripe for django/stripe integration)
While on development (django's built-in HTTP server).. everything seems to work (i.e. stripe can send webhook events just fine)... however, on production, i get emails saying that Stripe can't reach my server.
When I run
curl -D - -d "user=user1&pass=abcd" -X POST https://my.server/stripe/webhook/
I get this response
HTTP/1.1 400 Bad Request
Server: nginx/1.15.9 (Ubuntu)
Date: Thu, 18 Jun 2020 19:44:07 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 0
Connection: keep-alive
X-Frame-Options: SAMEORIGIN
Vary: Cookie
However, non-webhook (i.e. visiting the website via browser) seems to work normally.. just webhooks.
Any idea where this is going wrong?

Your request doesn't have the Stripe secret which is needed for authentication.

Related

How to send a valid HTTP request to a Google Apps Script Web App?

We sent an HTTP request from a C++ app (Arduino Sketck) to a Google apps script web app, but we got the HTTP Response: HTTP/1.1 302 Moved Temporarily. The url with the http request works fine from a browser.
The same code works also fine with other web site, like www.google.com. Do not work with script.google.com.
The Google apps script published web app is public, anyone even anonymous can access:
Here the code we used.
client.println("GET /macros/s/AKfycbyQnmHekk4_NNy3Bl5ILzuSRkykMWaXQ7Rtojk7fFieDUbVqNM/exec?valore=7 HTTP/1.1");
client.println("Host: script.google.com");
client.println("Connection: close");
client.println();
The answer was:
HTTP/1.1 301 Moved Permanently
Content-Type: text/html; charset=UTF-8
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: Mon, 01 Jan 1990 00:00:00 GMT
Date: Wed, 03 Feb 2021 09:29:02 GMT
Location: https://script.google.com/macros/s/AKfycbyQnmHekk4_NNy3Bl5ILzuSRkykMWaXQ7Rtojk7fFieDUbVqNM/exec?valore=7
X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN
Content-Security-Policy: frame-ancestors 'self'
X-XSS-Protection: 1; mode=block
Server: GSE
Accept-Ranges: none
Vary: Accept-Encoding
Connection: close
Transfer-Encoding: chunked
11e
<HTML>
<HEAD>
<TITLE>Moved Permanently</TITLE>
</HEAD>
<BODY BGCOLOR="#FFFFFF" TEXT="#000000">
<H1>Moved Permanently</H1>
The document has moved here.
</BODY>
</HTML>
0
disconnecting from server.
The url is correct (
http://script.google.com/macros/s/AKfycbyQnmHekk4_NNy3Bl5ILzuSRkykMWaXQ7Rtojk7fFieDUbVqNM/exec?valore=7) but seems that the google apps script web app redirect the request (to the same url, using the https protocol).
Using the same code, we did others HTTP request from Arduino, and it worked fine.
For example we did:
client.println("GET /search?q=arduino HTTP/1.1");
client.println("Host: www.google.com");
client.println("Connection: close");
client.println();
And we got the response `` HTTP/1.1 200 OK ```, and the html response contains the search result according with the query q=arduino
Any suggestion on how we can send a valid http/https request to a Google apps script web app?
Thanks.
As you have noticed, the Google script app is redirecting you from HTTP to HTTPS. Some Google sites are accessible via HTTP, they don't have to redirect to HTTPS if they don't want to. In your example, http://www.google.com/search?q=arduino does redirect, to https://www.google.com/search?q=arduino&gws_rd=ssl. But, your client is not sending a User-Agent header in the request, so Google knows your client is not a browser, and might not be issuing the redirect in your case. But in a real browser, it does.
Putting the URL http://script.google.com/macros/s/AKfycbyQnmHekk4_NNy3Bl5ILzuSRkykMWaXQ7Rtojk7fFieDUbVqNM/exec?valore=7 into a browser does redirect to https://script.google.com/macros/s/AKfycbyQnmHekk4_NNy3Bl5ILzuSRkykMWaXQ7Rtojk7fFieDUbVqNM/exec?valore=7. A real browser will follow that redirect automatically, a user might not even notice the difference.
But your client will have to follow the redirect manually. That means extracting the Location header from the response, closing the existing connection (to script.google.com on port 80), connecting to the specified server (script.google.com on port 443), and initiating an SSL/TLS encrypted session with the server before you can finally send the HTTP request.
SSL/TLS is complex, and HTTP has a lot of rules to it. Don't try to implement them manually. You are best off using an existing HTTP library that has HTTPS support built in. Let it handle all of these details for you.

Get ADFS SAML 2.0 Assertion Response from command line using curl

I would to know WINDOWS Server ADFS really exposes an API to post SAML request en get saml assertion response.
When I enter this in my browser : https://<myfqdn>/adfs/ls/IdpInitiatedSignOn.aspx
I’m presented with a site selection page, as shown in the following image .
Then I choose AWS, and get to the authentication page to provide my AD credentials, after what I get to AWS console page.
It's a POST request and If activate my Google Chrome Developer Tools for example, I can see the from headers
However I'm trying to reproduce the same from my Linux command line using curl but It's not working.
This is what I'm trying :
$api_body="{\"service\": \"aws\", \"email\": \"myemail\", \"password\": \"mypass\"}"
$SAML_IDP_ASSERTION_URL=https://<myfqdn>/adfs/ls/IdpInitiatedSignOn.aspx
$curl -sD - -X POST "$SAML_IDP_ASSERTION_URL" -H "Content-Type: application/json" -d "$api_body"
This gives me the following header :
HTTP/1.1 200 OK
Cache-Control: no-cache,no-store
Pragma: no-cache
Content-Length: 12844
Content-Type: text/html; charset=utf-8
Expires: -1
Server: Microsoft-HTTPAPI/2.0 Microsoft-HTTPAPI/2.0
x-frame-options: DENY
Date: Fri, 22 Mar 2019 10:25:13 GMT
Followed by the site html content in my terminal including javascript and others. I don't get or see any json data back, nor SAML Response.
Do you guys have an idea of what's the right command/request to get SAML Response from command line?

URL forbidden 403 when using a tool but fine from browser

I have some images that I need to do a HttpRequestMethod.HEAD in order to find out some details of the image.
When I go to the image url on a browser it loads without a problem.
When I attempt to get the Header info via my code or via online tools it fails
An example URL is http://www.adorama.com/images/large/CHHB74P.JPG
As mentioned, I have used the online tool Hurl.It to try and attain the Head request but I am getting the same 403 Forbidden message that I am getting in my code.
I have tried adding many various headers to the Head request (User-Agent, Accept, Accept-Encoding, Accept-Language, Cache-Control, Connection, Host, Pragma, Upgrade-Insecure-Requests) but none of this seems to work.
It also fails to do a normal GET request via Hurl.it. Same 403 error.
If it is relevant, my code is a c# web service and is running on the AWS cloud (just in case the adorama servers have something against AWS that I dont know about). To test this I have also spun up an ec2 (linux box) and run curl which also returned the 403 error. Running curl locally on my personal computer returns the binary image which is presumably just the image data.
And just to remove the obvious thoughts, my code works successfully for many many other websites, it is just this one where there is an issue
Any idea what is required for me to download the image headers and not get the 403?
same problem here.
Locally it works smoothly. Doing it from an AWS instance I get the very same problem.
I thought it was a DNS resolution problem (redirecting to a malfunctioning node). I have therefore tried to specify the same IP address as it was resolved by my client but didn't fix the problem.
My guess is that Akamai (the service is provided by an Akamai CDN in this case) is blocking AWS. It is understandable somehow, customers pay by traffic for CDN, by abusing it, people can generate huge bills.
Connecting to www.adorama.com (www.adorama.com)|104.86.164.205|:80... connected.
HTTP request sent, awaiting response...
HTTP/1.1 403 Forbidden
Server: **AkamaiGHost**
Mime-Version: 1.0
Content-Type: text/html
Content-Length: 301
Cache-Control: max-age=604800
Date: Wed, 23 Mar 2016 09:34:20 GMT
Connection: close
2016-03-23 09:34:20 ERROR 403: Forbidden.
I tried that URL from Amazon and it didn't work for me. wget did work from other servers that weren't on Amazon EC2 however. Here is the wget output on EC2
wget -S http://www.adorama.com/images/large/CHHB74P.JPG
--2016-03-23 08:42:33-- http://www.adorama.com/images/large/CHHB74P.JPG
Resolving www.adorama.com... 23.40.219.79
Connecting to www.adorama.com|23.40.219.79|:80... connected.
HTTP request sent, awaiting response...
HTTP/1.0 403 Forbidden
Server: AkamaiGHost
Mime-Version: 1.0
Content-Type: text/html
Content-Length: 299
Cache-Control: max-age=604800
Date: Wed, 23 Mar 2016 08:42:33 GMT
Connection: close
2016-03-23 08:42:33 ERROR 403: Forbidden.
But from another Linux host it did work. Here is output
wget -S http://www.adorama.com/images/large/CHHB74P.JPG
--2016-03-23 08:43:11-- http://www.adorama.com/images/large/CHHB74P.JPG
Resolving www.adorama.com... 23.45.139.71
Connecting to www.adorama.com|23.45.139.71|:80... connected.
HTTP request sent, awaiting response...
HTTP/1.0 200 OK
Content-Type: image/jpeg
Last-Modified: Wed, 23 Mar 2016 08:41:57 GMT
Server: Microsoft-IIS/8.5
X-AspNet-Version: 2.0.50727
X-Powered-By: ASP.NET
ServerID: C01
Content-Length: 15131
Cache-Control: private, max-age=604800
Date: Wed, 23 Mar 2016 08:43:11 GMT
Connection: keep-alive
Set-Cookie: 1YDT=CT; expires=Wed, 20-Apr-2016 08:43:11 GMT; path=/; domain=.adorama.com
P3P: CP="NON DSP ADM DEV PSD OUR IND STP PHY PRE NAV UNI"
Length: 15131 (15K) [image/jpeg]
Saving to: \u201cCHHB74P.JPG\u201d
100%[=====================================>] 15,131 --.-K/s in 0s
2016-03-23 08:43:11 (460 MB/s) - \u201cCHHB74P.JPG\u201d saved [15131/15131]
I would guess that the image provider is deliberately blocking requests from EC2 address ranges.
The reason the wget outgoing ip address is different in the two examples is due to DNS resolution on the cdn provider that adorama are providing
Web Server may implement ways to check particular fingerprint attributes to prevent automated bots . Here a few of them they can check
Geoip, IP
Browser headers
User agents
plugin info
Browser fonts return
You may simulate the browser header and learn some fingerprinting "attributes" here : https://panopticlick.eff.org
You can try replicate how a browser behave and inject similar headers/user-agent. Plain curl/wget are not likely to satisfied those condition, even tools like phantomjs occasionally get blocked. There is a reason why some prefer tools like selenium webdriver that launch actual browser.
I found using another url also being protected by AkamaiGHost was blocking due to certain parts in the user agent. Particulary using a link with protocol was blocked:
Using curl -H 'User-Agent: some-user-agent' https://some.website I found the following results for different user agents:
Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:70.0) Gecko/20100101 Firefox/70.0 okay
facebookexternalhit/1.1 (+http\://www.facebook.com/externalhit_uatext.php): 403
https ://bar: okay
https://bar: 403
All I could find for now is this (downvoted) answer https://stackoverflow.com/a/48137940/230422 stating that colons (:) are not allowed in header values. That is clearly not the only thing happening here as the Mozilla example also has a colon, only not a link.
I guess that at least most webservers don't care and allow facebook's bot and other bots having a contact url in their user agent. But appearently AkamaiGHost does block it.

MISS from Cloudfront after HIT from Cloudfront

I am switching to Amazon Cloudfront for serving images on my website. To reduce load when we finally make it live, I thought of warming up the cache by hitting image URLs (I am making these request from India and expect majority of users to request from the same region so no need to have a copy of object on all edge locations worldwide).
The problem is that script uses curl to request image and when I access the same URL in browser I get MISS from Cloudfront. So Cloudfront is making two copies of object for these two request.
My current Cloudfront configuration forwards Content-Type request Header to origin.
How should I configure Cloudfront so that it doesn't care about request headers at all and once I made a request (whether curl or using browser) it should serve all future request for same resource from edge and not origin.
Request/Response headers-
I am afraid that the Cloudfront url won't be accessible from outside (until we go live) but I am posting request/response headers, this should give you fair idea. Also you can check out caching headers at origin - https://origin.ixigo.com/image/upload/t_thumb,f_auto/r7y6ykuajvlumkp4lk2a.jpg
Response after two successive request using browser
Remote Address:54.230.156.66:443
Request URL:https://youcannotaccess.com/image/upload/t_thumb,f_auto/r7y6ykuajvlumkp4lk2a.jpg
Request Method:GET
Status Code:200 OK
Response Headers
view source
Accept-Ranges:bytes
Age:23
Cache-Control:public, max-age=31557600
Connection:keep-alive
Content-Length:8708
Content-Type:image/jpg
Date:Fri, 27 Nov 2015 09:16:03 GMT
ETag:"-170562206"
Last-Modified:Sun, 29 Jun 2014 03:44:59 GMT
Vary:Accept-Encoding
Via:1.1 7968275877e438c758292828c0593684.cloudfront.net (CloudFront)
X-Amz-Cf-Id:fcbGLv8uBOP89qfR52OWa-NlqWkEREJPpZpy9ix0jdq8-a4oTx7lNw==
X-Backend:image6_40
X-Cache:Hit from cloudfront
X-Cache-Hits:0
X-Device:pc
X-DeviceType:pc
X-Powered-By:xyz
Now same url requested using curl but gave me miss
curl manu-mdc:cache manuc$ curl -I https://youcannotaccess.com/image/upload/t_thumb,f_auto/r7y6ykuajvlumkp4lk2a.jpg
HTTP/1.1 200 OK
Content-Type: image/jpg
Content-Length: 8708
Connection: keep-alive
Age: 0
Cache-Control: public, max-age=31557600
Date: Fri, 27 Nov 2015 09:16:47 GMT
ETag: "-170562206"
Last-Modified: Sun, 29 Jun 2014 03:44:59 GMT
X-Backend: image6_40
X-Cache-Hits: 0
X-Device: pc
X-DeviceType: pc
X-Powered-By: xyz
Vary: Accept-Encoding
X-Cache: Miss from cloudfront
Via: 1.1 4d42171c56a4c8b5c627040e6aa0938d.cloudfront.net (CloudFront)
X-Amz-Cf-Id: fY0LXhp7NlqB-I8F5-1TIMnA6bONjPD3CEp7dsyVdykP-7N2mbffvw==
Now this will give HIT
manu-mdc:cache manuc$ curl -I https://youcannotaccess.com/image/upload/t_thumb,f_auto/r7y6ykuajvlumkp4lk2a.jpg
HTTP/1.1 200 OK
Content-Type: image/jpg
Content-Length: 8708
Connection: keep-alive
Cache-Control: public, max-age=31557600
Date: Fri, 27 Nov 2015 09:16:47 GMT
ETag: "-170562206"
Last-Modified: Sun, 29 Jun 2014 03:44:59 GMT
X-Backend: image6_40
X-Cache-Hits: 0
X-Device: pc
X-DeviceType: pc
X-Powered-By: xyz
Age: 3
Vary: Accept-Encoding
X-Cache: Hit from cloudfront
Via: 1.1 6877899d48ba844a34ea4378ce336f06.cloudfront.net (CloudFront)
X-Amz-Cf-Id: qpPhbLX_5t2Xj0XZuZdjWD2w-BI80DUVyL496meQkLfSEn3ikt7hNg==
This is similar to this issue: Why are two requests with different clients from the same computer cache misses on cloudfront?
Depending on whether you provide the "Accept-Encoding: gzip" header or not, CloudFront edge server caches the object separately. Since browsers provides this header by default, and your site is likely to be accessed majorly via browser, I will suggest changing your curl call to include this header.
I was facing the same problem, after making the change in my curl call, I started to get a Hit from the browser on my first try via browser (after making a curl call).
Another thing I noticed is that CloudFront requires the full requested object to be downloaded before it will be cached. If you try to download the file partially by specifying the byte range in the curl, the intended object does not get cached, only the downloaded part gets cached as a different object. Same goes for a curl that was terminated in between. The other options I tried were wget call with spider option, but that internally does a HEAD call only and thus does not get the content cached on the edge server.

How to find out where a cookie is set?

I am trying to find out where a cookie is being set.
I am running Varnish cache and want to know where the cookie is being set so I know if I can safely remove it for caching purposes.
The response headers look like this;
HTTP/1.1 200 OK
Server: Apache/2.2.17 (Ubuntu)
Expires: Mon, 05 Dec 2011 15:11:39 GMT
Cache-Control: no-store, max-age=7200
Vary: Accept-Encoding
Content-Type: text/html; charset=UTF-8
X-Session: NO
X-Cacheable: YES
Date: Tue, 04 Dec 2012 15:29:40 GMT
X-Varnish: 1233768756 1233766580
Age: 1081
Via: 1.1 varnish
Connection: keep-alive
X-Cache: HIT
There is no cookie present. But when loading the same page in a browser the headers are the same, I get a cache hit and no cookie in the response headers.
But then the cookie is there all of a sudden, so it must be being somewhere. Even if I remove it it reappears. It even appears in Incognito mode in Chrome. But it is not in the header response.
I have been through all the javascript on the site and cannot find anything, is there any other way of setting a cookie?
Thanks.
If the Set-Cookie header goes through Varnish at some point, you can use varnishlog to find the request URL:
$ varnishlog -b -m 'RxHeader:Set-Cookie.*COOKIENAME'
This will give you a full varnishlog listing for the backend requests, including the TxURL to the backend which tells you what the client asked for when it got Set-Cookie back.