How do I debug AuthorizeAttribute and FormsAuthentication calls - asp.net-mvc-3

I am having crazy problems with Forms Authentication, with the AuthorizeAttribute, and 302 redirect loops. I need to find out what is going on. Is there anyway I can debug Forms Authentication and the AuthorizeAttribute?
Just some more details, in case it is important:
I am using custom membership provider and role provider. I have the correct methods implemented and doing the reading for User/Roles from my custom database tables.
I have the following in my web.config to point to my custom providers:
<membership defaultProvider="MyMembershipProvider">
<providers>
<clear />
<add name="MyMembershipProvider" type="Domain.Entities.Security.MyMembershipProvider" connectionStringName="MyDB" MinRequiredPasswordLength="8" MaxInvalidPasswordAttempts="5" MinRequiredNonAlphanumericCharacters="0" applicationName="My App Name" />
</providers>
</membership>
<profile enabled="false">
<providers>
<clear />
</providers>
</profile>
<roleManager enabled="true" defaultProvider="MyRoleProvider" cookieTimeout="2800" cookieSlidingExpiration="true" cacheRolesInCookie="true">
<providers>
<clear />
<add name="MyRoleProvider" type="Domain.Entities.Security.MyRoleProvider" connectionStringName="MyDB" applicationName="/" />
</providers>
</roleManager>
Some of my controller/actions are 'open'. Some of them have the 'Authorize[Roles="admin"]' and similar.
Sometimes I can work on the application for hours without anything happening. Sometimes I hit a 302 redirect loop soon after I login and then I try to go into one of the other pages. Once that happens, I cannot even go into the top level path without it going into a 302 redirect loop sometimes.
Any directions, any pointers, any suggestions would be greatly appreciated.

Please see the answer in the question linked. This was the resolution to the redirect loop problem.
IIS Session timeout and Forms Authentication loop

Related

Acess denied / Method Not allowed - some browsers only

