strange behavior of WebAPI - responds differently when called from different machines - asp.net-mvc

I have a WebAPI service deployed on a server. There is also an MVC app for testing the API. One such tester runs on my dev machine and another copy (same version) runs on the server where API resides.
The MVC tester app supports calling API directly and also through a built-in 'proxy' (http handler) to bypass the "Access-Control-Allow-Origin" errors. So for example if I run the tester app on my dev machine and I want to receive data from the server, I must use the proxy. This setup works nicely and all of the calls are going through and data is passed properly.
Problem occurs when I don't provide enough inputs (for testing purposes) and API generates a "400 Bad request" error. It only happens when I make a call from my dev machine to remote machine and works fine if I make the same call on the server.
I tested with Postman on the remote server:
post directly to API: POST to 177.77.77.77/v1/feature {JSON payload}
the response I get back contains proper headers, a body with a JSON object describing the error. Same thing happens when I send the same exact command but through server's proxy:
post through proxy: POST to 177.77.77.77/proxy/feature {JSON payload}
both results are identical and this is the expected behavior, which I think allows to make a conclusion that proxy is working and API is working.
When I go back to my dev machine and try the same calls, my result for posting directly to API is the same as above but if I use the server's proxy something else happens. Here's output from Fiddler for the working case (from dev machine directly to API):
POST http://177.77.77.77/v1/feature HTTP/1.1
Host: 177.77.77.77
Connection: keep-alive
Content-Length: 514
User-Agent: Mozilla/5.0 xx..
Cache-Control: no-cache
Origin: chrome-extension://xx-postman-xx
Authorization: Basic pwd=
Content-Type: application/json
Accept: */*
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.8
{payload}
response:
HTTP/1.1 400 Bad Request
Cache-Control: no-cache
Pragma: no-cache
Content-Type: application/json; charset=utf-8
Expires: -1
Server: Microsoft-IIS/7.5
X-Powered-By: ASP.NET
Date: Mon, 30 Mar 2015 15:48:52 GMT
Content-Length: 139
{"code":"INVALID_REQUEST","message":"proper error message"}
this is the correct behavior with expected message body (JSON) and correct content-lenght. If I make a request to the server's proxy, my request becomes:
POST 177.77.77.77/proxy/feature HTTP/1.1
Host: 177.77.77.77
Connection: keep-alive
Content-Length: 514
User-Agent: Mozilla/5.0 xx..
Cache-Control: no-cache
Origin: chrome-extension://xx-postman-xx
Authorization: Basic pwd=
Content-Type: application/json
Accept: */*
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.8
Cookie: appSettings=xx
{payload}
then the response I get is:
HTTP/1.1 400 Bad Request
Cache-Control: private
Content-Type: text/html
Server: Microsoft-IIS/7.5
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
Date: Mon, 30 Mar 2015 15:51:37 GMT
Content-Length: 11
Bad Request
the body/payload of the response is lost or replaced by status, content-type changed from JSON to text/html and cache-control became private.
The cookie in the non-working case plays no role. I tried removing it and result is still wrong.
Why do you think this is happening? How can I troubleshoot this and find what portion of code (or maybe IIS setting?) is responsible for sending a different response for what seems to be same requests? After all everything works fine when I run only on dev or only on remote. Could this be some permission issue or something in IIS on the server?
I tried remote-debugging of the proxy code where I would step through the code while sending Post commands (with the same payload) through Postman. In one scenario I ran Postman on the server and made a request to server's proxy and in another scenario I ran Postman on dev and also made requests to server's proxy. In VS I can see that I'm going through the same path in code for both scenarios and that API's response is the same.
Thanks for reading and any attempts to help will be greatly appreciated!

added this to web.config:
<system.webServer>
<httpErrors existingResponse="PassThrough"></httpErrors>
</system.webServer>
found the solution here:
In IIS7.5 what module removes the body of a 400 Bad Request

Related

Get Akamai Token for IPTV HLS

