Stop proxy server transforming HTTP POST to HTTP GET - asp.net-mvc-3

I have a web app, which has a dashboard functionality. The app is used by many different companies in many different environments, all browsers.
There is a piece of javascript that refreshes that dashboard every 60 seconds via an http POST to a url which returns JSON.
For one user (and one user only according to my logs) the following .NET error message is generated every 60 seconds from that URL:
System.InvalidOperationException: This request has been blocked because sensitive information could be disclosed to third party web sites when this is used in a GET request. To allow GET requests, set JsonRequestBehavior to AllowGet.
at System.Web.Mvc.JsonResult.ExecuteResult(ControllerContext context)
at System.Web.Mvc.ControllerActionInvoker.InvokeActionResult(ControllerContext controllerContext, ActionResult actionResult)
at System.Web.Mvc.ControllerActionInvoker.<>c__DisplayClass1c.<InvokeActionResultWithFilters>b__19()
at System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilter(IResultFilter filter, ResultExecutingContext preContext, Func`1 continuation)
at System.Web.Mvc.ControllerActionInvoker.<>c__DisplayClass1c.<>c__DisplayClass1e.<InvokeActionResultWithFilters>b__1b()
at System.Web.Mvc.ControllerActionInvoker.InvokeActionResultWithFilters(ControllerContext controllerContext, IList`1 filters, ActionResult actionResult)
at System.Web.Mvc.ControllerActionInvoker.InvokeAction(ControllerContext controllerContext, String actionName)
For all other users, there's never a problem.
I know for a fact that this user is on a network which is proxied (Government). This user is a new user - i.e. we've never had other users on this network.
The above leads me to believe that their proxy is modifying the request for some reason (attempted bandwidth optimisation?), converting the POST to a GET, silently. My Asp.NET MVC app is (correctly) refusing to honour the request for security reasons.
I'm unlikely to be able to change their proxy setup of course.
I tried adding the following to the action:
[OutputCache(Duration = 0, Location = OutputCacheLocation.None, NoStore=true)]
As well as:
Response.Cache.SetNoTransforms();
But the problem remains.
Are there any other HTTP headers that I can set to instruct the proxy to stop mangling things? Any other way of making these proxies behave? Or is there anything in a browser that might be doing this?
Update: since writing this, another 2 different users, from the same company, are now generating these errors, adding weight to my proxy theory.

Related

Expected behaviour with Basic Authentication bad credentials

