Is it possible to skip the first anonymous request to a webserver? - asp.net-mvc

On a webserver with Kerberos the client will send a request anonymously, and get a 401 status back. Then it sends the same request again, with authentication, and now get a 200 status back. Is it possible to set up a web application in MVC/JavaScript/etc to know that an anonymous request is futile and go stright for the user authentication request? For a specific case I am using jQuery and AJAX that is pulling data from a server at short intervals.
UPDATE: I want the client to know that there is no use sending an anonymous request, so it can just as well send a request with a username the first time. Why sending an anonymous request in the first place when you absolutely know you will only get a 401 back?

Based on this answer, you should just use beforeSend callback and then add the Authorization header on your own.

You are looking for preemptive authentication and this is highly discouraged. Do not send credentials unless the server challenges you otherwise you may reveal secrets to an unknown server.

update as you don't need to allow anonymous access.
You could remove default IIS authentication module and/or add your own custom HttpModule for a specific part
<location path="PathToWebApi">
<system.web>
<httpModules>
<!-- default IIS HttpModules -->
<remove name="WindowsAuthentication"/>
<remove name="FormsAuthentication"/>
<remove name="PassportAuthentication"/>
<remove name="RoleManager"/>
<remove name="UrlAuthorization"/>
<remove name="FileAuthorization"/>
<remove name="AnonymousIdentification"/>
<remove name="Profile"/>
<add name="CustomAuthentication" type="Your.NameSpace.CustomAuthentication"/>
</httpModules>
</system.web>
<system.webServer>
<modules runAllManagedModulesForAllRequests="false">
<add name="CustomAuthentication" type="Your.NameSpace.CustomAuthentication" preCondition="managedHandler"/>
</modules>
</location>
You can implement CustomAuthentication : IHttpModule class that inspect incoming request context and set current user identity depend on your custom logic.
public void Init(HttpApplication context)
{
//add event listener to authenticate Http request
//context.AuthenticateRequest += new EventHandler(AuthenticateRequest); //Session is null at AuthenticateRequest state
context.PreRequestHandlerExecute += new EventHandler(OnPreRequestHandlerExecute);
}

Related

Sitecore 7.5 MVC and HttpContext.Session.Timeout set to 1 min

I have the session timeout set to 20min but when I try to access this value from action I'm getting 1min instead.
Web.Config settings are:
<sessionState mode="InProc" cookieless="false" timeout="20">
<authentication mode="None">
<forms name=".ASPXAUTH" cookieless="UseCookies" timeout="20" />
</authentication>
In Global.asax.cs in Session_Start value of timeout is 20min:
HttpContext.Current.Session.Timeout
But in action in my controller is set to 1min:
System.Web.HttpContext.Current.Session.Timeout
HttpContext.Session.Timeout
I've found that when I remove SitecoreHttpModule which is of type (Sitecore.Nexus.Web.HttpModule,Sitecore.Nexus) from web.config the timeout works fine but I dont think I can remove it permanently.
<system.webServer>
<modules runAllManagedModulesForAllRequests="true">
<remove name="WebDAVModule"/>
<add type="Sitecore.Web.RewriteModule, Sitecore.Kernel" name="SitecoreRewriteModule"/>
<!-- !!!REMOVED MODULE!!! <add type="Sitecore.Nexus.Web.HttpModule,Sitecore.Nexus" name="SitecoreHttpModule"/> -->
<add type="Sitecore.Resources.Media.UploadWatcher, Sitecore.Kernel" name="SitecoreUploadWatcher"/>
<add type="Sitecore.IO.XslWatcher, Sitecore.Kernel" name="SitecoreXslWatcher"/>
<add type="Sitecore.IO.LayoutWatcher, Sitecore.Kernel" name="SitecoreLayoutWatcher"/>
<add type="Sitecore.Configuration.ConfigWatcher, Sitecore.Kernel" name="SitecoreConfigWatcher"/>
...
</modules>
</system.webServer>
Is there any place I can configure this timeout for this module or there is any other way to set session timeout to desired value?
Every first request for a new user is considered as a possible bot request. That's why session timeout is set to 1 minute for those requests.
If the request is executed by the proper end user, there should be VisitorIdentification code on your page which in fact will cause another background call to the server and extend the session for the user.
Just add
#using Sitecore.Mvc.Analytics.Extensions
...
#Html.Sitecore().VisitorIdentification()
to your layout .cshtml file.
Timeout will be set to 1 minute for the first request, but then automatically changed back to 20 (or whatever is configured), when Sitecore does the VisitorIdentification call.
The problem is in robots detection in Sitecore Analytics module. My browser is recognized as a bot and there are some settings about that in Sitecore.Analytics.Tracking.config file:
<!-- ANALYTICS ROBOTS SESSION TIMEOUT
The ASP.NET Session Timeout for auto detected robots.
When the automatic robot detection identifies a session as being a robot, the ASP.NET
Session Timeout is set to this value (in minutes).
Default: 1
-->
<setting name="Analytics.Robots.SessionTimeout" value="1" />
The timeout is set to 1min when bot is detected to save some mememory and not to keep session too long.
The timeout will be set to desired 20min value when I either disable Analytics at all or disable Analytics.AutoDetectBots (in Sitecore.Analytics.Tracking.config file).
The proper solution for this is to clasify browser correctly (not as a bot).
Another post on this issue:
Sitecore Analytics Robots SessionTimeout causing premature session timeout
In Sitecore 7 there is now multiple places you have to specify the Session Timeout.
I would check these values in your Web.config.
<setting name="Authentication.ClientSessionTimeout" value="120" />
and
<forms name=".ASPXAUTH" cookieless="UseCookies" timeout="120" />
and then
<sessionState mode="InProc" ... timeout="120" />
More info here:
Strange Timeout in Sitecore 7