Can anyone solve the way I can generate akamai streaming token from the browser when the android app is not available?
I get this string from the app :
<--
POST /api/tibo324/getakamaitoken HTTP/1.1
Content-Length: 328
Content-Type: application/x-www-form-urlencoded
Host: tibodrm.appspot.com
Connection: Keep-Alive
User-Agent: Apache-HttpClient/UNAVAILABLE (java 1.4)
<--
auth=84Kwfr741QQv%252BnUMXtW%252FcbZ6aWNQKN0mCAVccmjo%252FXaf6PaB2pz7j3QqAlxHaj%252Fut%252Bu3vSzDt8NO%250AKqNBIgM7ckBedzNMkGOBRtlFfi3gAUuUzYvFN7U9ClHQKKWtfL%252F%252FyB2o1qyvGc2tY8i8lud%252F3tqg%250AhyjUvUD3Bib11V9aQqx8JOBslArMz%252FUaXLR0skPUETIeQatFmGmhFoyuyPhgbg%253D%253D%250A&AppID=v%252B10zWNKL8RJ8SY6LUSZXg%253D%253D%250A
-->
HTTP/1.1 200 OK
Server: nginx
Date: Tue, 26 Dec 2017 22:24:09 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 118
Vary: Accept-Encoding
X-Powered-By: Express
ETag: W/"76-zi4HHRQAuAUejh/FF9M5ZFJtPek"
Via: 1.1 google
Alt-Svc: hq=":443"; ma=2592000; quic=51303431; quic=51303339; quic=51303338; quic=51303337; quic=51303335,quic=":443"; ma=2592000; v="41,39,38,37,35"
-->
?__token__=ip=00.000.00.000~exp=1514332929~acl=*~hmac=e9afdfe9f6b41c0ca14a16bc60a11253aecd432243789144c1ebaa70f23c615e
When I try to fetch the following URL:
https://tibodrm.appspot.com/api/tibo324/getakamaitoken?auth=84Kwfr741QQv%2BnUMXtW%2FcbZ6aWNQKN0mCAVccmjo%2FXaf6PaB2pz7j3QqAlxHaj%2FuFjEcIocduH6Z%0Awc5ZzKaqnmHhinePCNCcvQfh68bi2UvbZq04lBalY0job9%2FyVeuV1kh4hzWnP8sVuRozO27rFhSY%0AmDB8ck%2FuN0SqKEoxzycGUGhaZy3bjy88%2BhhwEMQknGNJ2j2JdMIHMT0AcLTFoQ%3D%3D%0A&AppID=v%2B10zWNKL8RJ8SY6LUSZXg%3D%3D%0A
I get a response in the browser:
Cannot GET /api/tibo324/getakamaitoken
What am I missing?
The answer is in your question: you can't GET the URL because it's accessed via POST only. And it looks like the POST requires an authentication string that's generated via the app. Making a POST without any data returns a descriptive error string:
$ http POST https://tibodrm.appspot.com/api/tibo324/getakamaitoken
HTTP/1.1 200 OK
Alt-Svc: hq=":443"; ma=2592000; quic=51303431; quic=51303339; quic=51303338; quic=51303337; quic=51303335,quic=":443"; ma=2592000; v="41,39,38,37,35"
Content-Encoding: gzip
Content-Type: application/json; charset=utf-8
Date: Wed, 27 Dec 2017 21:44:19 GMT
ETag: W/"31-zIZow+wVfq5Z3stS2NUNRdvP0go"
Server: nginx
Transfer-Encoding: chunked
Vary: Accept-Encoding
Via: 1.1 google
X-Powered-By: Express
{
"description": "no token at all",
"isValid": false
}
The inability to access the token generator through unauthenticated web calls is usually by design as the token is a protective tool Akamai provides customers to prevent access to content outside of the content provider's control.
In short, the content provider you're looking at doesn't want you to access their video outside of their application. If the application isn't able to access the video then you should reach out to the content provider to get that issue fixed rather than trying to circumvent their security scheme.

SignalR security warning : Missing Cross-Frame Scripting Defence