I have a webapi service in/under DNN V7 (IIS/10 on Win10 Dev box).
It works fine but i have one scenario i wanted check the response i get with expected basic auth responses since i don't seem to be able to find this answer elsewhere.
Controller method is marked with these attributes (which validates using basic auth)
<HttpGet>
<DnnAuthorize(StaticRoles:="TestRole")>
Providing valid user credentials in basic auth header for a user with this role returns
200 ok. all good so far.
Not providing basic auth header at all, returns 401 not authorised, all good and expected.
however, providing basic auth header with say a wrong password or username, returns 500 internal server error.
So is a 500 error correct if the user/pass IS provided BUT wrong?
In my head i should be getting 401 not authorised as it has credentials to validate, they were just incorrect. So i wouldn't expect it to blow up with an exception, just return not authorised?
the call stack isn't very revealing
[NullReferenceException: Object reference not set to an instance of an object.]
System.Web.Http.WebHost.HttpControllerHandler.EndProcessRequest(IAsyncResult result) +113
System.Web.Http.WebHost.HttpControllerHandler.System.Web.IHttpAsyncHandler.EndProcessRequest(IAsyncResult result) +10
System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +9836613
System.Web.HttpApplication.ExecuteStepImpl(IExecutionStep step) +50
System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +163
Does basic auth (or DotNetNuke's implementation of the of the DnnAuthorize attribute) return a 500 error intentionally for security purposes? Did i get a setting or config the api controller wrong? basically what am i missing here?
A 500 status code implies that the server messed up and expects the client to retry, as such it is never related to security, and clearly indicates a problem somewhere.
There are two possible sources of issues:
Configuration of some other middleware in your application.
Validation of username/pass is incorrect, and it is actually passing, but then failing at a later point in your code.
DNN's SDK source has a bug in it.
The reason this is a 500 is because your application isn't handling the failure that is being thrown. It is being caused by one of the two sources (or both above) but as a result your application throws the default 500. It's possible to catch this problem and throw a 401 instead, but it is likely better to tracedown the problem.
First step would be to validate that your code in the step actually isn't being executed. It's possible something there is being executed when you expect it to not be (like userId is NULL instead of the right value), and the problem is really somewhere else.
Also, given that V7 is not the latest version, and from searching around there are other SO instances of DNN having issues before V9, I would suggest validating the problem on a later version. And then if it is still an issue posting it on the relevant github issues.

Passing Multiple Get Parameters to WebApi

I am working on a asp.net core 2.2 application. I want to pass two parameters(token and refresh token) to the asp.net core 2.2 web api to retrieve new token. When I am passing the values, i am getting an error
An unhandled exception occurred while processing the request.
AggregateException: One or more errors occurred. (Response status code does not indicate success: 404 (Not Found).)
System.Threading.Tasks.Task.Wait(int millisecondsTimeout, CancellationToken cancellationToken)
HttpRequestException: Response status code does not indicate success: 404 (Not Found).
Is this right way to pass multiple parameters and route it?
requestUrl is build as below:
string requestUrl = string.Format(Token_RefreshUserToken + "/{0}"+"/{1}", token,refreshToken);
requestUrl value is(web api controller name is 'Token'):
"Token/Refresh/eyJhbGciOiJIQrI1NiIsInR5cCI6IkpXVCJ9.eyJlbWFpbCI6InJlZnJhbmNpc0BzdXlhdpdGkuY54tIiwiZXhwIojxNTYwMzMyOTk7hCJpc3MiOiJodHRwOi8vd3d3LnNlY3WeaXR5Lm9yZyIsImF1ZCI3rdh0dHA6Ly93d3cuc2VjdXJpdHkub3JnIn0.2Iw0VS_OgMjfpgt5V27mjCuLLqzlZBgRMpYgCTEHRP88E/IDwRYkf9idsVrBhBJJ5ymS+8RrZuSBSl+wywuKCs+Bw="
Client:
Task<TokenModel> userToken = _commonHelper.RecreateUserToken(tokenModel.TokenVal, tokenModel.RefreshToken);
userToken.Wait();
public async Task<TokenModel> RecreateUserToken(string token, string refreshToken)
{
string url = string.Format(WebApiConstants.Token_RefreshUserToken + "/{0}"+"/{1}", token,refreshToken);
var statusResponse = await _ApiHelper.GetAsync(url);
tokenData = await statusResponse.Content.ReadAsAsync<TokenModel>();
return tokenData;
}
Web Api method :
[HttpGet]
[Route("Refresh/{token}/{refreshToken}")]
public async Task<TokenValue> Refresh(string token, string refreshToken){ //logic }
It seems that request containing double escape sequence caused the problem.In development mode, try to run the web api project with Kestrel instead of IIS express.
ASP.NET Core application could be hosted on variety of web servers (IIS, Kestrel, Nginx, Apache, ...). All these web servers know nothing about request filtering (and particularly enabling of double escape) which is a native IIS feature. It's a hosting concern and ASP.NET Core application should not deal with it directly. If URL like http://youserver.com/Home/Phone/+12345 will reach ASP.NET Core pipeline, plus sign will not be treated in any special way and will get to string model as + character.
When you host your application on IIS, web.config is still in use, so you could configure <requestFiltering allowDoubleEscaping="true"/> as for usual ASP.NET application.
<system.webServer>
<security>
<requestFiltering allowDoubleEscaping="true" />
</security>
If you want to host application in another Web server, you should check how it handle special characters. Kestrel will just pass such URLs as is, so you don't need to take any specific actions if hosted on Kestrel.
Refer to here

ASP .NET Core MVC: What happens to a request on RedirectToAction

I was trying to pass data around between controllers all day long, but now I'm at the point where I think I haven't quite understood the basics.
Throughout the documentation of ASP .NET core, they use the word "request". I was under the assumption that this is the HttpRequest that is made by the client of the WebServer.
There are also different things that are supposed to be bound to the lifetime of a request:
The HttpContext and its HttpContext.Items dictionary.
Services added with AddScoped via dependency injection.
The TempData dictionary? (not so sure about that)
But when trying to pass data around, I made the observation that when I do return RedirectToAction(...); the HttpContext changes (HttpContext.GetHashCode() has a different value), TempData changes and services added via AddScoped are also new objects.
That would suggest that on RedirectToAction a new request is made, going through all the steps of the request pipeline again. My expectation though was that a RedirectToAction only continues the current request pipeline with a different controller action.
I also thought that the browser or whatever client only made one request and got one response during that entire process.
So what is actually happening when calling RedirectToAction in a controller action and returning the result?
UPDATE:
Using TempData works, but a TempDataProvider has to be configured first. For example add services.AddSingleton<ITempDataProvider,SessionStateTempDataProvider>(); to Startup.cs. Thanks #RonC.
As mentioned, RedirecToAction will cause the browser to make a new request, and when that new request comes in, it will create a totally new HttpContext. As mentioned, To pass data between the two requests, you can use the query string, session or cookies. But there is another option to consider.
TempData
Data can be passed from one request to another via the TempData collection which is accessible in the controller action method. The TempData collection was specifically designed for passing data from one request to another. The beauty of TempData is that the lifetime of an object placed in TempData is exactly one additional request. So anything placed in TempData in request 1 will be there for request 2 but then be automatically removed from TempData at the conclusion of request 2. This makes TempData perfect for passing data from one request to another without having to disclose that information in a query string or possibly forgetting it in session and bloating the session object.
It's impossible to save state of current request, because... HTTP is stateless. Every RedirectToAction really tells browser to make another HTTP request. As documentation says.
Returns an HTTP 302 response to the browser, which causes the browser to make a GET request to the specified action.
If you would like to pass some data between HTTP requests, you have to use cookies or session mechanism.

Sending AJAX request without querystring parameters as 'referrer'

I'm trying to communicate to Google Calendar API.
The API only accepts requests from a specific referrer, e.g.: www.mysite.com/calendar/events.asp
But sometimes the URL includes querystring parameters, e.g.:
www.mysite.com/calendar/events.asp?message=eventAddedSuccessfully&id=50
The API rejects requests from the above URL, and returns this message:
"The referrer www.mysite.com/calendar/events.asp?message=eventAddedSuccessfully&id=50 does not match the referrer restrictions configured on your API key. Please use the API Console to update your key restrictions."
How can I send an AJAX request with only the path in the URL as the referrer?
Thanks
Change your restriction to cater the context path of the domain, it may be specific to that page (and possibly treats it differently with parameters) and causes the issue you're encountering.
www.mysite.com/*
or
www.mysite.com/calendar/*
Hopefully this will resolve the issue.

WebAPI and https not playing well together

I'm getting errors (strange ones) when I try to do GET,PUT,POST,DELETE with https to the same WebAPI controller calls that work http. Is there any special web.config magic that is needed for https with WebAPI controllers?
** ADDING ERROR:
(this is the error code I get when I hit the same GET web api controller as the one that works with http. that is, http works, https fails with this error)
{"message":"An error has occurred.","exceptionMessage":"A null value was returned where an instance of HttpResponseMessage was expected.","exceptionType":"System.InvalidOperationException","stackTrace":" at System.Web.Http.Controllers.ResponseMessageResultConverter.Convert(HttpControllerContext controllerContext, Object actionResult)\r\n at System.Web.Http.Controllers.ApiControllerActionInvoker.<>c__DisplayClass3.<InvokeActionAsync>b__1(Object value)\r\n at System.Threading.Tasks.TaskHelpersExtensions.<>c__DisplayClass3b`2.<Then>b__3a(Task`1 t)\r\n at System.Threading.Tasks.TaskHelpersExtensions.ThenImpl[TTask,TOuterResult](TTask task, Func`2 continuation, CancellationToken cancellationToken, Boolean runSynchronously)"}

Resources