IIS hijacks CORS Preflight OPTIONS request

I am making a CORS POST request and setting the Content-Type header to json. This triggers a Preflight OPTIONS request to fire (this is good and expected)
This OPTIONS request is responded to with a 200 OK but this isn't coming from my WebAPI application.
I have a custom Message Handler in place and it never get's hit so the request is getting responded to by IIS prior to hitting ASP.NET it seems.
I have found several posts on the subject and they say the following
Make sure WebDav is uninstalled / removed / disabled - DONE
Make sure the OPTIONSVerbHandler is removed / changed to use aspnet_isapi.dll - TRIED BOTH
Make sure the extensionlessURLHandler includes the OPTIONS verb - DONE
However, my options request is still getting hijacked. By that I mean, IIS responds with at 200 OK but isn't including an Access-Control-Allow-Origin header in the response. It isn't including this header because it is never getting to my WebAPI CORS code that would set this header.
The two best posts I could find that sound like my issue are
here: JQuery stuck at CORS preflight and IIS ghost response
and here: http://brockallen.com/2012/10/18/cors-iis-and-webdav/
I have tried turning on Failed Request tracing (FERB) in IIS and set it to trace all 200 status codes. I don't ever see the options request being logged... Not sure if this means FERB doesn't track OPTIONS requests or if I need to change something in the FERB settings to make it track OPTIONS requests, Or if this is a clue to what my problem is?
This is ASP.NET WebAPI 2.0 running on IIS 7.5 (Also tested on IIS 8 and IISExpress with same results)
Doesn't matter what browser (Chrome, FF, and IE all fail the same way)
I have tried everything I can find on the subject and still can't fix my problem.
Help me StackOverflow, you're my only hope.
A couple of things you can try here, all web.config related, firstly modify your modules element to include the attribute runAllManagedModulesForAllRequests="true", as below:
<modules runAllManagedModulesForAllRequests="true">
<remove name="WebDavModule" />
</modules>
Then set your handlers to the below:
<handlers>
<remove name="ExtensionlessUrlHandler-ISAPI-4.0_32bit" />
<remove name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" />
<remove name="ExtensionlessUrlHandler-Integrated-4.0" />
<remove name="WebDav" />
<remove name="OPTIONSVerbHandler" />
<add name="ExtensionlessUrlHandler-ISAPI-4.0_32bit" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness32" responseBufferLimit="0" />
<add name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness64" responseBufferLimit="0" />
<add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
</handlers>
This should do the trick, but if it doesn't, as a last resort you can force IIS to output the correct headers with the below:
<system.webServer>
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="*" />
<add name="Access-Control-Allow-Methods" value="GET,PUT,POST,DELETE,OPTIONS" />
<add name="Access-Control-Allow-Headers" value="Content-Type" />
</customHeaders>
</httpProtocol>
</system.webServer>
Be wary of the wildcard value, you should really set this to the domain name that your site will be hosted on.
that's what worked for me after 4 hours of searching/experimenting:
<handlers>
<remove name="OPTIONSVerbHandler" />
<add name="OPTIONSVerbHandler" path="*" verb="OPTIONS" modules="IsapiModule" scriptProcessor="C:\Windows\System32\inetsrv\asp.dll" resourceType="Unspecified" requireAccess="None" />
</handlers>
I tried all of the above suggestions as well as others I found on SO and what mattered in my situation was we had Request Filtering enabled on IIS and the OPTIONS HTTP Verb was not in the list of allowed verbs. Once I added it I was able to sort out the rest of it.
I had the same issue and the following web.config settings fixed it for me.
<modules runAllManagedModulesForAllRequests="false">
<remove name="FormsAuthenticationModule" />
</modules>
<handlers>
<remove name="OPTIONSVerbHandler" />
<remove name="ExtensionlessUrlHandler-Integrated-4.0" />
<add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
</handlers>
I was then able to handle CORS OPTIONS requests manually in Application_BeginRequest.
I was originally using the library detailed in this blog post for handling CORS requests. The product I'm working on requires that runAllManagedModulesForAllRequests be set to false, though. This is why I had to set up a custom implementation, but if you don't have that requirement you should give that library a try. It worked great when I was able to have runAllManagedModulesForAllRequests set to true.
In our case it was request filtering in IIS disabling OPTIONS verb at the root web application level. Open up IIS Manager, click on root application, click on Request Filtering, if OPTIONS appears in list either remove or Allow Verb. Wish I had checked this first as lots of wasted time.
In my case, I missed the Microsoft.WebApi.Cors package.
Installed this package and configured it like so in the WebApiConfig class:
public static void Register(HttpConfiguration config)
{
config.MapHttpAttributeRoutes();
config.EnableCors(new EnableCorsAttribute("*","*","*"));
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
Please fine-tune this before using in production because you probably don't want to have wild-cards for everything
This is what worked for me:
<system.webServer>
<handlers>
<remove name="ExtensionlessUrlHandler-Integrated-4.0" />
<remove name="OPTIONSVerbHandler" />
<remove name="TRACEVerbHandler" />
<add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
</handlers>
</system.webServer>
Check if URLScan tool is installed on IIS.
When so check following section:
;
; The verbs (aka HTTP methods) listed here are those commonly
; processed by a typical IIS server.
;
; Note that these entries are effective if "UseAllowVerbs=1"
; is set in the [Options] section above.
;
GET
HEAD
POST
OPTIONS
I know this is an old post, but I just went through the exact same problem.
In my situation, I have CORS installed for both OWIN and WebAPI. The OWIN CORS middleware was intercepting the OPTIONS call long before it ever made it to the WebAPI stuff. Maybe this well help someone else in the future.
I have installed Microsoft.AspNet.WebApi.Cors & Microsoft.Owin.Cors for my oWin based WebAPI and added app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll); at config like below:
public class Startup : IStartup, IAppStartup
{
public void Configuration(IAppBuilder app)
{
var config = this.GetInjectionConfiguration();
BootstrapperWebApi bootstrapperWebApi = (BootstrapperWebApi)this.GetBootstrapperWebApi(config);
bootstrapperWebApi.Initialize(true)
.EnableLogging()
.DisableWebApiDefaultExceptionHandler();
WebApiConfig.Register(config);
app.UseOwinExceptionHandler();
app.Use<LoggerMiddleware>();
app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
//others stuff
}
I tried all the mentioned posts but nothing worked for me, then i shifted my ASP.Net Web API 2 service to windows server 2012 (IIS 8.5) and same service worked without any changes. So issue was specific to IIS 7.5 on windows 7 machine.
In my case I did this:
<verbs allowUnlisted="true" applyToWebDAV="true">
<remove verb="OPTIONS"/>
<add verb="OPTIONS" allowed="true"/>
</verbs>
</requestFiltering>
</security>
When I added <add verb="OPTIONS" allowed="true"/> to the web.config, the application failed to start with this error
HTTP Error 500.19 - Internal Server Error
The requested page cannot be accessed because the related configuration data for the page is invalid.
Cannot add duplicate collection entry of type 'add' with unique key attribute 'verb' set to 'OPTIONS'
So I had to remove it first.
I have the same issue. The OPTIONS request return 200 OK status but it does not contain Access-Control-Allow-Origin header. The problem was our customer network policy blocking the OPTIONS verb request and response the warning message with 200 OK status. I know this is the old post but I want to share my case for anyone needed.
One more case, maybe it will save time for somebody. When I used config with HttpConfiguration.EnableCors all was working fine but when I used web.config file it was failing with CORS errors. It started work after I removed the .vs folder.
<figure>
<img src="https://i.stack.imgur.com/CbRyM.png" alt="">
<figcaption> change the OptionsVerbHangle</figcaption>
</figure>
<figure>
<img src="https://i.stack.imgur.com/wjcMV.png" alt="Minha Figura">
<figcaption>Adicione * and in the case of php use fastcgimodule</figcaption>
</figure>
<figure>
<img src="https://i.stack.imgur.com/wRwpi.png" alt="Minha Figura">
<figcaption>Mapping to folder
</figcaption>
</figure>
<figure>
<img src="https://i.stack.imgur.com/hhqJi.png" alt="Minha Figura">
<figcaption>all verbs
</figcaption>
</figure>
<figure>
<img src="https://i.stack.imgur.com/86kKX.png" alt="Minha Figura">
<figcaption>Select script
</figcaption>
</figure>
Just follow the images below to unlock the colors in IIS
enter image description here
enter image description here
enter image description here
enter image description here
enter image description here
enter image description here

OPTIONS and then POST executing action twice

When I make a $http.post from my client to the web api on a different project, firebug and chrome both show an OPTIONS method and then a POST method.
The problem
Both request actually execute my API action. If I restrict to POST, the OPTIONS fails and the post never happens. I have CORS turned on in both angular and webapi.
my app.js has these lines:
$httpProvider.defaults.useXDomain = true;
delete $httpProvider.defaults.headers.common['X-Requested-With'];
my api call:
$scope.add = function () {
var role = { Name: 'admin' };
$http.post('http://localhost:7514/Roles/add', role).
success(function () {
alert('RolesController.add');
}).
error(function (message) {
alert('FAILED EXECUTE RolesController.add');
});
};
the webapi web.config
<system.webServer>
...
<!-- added for cors handling, remove when using a dedicated cors handler or the system.web.cors dll-->
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="*"/>
<add name="Access-Control-Allow-Headers" value="Origin, X-Requested-With, Content-Type, Accept" />
</customHeaders>
</httpProtocol>
</system.webServer>
If you use the nightly CORS package, the OPTIONS request gets intercepted by a message handler which doesn't execute the action, but still sends the appropriate response header. For more information and how to use nightly packages, you should look at this blog post regarding getting the CORS nightly package.
http://blogs.msdn.com/b/yaohuang1/archive/2013/04/05/try-out-asp.net-web-api-cors-support-using-the-nightly-builds.aspx
Make sure to select "Prerelease" from the the drop down.

Custom 400 with message being overwritten

I have some custom error messages I want to display to the user. So when they say enter a bad username/password combo I might do this in my code:
Response.StatusCode = 400;
return Json("Invalid username or password");
This works fine on my local machine. I've been deploying to a web host and these messages are being overwritten by the server so that they all come out as:
The page cannot be displayed because an internal server error has
occurred.
The server is obviously trying to protect me from revealing sensitive information about what went wrong but I actually do want this error to go through and be seen by the user (well really, parsed by my code and then displayed).
I assume there's something in web.config I can do to make this work but everything I've tried thus far hasn't work. Any ideas?
Relevant section of web.config as I have it now:
<system.webServer>
<httpErrors errorMode="Custom" existingResponse="PassThrough">
</httpErrors>
<validation validateIntegratedModeConfiguration="false"/>
<modules runAllManagedModulesForAllRequests="true"/>
etc.
By the default, some HTTP status codes are obscured by IIS and replaced by it. However, it can be configured by using this line:
<system.webServer>
<httpErrors errorMode="Detailed"/>
This will allow you to pass your custom message in a response and to read it on the client side when AJAX call is done.
In order to handle each Http error code you need to add the specific mapping on the web.config file
<customErrors mode="On/RemoteOnly" >
<error statusCode="400" redirect="My400View" />
<error statusCode="404" redirect="My404iew" />
<error statusCode="500" redirect="My500View" />
</customErrors>
The solution to this ended up being removing the < httpErrors > element from web.config entirely. Even setting it to its default options as seen here http://www.iis.net/configreference/system.webserver/httperrors didn't work so I'm a bit perplexed why removing it works.
<system.webServer>
**Remove <httpErrors> !**
<validation validateIntegratedModeConfiguration="false"/>
<modules runAllManagedModulesForAllRequests="true"/>

How to skip static http requests when using one UoW per http request

I am using one NHibernate UoW per http request in my .net mvc 2 web application. I was just wondering how I can skip creating a UoW for static http requests like images.
You can convert your unit of work implementation to be an implementation of IActionFilter instead of an HttpModule. So OnActionExecuting you can begin your unit of work and OnActionExecuted you can end the unit of work. Then just apply it to your controllers and actions that do data processing.
you can use the IRequiresSessionState marker interface.
private void BeginTransaction(object sender, EventArgs e)
{
HttpApplication app = (HttpApplication)source;
if (app.Context.Handler is IRequiresSessionState) {
// do work
}
}
the staticfilehandler does not apply Session to the request.
I'm not sure if the StaticFileHandler actually issues Begin/EndRequest but I'm guessing not. If you notice that it is triggered for your static files, I assume that your order of handlers are wrong or wildcards for handlers are wrong.
If you map "*" to you MVC handler, maybe you might need to actually move your static content into a subfolder and override the web.config and clear all handlers and only add StaticFileHandler on that.
I noticed that you mention that you use a IHttpModule for the UoW, so I'm guessing that you hijack that for every request.
You could do this:
create a subfolder that you call for example "/static/" and move your static files here. In that folder, create a web.config which contains the following:
<handlers>
<clear />
<add name="StaticFile" path="*" verb="*" modules="StaticFileModule" resourceType="Either" requireAccess="Script" />
</handlers>
and remove the UoW module here (maybe you would only need this row)
<modules>
<remove name="YourUoWModuleName" />
</modules>

Resources