Find cause of Redirect in ASP.NET? - asp.net

I'm trying to put in an exception in my web.config so that one page does not require authentication. However, it still redirects to the login page.
The question isn't how to setup the web.config. Why? Our system (for better or worse) has a bunch of instrumentation besides the web.config. We have global.asax and custom HttpHandlers. The code base isn't huge, but there's a lot of potential causes for the redirect.
What I do want to know is how to best determine the cause of the redirect. Is there some way to find out what code triggered the redirect?

If you can debug the app, starting from HttpApplication.BeginRequest in global.asax and stepping through System.Web's reference source would be the brute force way.
Alternatively, set a breakpoint on HttpResponse.Redirect(string, bool) and follow the call stack - I doubt there's any other ways that the runtime uses to redirect a request.
If that doesn't turn anything up (or you can't debug), and since the brute force method is likely to lead through a lot of code - and it seems your problem is security related - you could probably just hook HttpApplication. AuthenticateRequest and HttpApplication. AuthorizeRequest, (and it's associated Post* events) and seeing what things look like there.
If you're using Forms Authentication, I happen to know that the FormsAuthenticationModule looks for a status code of 401 at HttpApplication.EndRequest to decide whether to redirect the request. Anything that sets 401 (access denied) will result in a redirect - not the 401 being returned to the browser.

When a request is made to an asp.net page requiring authentication, asp.net redirects to the specified login page with supplying a ReturnUrl querystring argument identifying the original requested page by default. While this ReturnUrl is configurable, if you have not modified the configuration, it's presence should indicate that authentication failed.
In this case, you should be focused on troubleshooting the authentication settings for the page. Gordon Bell's answer looks good for this.
<system.web>
...
</system.web>
<location path="NoAuthNeeded.aspx">
<system.web>
<authorization>
<allow roles="*" />
<allow roles="?" />
</authorization>
</system.web>
</location>

Also, if this is only happening in your production app, you might be able to find out what is going on using WinDBG. Loosely following this article you'd do the following:
Fire up WinDBG and attach to the w3wp process
WinDBG will breakpoint, so do a .loadby sos mscorwks which will load the SOS module
type sxe clr to breakpoint on CLR exceptions
type g to continue on
Now your app will break on any exception. Since Response.Redirect typically throws a ThreadAbortException it might be a simple way to break. Then do a !printexception to get the stack trace. You can also do a ~*e!clrstack if my WinDBG foo isn't failing me to see the managed stack for all the threads currently executing.
Note that you freeze the w3wp process while you are broken in, so be quick!
Hopefully you can use another method instead, but if all else fails, this might help you get started.

Have you tried turning on Tracing? That may help.
How are you specifying the page doesn't require authentication, like:
<system.web>
...
</system.web>
<location path="NoAuthNeeded.aspx">
<system.web>
<authorization>
<allow roles="*" />
<allow roles="?" />
</authorization>
</system.web>
</location>

Put a breakpoint at the beginning of each HTTP handler and notice which one is the last invoked handler before the redirect occurs. You will probably find the cause of the problem in that one.

You can use the following method to find a redirect in your own code:
Open the Exception Settings window and search for "threadabort". Check the checkbox for the ThreadAbortException. Now, when a redirect is executed from code, your debug session will enter break mode.
But since you are talking about the authentication in the web.config, it's highly likely that the issue is there, and not in the code.
Double-check that all the authorization elements like mentioned in HectorMac's answer are correct.

Related

asp.net/iis is NOT appending a ReturnUrl when redirected to login page

Using Forms authentication in a traditional (not mvc) asp.net app, I can not get IIS or IIS-express (when debugging in VS2019) to append a ReturnUrl to the request querystring when it redirects to login.aspx. Thus Request["ReturnUrl"] is always null.
I've read many questions/answers over a few days regarding the Redirect not working but it's always in regards to after authentication and nobody that I've seen has had the problem where ?ReturnUrl=/blah/blah/blah is not even getting appended to the url itself.
Also have read instances where users want ReturnUrl to NOT be appended which is maybe fixed by some code in Global.asax. Lucky them, I wish I had that problem instead of not getting the ReturnUrl in the first place!
I've tried every web.config possibility regarding the tag; specifiying/not specifying loginUrl and defaultUrl; specifiying allow/deny and all combinations thereof
I do have a Global.asax but it is empty for the Request-related methods.
I've also looked into various IIS settings to see if it is an option that it appends a returnUrl but I haven't found anything that suggests that option.
The latest basic entry I tried:
<authentication mode="Forms">
<forms timeout="120" slidingExpiration="true" />
</authentication>
<authorization>
<!--<deny users="?"/>-->
<allow users="*"/>
</authorization>
I should also add that I am using a custom membership provider and not the default asp.net membership provider. Although not sure that would even matter in IIS appending/not appending a ReturnUrl but you never know...
<membership defaultProvider="LegacyDBMembershipProvider">
<providers>
<remove name="AspNetSqlMembershipProvider"/>
<add name="LegacyDBMembershipProvider" someothertags... />
</providers>
</membership>
I would like to have IIS redirect me to login.aspx (as it does) but have the Url look like:
http://localhost:21542/MyWeb/Login.aspx?ReturnUrl=/MyWeb/RequestedPage.aspx
instead of just:
http://localhost:21542/MyWeb/Login.aspx
so that after authentication I can redirect the user to the originally requested page.
Thanks for your time and your consideration.
Thanks Brando, wazz and all that took time to read my question. Apparently it came down to the [allow users=""/> tag itself. Whether or not I had [deny users> anywhere before or after it. I'm not sure why if I only have [allow users=""/> (and no deny tag) that it even still forces to the login page (which I wanted) but it does and WITHOUT appending ReturnUrl. Hence my issue. But after removing any [allow> tags (I tried with individual users, groups, *, etc) the miracle happened and I got a ReturnUrl. It may also have something to do with not supplying a defaultUrl attribute in the [forms> tag. I thought I had tried every combo but apparently not.
Anyways, I'm going to do a little more research as to WHY it works this way and I'll post any info I can garner for posterity but right now I'm just giddy that I'm getting a ReturnUrl appended in the query string.
Thanks again all.

To Increase Request Timeout only on particular Web Page

Is it possible to increase the request timeout for just the one particular web page? I am working on ASP.Net 4.0 and I need one particular page to have a longer request timeout, since it is responsible for initiating a long running process. Thanks.
Use Web.config:
<location path="Page.aspx">
<system.web>
<httpRuntime executionTimeout="180"/>
</system.web>
</location>
This is an old thread, but it should be emphasized that updating the executionTimeout of a page or the entire machine must also be accompanied by the compilation debug flag being set to "false", otherwise the timeout element is ignored.
Also, depending on whether or not you are using AJAX update panels, you may also have to look at the AsycPostBackTimeout flag on the ScriptManager itself - depends on how your timeout is manifesting itself. Ajax post back timeouts will be seen as error messages logged to the Javascript Console and tend to manifest themselves as ajax operations "dying on the vine" depending on how you are handling things.
The debug="false" bit is probably what is afflicting the gentleman above who was having issues on his Amazon Server, but not locally.
Some googling will also reveal that some folks have noticed that localhost handles things differently as well, so you may need to experiment around that.

"Potentially Dangerous Request.Form" Exception in a generic handler

I've seen this error before but cannot seem to get around it. In this case, I have an ASHX page spitting out a simple HTML form with a textbox into which XML may be posted. When I try to read the form, I receive the "A potentially dangerous Request.Form value...".
Since it's a generic handler the "ValidateRequest" attribute isn't available. However I already had this defined in web.config:
<location path="xml/MyGenericHandler.ashx">
<system.web>
<pages validateRequest="false" />
</system.web>
</location>
This snippet predates a move from .NET 3.5 to 4.0 so I'm guessing that's where the breakage originated.
Any idea how to get around this error for ASHX pages?
The 3.5-4.0 change that clipped you was some stepped up runtime security features for ASP.NET 4.0. The quick fix is to apply the following attribute:
<httpRuntime requestValidationMode="2.0" />
Unfortunately, that opens all pages up to 2.0 request validation, so I'd only do this if you've got a relatively small attack surface.
While not a direct answer to your question, I would say to read this previous post. it does give you a way to ensure that the error is not thrown. It's a risky way in one sense, because it means turning off a basic protection. However, the answer is well-reasoned, and the it clearly states that you should only implement it when you're absolutely sure you're encoding all output.
A potentially dangerous Request.Form value was detected from the client
As a side note, I would also recommend using the Microsoft Anti-Xss Library rather than the built in Server.HtmlEncode functions.
However, if you can modify the ashx, a simpler solution would be to just modify the error code and add an "if" statement to not log errors if the error message contains the string you want to filter.
You'd better disable validation for you handler page only:
<location path="MyGenericHandler.ashx">
<system.web>
<!-- requestValidationMode is to avoid HTML-validation of data posted to the handler -->
<httpRuntime requestValidationMode="2.0"/>
</system.web>
</location>
Or use this property from within your handler to avoid triggering the exception:
context.Request.Unvalidated.Form

Defining a forms auth path erratically redirecting to ReturnUrl after logon

I'm having a very erratic problem with forms auth I'm hoping someone can shed some light on. Here's what's in the web.config:
<location path="Admin">
<system.web>
<authorization>
<deny users="?"/>
</authorization>
</system.web>
</location>
And for the auth:
<authentication mode="Forms">
<forms loginUrl="~/Admin/LogOn.aspx" name="MyAppAdmin" requireSSL="false" path="/Admin" cookieless="UseCookies"/>
</authentication>
There's also a custom membership provider implementing ValidateUser against a credential repository. The app has a master page with a LoginName control.
What seems to be happening is that sometimes a user logs on successfully but the logon page remains rather than redirecting them to the ReturnUrl in the query string. We know they've successfully authenticated because the LoginName control shows their identity and they can always browse off to other secured content.
Unfortunately we can't identify the pattern which causes this. Different browsers, different servers, removing cookies, SSL or no SSL; there's no discernible pattern. The only thing which is clear is that after removing the "path" attribute from the forms node the problem couldn't be reproduced.
Is there anything obviously wrong with this configuration? Any thoughts on a possible cause? Obviously the path attribute isn't essential but it's nice to isolate things a bit further.
So I actually found the answer for this right before clicking the submit but have put it in for the sake of having the info on SO. Rick Strahl actually nailed it in this post; it's a case sensitivity problem.
Basically, if you hit "/admin" it redirects you to "/Admin/LogOn.aspx?ReturnUrl=%2fadmin%2fdefault.aspx" then after authentication the cookie is set against the path "/Admin" (defined in the web.config), then you're redirected to "/admin/Default.aspx". The path comparison is case sensitive therefore you're not being identified as authenticated so you're looped back around to the form.
The reason my results were erratic was due to some people manually typing "Admin" and others typing "admin". I wasn't next the the guys doing this and it all sounded just fine over the phone.
Simple answer; get rid of the path attribute. It's too much trouble unless you have absolute confidence the case won't change.

Freetextbox and validating requests

I am using freetextbox and have added to the web.config of my app but I still get the following error when submitting text with html:
A potentially dangerous Request.Form value was detected from the client (ctl00_MainContent_FreeTextBox1="
I know this is not the preferred way to set up an app but why am I getting these errors even though I have turned off request validation in my app?
The short answer is you shouldn't be getting such an error if you turned off Request Validation.
Did you do one of these two things correctly?
Disable on the page by inserting this at the top of the ASPX
Add the below section to your web.config.
<configuration>
<system.web>
<pages validateRequest="false" />
</system.web>
</configuration>
If that doesn't work then check the machine.config and see if the pages validaterequest value is set to true in there as that would override the web.config.
I had the same problem, and it was actually my fault. Maybe you have done the same mistake: I placed <httpRuntime requestValidationMode="2.0"/> inside
<configuration><location><system.web> instead of <configuration><system.web>.
Ensure that you haven't enabled request validation for this page. I would keep validation running for your site - but turn it off on pages where you need this control.
Be sure to sanitize anything that gets posted and be prudent about security.

Resources