I have created a WCF service, and am communicating with it using ajax/json 'get' commands. It's working fine on Edge, Chrome (Windows desktop), Firefox (Windows desktop). But with IE10 I'm getting
XMLHttpRequest: Network Error 0x80070005, Access is denied.
and with Chrome on my Android phone I'm getting
error 405 (Method not allowed).
It's also failing with Firefox on the phone (just reports 'web error'), but I haven't any debugger for that so can't check the underlying error.
On an iPad (using Safari), the browser just crashes with no message.
The method being accessed first is 'Login', but if I comment that out, hardcode my login details and try another method (GetLocations) I'm getting the same error.
The site is quilkin.co.uk, if anyone feels like having a look. If it's working correctly, you should get an 'invalid user' or 'invalid password' if you try to log in. Yes, I know it's not secure! I'll sort that later.
The web.config is as follows (sorry about the bad formatting):
<?xml version="1.0"?>
<configuration>
<appSettings>
<add key="aspnet:UseTaskFriendlySynchronizationContext" value="true"/>
</appSettings>
<system.web>
<customErrors mode="Off"/>
<compilation debug="true" targetFramework="4.5.2"/>
<httpRuntime targetFramework="4.5.2"/>
</system.web>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior>
<!-- To avoid disclosing metadata information, set the values below to false before deployment -->
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
<!-- To receive exception details in faults for debugging purposes, set the value below to true. Set to false before deployment to avoid disclosing exception information -->
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>
</serviceBehaviors>
</behaviors>
<protocolMapping>
<add binding="basicHttpsBinding" scheme="https"/>
</protocolMapping>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true"/>
</system.serviceModel>
<system.webServer>
<handlers>
<remove name="WebDAV"/>
</handlers>
<httpProtocol>
<customHeaders>
<clear />
<add name="Access-Control-Allow-Origin" value="*" />
<add name="Access-Control-Allow-Headers" value="Origin, X-Requested-With, Content-Type, Accept,Authorization" />
<add name="Access-Control-Allow-Methods" value="GET, PUT, POST, ORIGIN" />
</customHeaders>
</httpProtocol>
<modules runAllManagedModulesForAllRequests="true">
<remove name="WebDAVModule"/>
</modules>
<directoryBrowse enabled="true"/>
<validation validateIntegratedModeConfiguration="false"/>
</system.webServer>
</configuration>
The 'WebDAV' removal lines were added as a result of looking at other posts, but appeared to make no difference.
I also tried adding a new 'global.asax' as described here but that didn't help either.
i guess i now the problem. please use * in [ServiceContract]. like this:
[WebInvoke(Method = "*"
this way you allow your method receive options request.
Enabling CORS for non-GET requests requires more than just setting the
Access-Control-Allow-Origin header - it also needs to deal with
preflight requests, which are OPTIONS requests which ask the server
whether it's safe to perform operations which can potentially change
data (e.g., POST, PUT, DELETE) before the actual request is sent.
I've written a blog post about adding CORS support for WCF. It's not the simplest of the implementations, but hopefully the code in the post can be simply copied / pasted into your project. The post can be found at http://blogs.msdn.com/b/carlosfigueira/archive/2012/05/15/implementing-cors-support-in-wcf.aspx.
At last I have found the solution (or a solution). This thread's second answer was the key. Basically I had to add an extra (empty) method for each POST method, to deal with the OPTIONS request that some browsers are sending, e.g.:
[OperationContract]
[WebInvoke(Method = "POST", UriTemplate = "/Login", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json)]
Login Login(Login login);
[OperationContract]
[WebInvoke(Method = "OPTIONS", UriTemplate = "/Login", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json)]
Login LoginOptions(Login login);

Visual Studio debugging with windows auth not working

I have an ASP.NET webforms application that uses windows authentication when developing locally. The first time that I debug the webapp, IIS Express starts up and the pages work as expected. If I stop debugging and then start it again, I get in this endless cycle that no matter what page I go to, it always forwards to the login.aspx page and then to my Default.aspx page.
I can keep clicking on different pages, but it still keeps going to the Login then Default. I should be authenticated at this point and not be forwared to login.aspx. I believe it is because IIS express thinks that I am not authenticated. However, when I look at my cookies, I see that there is a ASP.NET_SessionId cookie so I don't think this should be happening.
If this helps, I have this in my page_load for login.aspx
if (authSection.Mode == AuthenticationMode.Windows)
{
//stuff happens here
Response.Redirect("Default.aspx");
return;
}
To fix the problem, I have to kill IIS express and start debugging again. I'm not really sure why it thinks that I am not authenticated. Even though this isn't the same question, I tried the answer provided here: https://stackoverflow.com/a/19515891/888617 and it did not help.
Edit: This actually doesn't appear to solve my issue.
It turns out the issue was specific to Chrome. I was getting this issue when debugging and had to kill the IIS express process for it to resolve itself. However, I found a more perminate solution by doing the following.
In %userprofile%\documents\IISExpress\config\applicationhost.config insure that the overrideModeDefault is set to allowed for windowsAuthentication and anonymousAuthentication like this:
<section name="anonymousAuthentication" overrideModeDefault="Allow" />
<section name="windowsAuthentication" overrideModeDefault="Allow" />
Your authentication section should also look like this. Note the only provider is NTLM.
<authentication>
<anonymousAuthentication enabled="false" userName="" />
<basicAuthentication enabled="false" />
<clientCertificateMappingAuthentication enabled="false" />
<digestAuthentication enabled="false" />
<iisClientCertificateMappingAuthentication enabled="false">
</iisClientCertificateMappingAuthentication>
<windowsAuthentication enabled="true">
<providers>
<add value="NTLM" />
</providers>
</windowsAuthentication>
</authentication>
This section should also be in the web.config.
<authentication>
<windowsAuthentication enabled="true">
<providers>
<clear />
<add value="NTLM" />
</providers>
</windowsAuthentication>
</authentication>

WebDAV and WebAPI together cause Error: Handler "ExtensionlessUrlHandler-Integrated-4.0" has a bad module "ManagedPipelineHandler" in its module list

I have both WebDAV installed and running on my site, as a virtual sub site i have a MVC WebAPI site, the API works great, until I try to send a PUT request to it, then i get the below error:
HTTP Error 500.21 - Internal Server Error
Handler "ExtensionlessUrlHandler-Integrated-4.0" has a bad module "ManagedPipelineHandler" in its module list
If I disable WebDAV, then everything works fine and I get no errors. This only happens when WebDAV is enabled.
I have all of the following code in my web.config:
<system.webServer>
<validation validateIntegratedModeConfiguration="false" />
<modules runAllManagedModulesForAllRequests="false">
<remove name="WebDAVModule" />
</modules>
<handlers>
<remove name="WebDAV" />
<remove name="ExtensionlessUrlHandler-ISAPI-4.0_32bit" />
<remove name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" />
<remove name="ExtensionlessUrlHandler-Integrated-4.0" />
<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>
</system.webServer>
I've tried messing with various app pools.
I've also tired all of the things mentioned in all of these questions:
How to get rid of this error Handler "PageHandlerFactory-Integrated" has a bad module "ManagedPipelineHandler" in its module list
Handler "ExtensionlessUrlHandler-Integrated-4.0" has a bad module "ManagedPipelineHandler" in its module list
How to fix: Handler "PageHandlerFactory-Integrated" has a bad module "ManagedPipelineHandler" in its module list
None of this has solved my issue, is there anything else out there that I have not tried?
We ended up going to Microsoft with this, they reviewed it for several weeks before coming back saying that it's not possible to run WebDAV and WebAPI in the same site.
They will try to address this issue in a future release of IIS.
#jblaske has a good response.
If you want to remove it temporarily then maybe this article is the best solution.
If you want to remove the handler all together then follow these steps.
Open IIS and go to the site in question.
Click on "Handler Mappings"
Find the handler named "WebDAV"
Select it and Remove it
This is my original post.
I started getting this error after I removed WebDAV module and handler manually from IIS to get PUT working. I had to remove "WebDAV Publishing" server role to get over this error. After removing this role and restarting the IIS, PUT is working fine.
You might have a typo issue in the declaration of handlers. Thomas Marquardt's Blog says
5.0 Troubleshooting
If you receive an error similar to the one below, your
section is probably invalid.
HTTP Error 500.21 - Internal Server Error Handler "" has
a bad module "ManagedPipelineHandler" in its module list You probably
have a handler mapping that does not have the correct precondition.
IIS is not forgiving in regard to typos, and preconditions are
case-sensitive. The text must be preCondition=”integratedMode” or
preCondition=”classicMode”.
Also, another suggestion from the comments on that article:
Andrew Johnson 25 Jan 2011 3:20 AM #:
I found that I can also get the "Handler has a bad
module ManagedPipelineHandler in its module list" if the handler has
requireAccess="None". For me, changing this to requireAccess="Read"
made the error go away.
That comment might apply to your case as I see that in applicationHost.config the entry for WebDav handlers is (note the requredAccess="None"):
<add name="WebDAV" path="*" verb="PROPFIND,PROPPATCH,MKCOL,PUT,COPY,DELETE,MOVE,LOCK,UNLOCK" modules="WebDAVModule" resourceType="Unspecified" requireAccess="None" />
Found an alternate for this issue.
When the patches of the server were pushed,The default framework were set back to 2.0.
Re register .Net framework by going to framework 4.0 folder C:\Windows\Microsoft.NET\Framework64\v4.0.30319
Executing the command aspnet_regiis -I
Check the web.config to match the .Net framework version
Go to IIS -> Application pool, set the .Net framework values to 4.0
Restart the IIS.

ASP.NET Membership Provider all user with no email

Does the ASP.NET Membership Provider allow you to create a user with no email address?
I plan to still send the username and password.
<membership defaultProvider="MySqlMembershipProvider">
<providers>
<clear />
<add connectionStringName="SimpleTickConnection" applicationName="TheaterSales" enablePasswordRetrieval="false" enablePasswordReset="true" requiresQuestionAndAnswer="false" requiresUniqueEmail="false" passwordFormat="Hashed" maxInvalidPasswordAttempts="15" minRequiredPasswordLength="7" minRequiredNonalphanumericCharacters="0" passwordAttemptWindow="10" passwordStrengthRegularExpression="" name="MySqlMembershipProvider" type="System.Web.Security.SqlMembershipProvider, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
</providers>
</membership>
I don't think so. I'm not 100% sure but here's a workaround: you can remove the email field from the createuserwizard (if you're using it to register new users) and assign a custom email for all users by handling the CreatingUser event (say noemail#mysite.com).
Also, you should disable RequiresUniqueEmail in your provider (via web.config settings)
If using the CreateUserWizard, setting the RequireEmail to false hides the email text box and removes the email requirement.
e.g
<asp:createuserwizard runat="server" RequireEmail="false">
<WizardSteps>
<asp:CreateUserWizardStep runat="server"/>
<asp:CompleteWizardStep runat="server"/>
</WizardSteps>
</asp:createuserwizard>

Enabling FormsAuthentication for multiple subfolders in a site

We're trying to implement formsAuthentication on our site, but in a scenario that we haven't been able to find a solution for yet - other than creating our own HttpModule and doing the custom logic ourselves - so I thought I'd toss the question out there to see if this was indeed the only solution.
We'd like to use formsAuthentication on top of custom Membership providers, but would like to use a different provider for different folders. Our site partitions these sections with subfolders (eg: ~/Admin, ~/GoldCustomer, ~/SilverCustomer, ~/BronzeCustomer), so we'd like to use different Membership providers for each section/subfolder. Using the framework to support this, we'd implement our web.config like:
<configuration xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0">
<location path="Admin">
<system.web>
<authentication mode="Forms">
<forms name="AdminAuth" loginUrl="~/AdminLogin.aspx" />
</authentication>
<membership defaultProvider="AdminProvider" >
<providers >
<add connectionStringName="ConnString" name="AdminProvider" type="Assembly.AdminMembershipProvider" ... />
</providers>
</membership>
</system.web>
</location>
<location path="GoldCustomer">
<system.web>
<authentication mode="Forms">
<forms name="GoldCustomerAuth" loginUrl="~/GoldCustomerLogin.aspx" />
</authentication>
<membership defaultProvider="GoldCustomerProvider" >
<providers >
<add connectionStringName="ConnString" name="GoldCustomerProvider" type="Assembly.GoldCustomerMembershipProvider" ...="" />
</providers>
</membership>
</system.web>
</location>
<system.web>
<compilation debug="true" />
<authentication mode="Forms" />
</system.web>
</configuration>
Doing this though results in the runtime error:
It is an error to use a section registered as allowDefinition='MachineToApplication' beyond application level. This error can be caused by a virtual directory not being configured as an application in IIS.
Line 11: <location path="Admin">
Line 12: <system.web>
Line 13: <authentication mode="Forms">
Line 14: <forms name="FormsAdmin" loginUrl="~/login.aspx" />
Line 15: </authentication>
It seems that the only way to accomplish what we're trying is with a custom HttpModule - or change our approach (like breaking the folders up into different web apps in IIS). Is this correct, or am I missing something? Or are there other alternatives I'm not aware of?
Thanks for your help!
First of all, I think role-based security makes perfect sense for your application if you have control over the databases. But if you can't change it, it's a no-go.
The alternative solution can be a gateway login forms that redirects user to folder specific login form based on ReturnUrl querystring variable and that form will use the provider it wants to validate the user. Then it uses the FormsAuthentication.RedirectFromLoginPage to set an authentication cookie and redirect to the previous page. You can set the roles and use role based security to control access to each folder with <authorization> tag in web.config.
I'm not sure what you're trying to do but how about Roles for each of these customer types? Limit access by a role for each sub folder but you'd still have 1 membership provider and 1 role provider.

Resources