A security scanning app picked up a risk against a signalR link in my asp.net MVC 5 website.
the X-Frame-Options response header is missing, which may allow
Cross-Frame Scripting attacks
Any one can tell me what's this about?
And How to solve it?
ASP.NET SignalR Input Validation Flaw Permits Cross-Site Scripting Attacks
Should not be the problem since I am using SignalR 2.1.x
The request is :
POST ***/signalr/send?transport=serverSentEvents&clientProtocol=1.4&connectionToken=bla**bla** HTTP/1.1
Host: ****
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:8.0.1) Gecko/20100101 Firefox/8.0.1
Accept: text/plain, */*; q=0.01
Accept-Language: en-us,en;q=0.5
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Connection: keep-alive
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
X-Requested-With: XMLHttpRequest
Referer: myhost
Pragma: no-cache
Cache-Control: no-cache
Cookie: authentication token
Content-Length: 113
data=********
The Response is :
HTTP/1.1 200 OK
Cache-Control: no-cache
Pragma: no-cache
Transfer-Encoding: chunked
Content-Type: application/json; charset=UTF-8
Expires: -1
Server: Microsoft-IIS/8.0
X-Content-Type-Options: nosniff
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
Some html body
I think this warning can safely be ignored. The X-Frame-Options header is used to prevent clickjacking. SignalR responses don't have any links or any other clickable content.
However, it might be a good idea to set an X-Frame-Options header on every response to be extra safe. You can do this via IIS manager or web.config. If you are not using IIS, you can use OWIN middleware instead.

RavenDb - The remote server returned an error: (403) Forbidden

When I try to create a database people collection on RavenDb, I get the following error:
The remote server returned an error: (403) Forbidden.
I hots the Raven on IIS and I am not sure what is going on. On the raven Management Studio, when I try to create a database, I get the below result:
Could not authenticate against server
Message: The remote server returned an error: NotFound. Uri:
/databases?database=Default Server Uri:
http://localhost:8888/docs/Raven/Databases/People
-- Error Information -- System.Net.WebException: The remote server returned an error: NotFound. at
System.Net.Browser.ClientHttpWebRequest.EndGetResponse(IAsyncResult
asyncResult) at System.Func2.Invoke(T arg) at
System.Threading.Tasks.TaskFactory1.FromAsyncCoreLogic(IAsyncResult
iar, Func2 endMethod, TaskCompletionSource1 tcs)
When I looked into this with process monitor, I see that I am getting bunch of not found errors:
Under C:\Utils\RavenDB\Web directory, there are Bin and Data folders, nothing more. Should I create the necessary folders by myself? I created the docs folder but nothing changed. Still having problems.
Any thoughts?
Edit:
Tried with fiddler on Raven Management Studio by creating a document:
Request:
PUT http://localhost:1786/docs/People HTTP/1.1
Accept: /
Accept-Language: en-US
Referer: http://localhost:1786/silverlight/Raven.Studio.xap
Content-Length: 24
Accept-Encoding: identity
If-None-Match: 00000000-0000-0000-0000-000000000000
Content-Type: application/json; charset=utf-8
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.7
(KHTML, like Gecko) Chrome/16.0.912.75 Safari/535.7
Host: localhost:1786
Connection: Keep-Alive
Pragma: no-cache
{
"Name": "..."
}
Response:
HTTP/1.1 403 Forbidden
Cache-Control: private
Server: Microsoft-IIS/7.5
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
Date: Thu, 08 Mar 2012 12:33:22 GMT
Content-Length: 0
This was answered in the comments, however I'll post it here for posterity.
The issue is resolved by changing the web.config value:
<add key="Raven/AnonymousAccess" value="Get"/>
To:
<add key="Raven/AnonymousAccess" value="All"/>
Here is the link to the config page that explains each of the options. Be aware that this option will in fact turn off authentication, if you wish to run with authentication you will need the 'Get' or 'None' setting and you will also need to make sure Windows Authentication is installed (IIS 7.5) and enabled on the Raven IIS Application.

Rails: HTTP version for response

If someone POSTs to my Rails application with HTTP version 1.0 like this:
POST /update HTTP/1.0
How do I send an HTTP version 1.0 response like this:
HTTP/1.0 200 OK
I'm using Ruby on Rails 3. Rails responses always seem to be HTTP version 1.1, but if the client sends a request with HTTP version 1.0 I want to respond with HTTP version 1.0.
If you want your controller to build Header-only responses, you can use the head method. Example:
head :bad_request
Would produce the following header:
HTTP/1.1 400 Bad Request
Connection: close
Date: Sun, 24 Jan 2010 12:15:53 GMT
Transfer-Encoding: chunked
Content-Type: text/html; charset=utf-8
X-Runtime: 0.013483
Set-Cookie: _blog_session=...snip...; path=/; HttpOnly
Cache-Control: no-cache
More information

Using chunked encoding in a POST request to an asmx web service on IIS 6 generates a 404

I'm using a CXF client to communicate with a .net web service running on IIS 6.
This request (anonymised):
POST /EngineWebService_v1/EngineWebService_v1.asmx HTTP/1.1
Content-Type: text/xml; charset=UTF-8
SOAPAction: "http://.../Report"
Accept: */*
User-Agent: Apache CXF 2.2.5
Cache-Control: no-cache
Pragma: no-cache
Host: uat9.gtios.net
Connection: keep-alive
Transfer-Encoding: chunked
followed by 7 chunks of 4089 bytes and one of 369 bytes, generates the following output after the first chunk has been sent:
HTTP/1.1 404 Not Found
Content-Length: 103
Date: Wed, 10 Feb 2010 13:00:08 GMT
Connection: Keep-Alive
Content-Type: text/html
Anyone know how to get IIS to accept chunked input for a POST?
Thanks
Chunked encoding should be enabled by default. You can check your setting with:
C:\Inetpub\AdminScripts>cscript adsutil.vbs get /W3SVC/AspEnableChunkedEncoding
The 404 makes me wonder if it's really a problem with the chunked encoding. Did you triple-check the URL?
You may well have URLScan running on your server. By default URLScan is configured to reject requests that have a transfer-encoding: header and URLScan sends 404 errors (which is conspicuous over a proper server-error).
UrlScan v3.1 failures result in 404 errors and not 500 errors.
Searching for 404 errors in your W3SVC log will include failures due
to UrlScan blocking.
You will need to look at the file located in (path may differ) C:\Windows\System32\inetsrv\URLScan\URLScan.ini. Somewhere in there you will find a [DenyHeaders] section, that will look a bit like this (it will probably have more headers listed).
[DenyHeaders]
transfer-encoding:
Remove transfer-encoding: from this list and it should fix your problem.

Resources