Forms authentication ignored in virtual application - asp.net

I have an admin site set up as a virtual applcation inside of another website.
I would like visitors to the sub directory (the virtual application) to be promtped for credentials using the same Forms authentication set up on the main parent site
Have tried all sorts of things but can't get it to work, including
Removing all <authentication mode="Forms">, <authorization>, <membership> and <roles> sections from the virtual-app web.config
Copying the same <authentication mode="Forms">, <authorization>, <membership> and <roles> sections from the parent to the virtual-app web.config
Using a virtual directory instead of virtual application
But I never get promted for credentials
Anyone know how to get this setup?
thanks
UPDATE:
Have now got it to inherit permissions from the parent, by deleting the application name in IIS (to make it a virtual directory rather than a virtual application)
However, this screws all the paths in the admin site
e.g. I get the following error
The file '/Site.master' does not exist.
So should I be using a virtual directory (which seems to inherit authentication from the parent)?
Or a virtual application (which currently doesn't inherit auth from the parent but has the correct relative paths)?
Here's the parent config
<membership defaultProvider="SqlServerMembershipProvider">
<providers>
<add connectionStringName="xxxxxxxx" requiresQuestionAndAnswer="false" applicationName="/" requiresUniqueEmail="true" passwordFormat="Hashed" maxInvalidPasswordAttempts="5" minRequiredPasswordLength="7" minRequiredNonalphanumericCharacters="0" passwordAttemptWindow="10" passwordStrengthRegularExpression="" name="SqlServerMembershipProvider" type="System.Web.Security.SqlMembershipProvider, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"/>
</providers>
</membership>
<roleManager enabled="true" defaultProvider="SqlServerRoleProvider">
<providers>
<add connectionStringName="xxxxxxx" applicationName="/" name="SqlServerRoleProvider" type="System.Web.Security.SqlRoleProvider, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"/>
</providers>
</roleManager>
<authentication mode="Forms">
<forms name=".EPiServerLogin" loginUrl="login.aspx" timeout="120"/>
</authentication>
<authorization>
<deny users="?"/>
</authorization>

I needed to use a single sign on solution, as described here
http://www.codeproject.com/KB/aspnet/SingleSignon.aspx
The main point being, each site needs to use the same encryption key for the cookie values. So this machineKey element needs to be added to each site involved in the Single Sign On

How have you configured authorization?
Also, I assume you're not already authenticated in the parent site?
In the admin subdirectory you should have something like the following in your web.config (obviously you may have more information in there as well):
<configuration>
<system.web>
<authorization>
<deny users="?" />
</authorization>
</system.web>
</configuration>
This will deny all anonymous users, but allow all authenticated users access. You can easily extend this if you are using a Role Provider to only allow certain roles:
<allow roles="Admin" />
<deny users="*" />
Note that you need the "Deny all users" in there, as the default behaviour is to allow all users. Authorization works "top down" in that it starts at the top of the list, and as soon as it finds a match, it stops processing, so if the user is in the "Admin" role, it will not get to the "Deny all users" rule.
You can also configure this in the root web.config using a <location> element.
Responding to comments
And your authentication/authorization all works in the parent site?
Could you edit your question to include (sanitised) web.config sections you've tried so we can see if there's anything obvious missing - for example, if you're using Roles to lock down the admin area, you have enabled it (<roleManager enabled="true">, defaults to false).

We do what you're trying to do quite often here.
We do it this way : The root level is a virtual application, it contains the master web.config and global.ascx. We have a normal folder, 'Admin' inside of that. Inside of that, we have a small web.config, it only contains <authorization> XML information. You'll need a login page somewhere, either the root or Admin folder.
I was a little confused in your post about whether there are three applications/directories involved (app, parent app, app's admin), or only two (app & it's admin). I'm making a critical assumption here that it's two. If you do have the three, it's going to be some more work to get this thing going.

Related

"Trust relationship between ... and the primary domain failed" in MVC5 Authentication

I have a ASP .NET MVC5 application in which I am not using Windows Authentication.
Everything was working fine until I tried running the application outside of the Domain in which it was being developed and (for whatever reason) got a:
The trust relationship between this workstation and the primary domain failed.
when I'm trying to do User.IsInRole("Admin").
I am using custom Identity, Role, IdentityStore, RoleStore, etc. from .NET's Identity and I can see that the User and Role data is being retrieved from the (MongoDB) database correctly.
There are plenty of questions regarding this issue, but they're from people who want to use Windows Auth. and impersonation in their MVC applications:
With windows authentication, The trust relationship between the primary domain and the trusted domain failed, when calling IsInRole
How to configure Windows Authentication / Impersonation + IIS 7 + MVC
The trust relationship between the primary domain and the trusted domain failed
My.User.IsInRole("Role Name") throws a Trust Relationship error on Windows 7
So why exactly am I getting this SystemException if I'm not using Active Directory and (as far as I know) not doing anything that might depend on the PC's domain? Am I missing some configuration (either in my Web.config or IIS Express)?
EDIT:
Ok, so narrowing it down a bit...
My User.IsInRole("Admin") line is inside an if() statement in my _Layout.cshtml View (i.e., to know what to show in the nav. bar depending on the role).
I now know I only get the error above when no user is authenticated and I'm not in the domain I used for dev. If I place a breakpoint on that line, I can see that the User object is is a System.Security.Principal.WindowsIdentity and its underlying Identity is System.Security.Principal.WindowsIdentity.
On the other hand, if the user is authenticated, then the User object and ts Identity are System.Security.Claims.ClaimsPrincipal and System.Security.Claims.ClaimsIdentity.
Why is it using Windows Identity at all (when unauthenticated) and how can I disable it?
So, based on my EDIT, I've modified my _Layout.cshtml so that instead of having
#if(User.IsInRole("Admin")) {...}
I have
#if(User.Identity.IsAuthenticated && User.IsInRole("Admin")) {...}
which seems to solve the problem.
I believe the problem was that ASP .NET Identity uses an empty WindowsIdentity when no user is authenticated and when I try to check for the User.IsInRole, then it will try to check the roles of a WindowsIdentity against an Active Directory that I don't have. Obviously I should first check if the user is even logged in before attempting to check its roles, so mea culpa.
But, even though the change above seems to fix my code, I'd be very interested in knowing more about this behavior: why is it using an empty System.Security.Principal.WindowsIdentity when no user is authenticated. I'll accept any answer which explains that.
I've had this issue - It failed for me if I tested an active directory group that didn't exist.
Make sure you're using a group that exists!
I was having this issue with Asp.Net Core 3.1 with Windows Authentication, but this thread came up first when searching the internet. I ended up resolving the issue by decorating the controller class declaration with the following:
using Microsoft.AspNetCore.Authorization;
[Authorize]
public class SetupController : Controller
Hope this is helpful for someone that is using Windows Authentication and is having the same error.
We were having this same issue on a new production server. Using the Identity Framework and restricting access to a specific directory with a web.config file denying any unauthenticated users. When unauthenticated users tried to access a page in this directory that contained any User.IsInRole("RoleName") code, they were getting the "Trust relationship..." error.
None of the fixes mentioned in other SO answers worked for us.
Turns out we just had to enable Forms Authentication in IIS - problem solved.
The "trust relationship between the primary domain and the workstation has failed" error message usaully requires that the computer be removed from the domain and then rejoined. Now there are a few ways to do this. As included in the link above, are instructions on how to do so either on the computer displaying the error or remotely. You can also do so in Active Directory and in PowerShell.
<authorization>
<allow roles="pri\Domain Users" users="pri\domain_user" />
<deny users="?" />
</authorization>
make sure that you have the above line in your web.config file and complete the user field with the correct user name.
I've just resolved this in our systems, unfortunately, none of the other suggestions worked for me. The issue was caused by an orphaned SID in a network folder the code was attempting to access. Once removed it started working again.
I had exactly the same scenario with custom Authentication Module and the same error when doing IsInRole. The highest ranking solution (User.Identity.IsAuthenticated && ...) did NOT help. So, I played quite a bit with it. Finally I found that I had to remove a (preCondition="managedHandler") attribute from my module declaration in web.config file. So, instead of:
<system.webServer>
...
<modules>
...
<add name="CompanyAuthentication" type="Company.Authentication.AuthHttpHandler" preCondition="managedHandler" />
</modules>
I would have to have:
<system.webServer>
...
<modules>
...
<add name="CompanyAuthentication" type="Company.Authentication.AuthHttpHandler" />
</modules>
That did the trick for me!
For me, the whole membership provider configuration tags were missing. After i copy those from one our previous apps, it worked fine.
<system.web>
<authentication mode="Windows" />
<compilation debug="true" targetFramework="4.7.1" />
<httpRuntime targetFramework="4.7.1" />
<httpModules>
<add name="TelemetryCorrelationHttpModule" type="Microsoft.AspNet.TelemetryCorrelation.TelemetryCorrelationHttpModule, Microsoft.AspNet.TelemetryCorrelation" />
<add name="ApplicationInsightsWebTracking" type="Microsoft.ApplicationInsights.Web.ApplicationInsightsHttpModule, Microsoft.AI.Web" />
</httpModules>
<profile defaultProvider="DefaultProfileProvider">
<providers>
<add name="DefaultProfileProvider" type="System.Web.Providers.DefaultProfileProvider, System.Web.Providers, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" connectionStringName="DefaultConnection" applicationName="/" />
</providers>
</profile>
<membership defaultProvider="DefaultMembershipProvider">
<providers>
<add name="DefaultMembershipProvider" type="System.Web.Providers.DefaultMembershipProvider, System.Web.Providers, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" connectionStringName="DefaultConnection" enablePasswordRetrieval="false" enablePasswordReset="true" requiresQuestionAndAnswer="false" requiresUniqueEmail="false" maxInvalidPasswordAttempts="5" minRequiredPasswordLength="6" minRequiredNonalphanumericCharacters="0" passwordAttemptWindow="10" applicationName="/" />
</providers>
</membership>
<roleManager defaultProvider="CustomRoleProvider" enabled="true" cacheRolesInCookie="false">
<providers>
<add name="CustomRoleProvider" type="ABC.ABCModels.ABCRoleProvider" />
</providers>
</roleManager>
<sessionState mode="InProc" customProvider="DefaultSessionProvider">
<providers>
<add name="DefaultSessionProvider" type="System.Web.Providers.DefaultSessionStateProvider, System.Web.Providers, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" connectionStringName="DefaultConnection" />
</providers>
</sessionState>
On my case, I am not using User.Identity but rather Thread.CurrentPrincipal.Identity.Name
So when I approach this line of code:
Thread.CurrentPrincipal.IsInRole("admin");
That's where I will encounter the same error message of:
The trust relationship between this workstation and the primary domain failed.
There are two cases why I encountered the same issue and of course the fixes I made:
I was disconnected with my VPN. This will look for the role that doesn't exist since I am not connected with my VPN and not connecting with my AD accounts.
If I am connected with my VPN and the role admin doesn't exist based on my code above, it will certainly trigger the same error message.
I think it is worth sharing how I've fixed on my situation as these answers helped me to figure it out.
We were allowing/restricting access to pages via web.config and this was happening before touching any code (so it didn't matter where the breakpoint was, the error was coming).
Since this was not amazing too, I've decided to implement this validation in the code manually instead of using the web.config one.
our web.config used to look like this:
<configuration>
<system.web>
<authorization>
<allow roles="10,5"/>
<deny users="*"/>
</authorization>
</system.web>
</configuration>
We've changed to:
Created a page (called restricted page) that inherits from Page
This page has a protected variable called RequiredAccessLevel
The OnLoad of the page we check if the user is in the role of the RequiredAccessLevel and if it is not, we redirect to a custom AccessDenied page
Made the pages that should have this restriction inherit from RestrictedPage instead of Page
On the constructor of the pages that are inheriting from RestrictedPage we set the access level necessary
Like this:
RestrictedPage.cs
public class RestrictedPage : Page
{
protected int[] RequiredAccessLevel { get; set; } = { };
protected override void OnLoad(EventArgs e)
{
if (RequiredAccessLevel.Length > 0)
{
var allowed = false;
foreach (var ral in RequiredAccessLevel)
{
if (Page.User.IsInRole(ral.ToString()))
{
allowed = true;
break;
}
}
if (!allowed)
{
Response.Redirect("~/AccessDenied.aspx");
}
}
base.OnLoad(e);
}
}
Example.cs
public partial class Example: RestrictedPage
{
public Example()
{
RequiredAccessLevel = new[] {10};
}
}

all requests to umbraco site redirect to login page

I just took my local, functioning umbraco installation and copied it over to the testing environment.
Suddenly ALL requests to my umbraco site, meaning css, javascript etc redirect to the login.aspx page. So the website is non-functional, unless you login. If you manage to login using the no-css form, then everything is back to normal.
Web.config says
<authentication mode="Forms">
<forms name="yourAuthCookie" loginUrl="login.aspx" protection="All" path="/" timeout="120" />
</authentication>
<authorization>
<allow users="*" />
</authorization>
Changing * to ? makes no difference. What could be the matter here? My setup is 2 configuration mirroring IIS7 web servers, looking at a common UNC path.
I think you should check permissions setting of your environment, because if you get redirect for all resources, even for static files - usually it is common permissions problem.
/install/default.aspx?installStep=validatePermissions
or for 4.7+
/install/?installStep=filepermissions
http://our.umbraco.org/wiki/reference/files-and-folders/permissions/perform-permissions-check
It can be a issue with file permissions. As a temporary solution try and set all files to "Everyone" - Modify.
All paths are only accessible with authentication, so you have to exclude js and css from authentication in your web.config, e.g.:
<configuration>
<location path="css">
<system.web>
<authorization>
<allow users="*"/>
</authorization>
</system.web>
</location>
</configuration>
You need to specify allow users="?" to allow anonymous users.
Check also the section membership...
My web.config contains:
<membership defaultProvider="UmbracoMembershipProvider" userIsOnlineTimeWindow="15">
<providers>
<clear />
<add name="UmbracoMembershipProvider" type="umbraco.providers.members.UmbracoMembershipProvider" enablePasswordRetrieval="false" enablePasswordReset="false" requiresQuestionAndAnswer="false" defaultMemberTypeAlias="Another Type" passwordFormat="Hashed" />
<add name="UsersMembershipProvider" type="umbraco.providers.UsersMembershipProvider" enablePasswordRetrieval="false" enablePasswordReset="false" requiresQuestionAndAnswer="false" passwordFormat="Hashed" />
</providers>
</membership>
You need to:
Create a login page (like any other ASP.NET site).
Create records in
"Members" section (at least one member type, member group and
member).
Define the restricted access on content nodes (menu "Public
access").
I recently experienced this also on a test Umbraco site. Discovered it was owing to the files attempting to access being stored on the disk encrypted (using Windows 7 in my test environment).
Fixed by selecting all site files and folders in Explorer, Properties, Advanced (on General tab), uncheck "Encrypt contents to secure data". Resources could then be accessed on the Umbraco without any authentication redirects.

Turning off ASP.Net WebForms authentication for one sub-directory

I have a large enterprise application containing both WebForms and MVC pages. It has existing authentication and authorisation settings that I don't want to change.
The WebForms authentication is configured in the web.config:
<authentication mode="Forms">
<forms blah... blah... blah />
</authentication>
<authorization>
<deny users="?" />
</authorization>
Fairly standard so far. I have a REST service that is part of this big application and I want to use HTTP authentication instead for this one service.
So, when a user attempts to get JSON data from the REST service it returns an HTTP 401 status and a WWW-Authenticate header. If they respond with a correctly formed HTTP Authorization response it lets them in.
The problem is that WebForms overrides this at a low level - if you return 401 (Unauthorised) it overrides that with a 302 (redirection to login page). That's fine in the browser but useless for a REST service.
I want to turn off the authentication setting in the web.config, overriding the 'rest' folder:
<location path="rest">
<system.web>
<authentication mode="None" />
<authorization><allow users="?" /></authorization>
</system.web>
</location>
The authorisation bit works fine, but the authentication line (<authentication mode="None" />) causes an exception:
It is an error to use a section registered as allowDefinition='MachineToApplication' beyond application level.
I'm configuring this at application level though - it's in the root web.config - and that error is for web.configs in sub-directories.
How do I override the authentication so that all of the rest of the site uses WebForms authentication and this one directory uses none?
This is similar to another question: 401 response code for json requests with ASP.NET MVC, but I'm not looking for the same solution - I don't want to just remove the WebForms authentication and add new custom code globally, there's far to much risk and work involved. I want to change just the one directory in configuration.
Update
I want to set up a single web application and in that I want all the WebForms pages and MVC views to use WebForms authentication. I want one directory to use basic HTTP authentication.
Note that I'm talking about authentication, not authorisation. I want REST calls to come with the username & password in an HTTP header, and I want WebForm & MVC pages to come with the authentication cookie from .Net - in either case authorisation is done against our DB.
I don't want to rewrite WebForms authentication and roll my own cookies - it seems ridiculous that is the only way to add an HTTP authorised REST service to an application.
I can't add an additional application or virtual directory - it's got to be as one application.
If "rest" is simply a folder in your root you are almost there:
remove authentication line i.e.
<location path="rest">
<system.web>
<authorization>
<allow users="*" />
</authorization>
</system.web>
</location>
Alternatively you can add a web.config to your rest folder and just have this:
<system.web>
<authorization>
<allow users="*" />
</authorization>
</system.web>
Check this one.
I've worked around this the messy way - by spoofing the Forms authentication in the global.asax for all the existing pages.
I still don't quite have this fully working, but it goes something like this:
protected void Application_BeginRequest(object sender, EventArgs e)
{
// lots of existing web.config controls for which webforms folders can be accessed
// read the config and skip checks for pages that authorise anon users by having
// <allow users="?" /> as the top rule.
// check local config
var localAuthSection = ConfigurationManager.GetSection("system.web/authorization") as AuthorizationSection;
// this assumes that the first rule will be <allow users="?" />
var localRule = localAuthSection.Rules[0];
if (localRule.Action == AuthorizationRuleAction.Allow &&
localRule.Users.Contains("?"))
{
// then skip the rest
return;
}
// get the web.config and check locations
var conf = WebConfigurationManager.OpenWebConfiguration("~");
foreach (ConfigurationLocation loc in conf.Locations)
{
// find whether we're in a location with overridden config
if (this.Request.Path.StartsWith(loc.Path, StringComparison.OrdinalIgnoreCase) ||
this.Request.Path.TrimStart('/').StartsWith(loc.Path, StringComparison.OrdinalIgnoreCase))
{
// get the location's config
var locConf = loc.OpenConfiguration();
var authSection = locConf.GetSection("system.web/authorization") as AuthorizationSection;
if (authSection != null)
{
// this assumes that the first rule will be <allow users="?" />
var rule = authSection.Rules[0];
if (rule.Action == AuthorizationRuleAction.Allow &&
rule.Users.Contains("?"))
{
// then skip the rest
return;
}
}
}
}
var cookie = this.Request.Cookies[FormsAuthentication.FormsCookieName];
if (cookie == null ||
string.IsNullOrEmpty(cookie.Value))
{
// no or blank cookie
FormsAuthentication.RedirectToLoginPage();
}
// decrypt the
var ticket = FormsAuthentication.Decrypt(cookie.Value);
if (ticket == null ||
ticket.Expired)
{
// invalid cookie
FormsAuthentication.RedirectToLoginPage();
}
// renew ticket if needed
var newTicket = ticket;
if (FormsAuthentication.SlidingExpiration)
{
newTicket = FormsAuthentication.RenewTicketIfOld(ticket);
}
// set the user so that .IsAuthenticated becomes true
// then the existing checks for user should work
HttpContext.Current.User = new GenericPrincipal(new FormsIdentity(newTicket), newTicket.UserData.Split(','));
}
I'm not really happy with this as a fix - it seems like a horrible hack and re-invention of the wheel, but it looks like this is the only way for my Forms-authenticated pages and HTTP-authenticated REST service to work in the same application.
I found myself with the same exact problem, the following article pointed me in the right direction: http://msdn.microsoft.com/en-us/library/aa479391.aspx
MADAM does exactly what you are after, specifically, you can configure the FormsAuthenticationDispositionModule to mute the forms authentication "trickery", and stop it from changing the response code from 401 to 302. This should result in your rest client receiving the right auth challenge.
MADAM Download page: http://www.raboof.com/projects/madam/
In my case, the REST calls are made to controllers (this is a MVC based app) in the "API"
area. A MADAM discriminator is set with the following configuracion:
<formsAuthenticationDisposition>
<discriminators all="1">
<discriminator type="Madam.Discriminator">
<discriminator
inputExpression="Request.Url"
pattern="api\.*" type="Madam.RegexDiscriminator" />
</discriminator>
</discriminators>
</formsAuthenticationDisposition>
Then all you have to do is add the MADAM module to your web.config
<modules runAllManagedModulesForAllRequests="true">
<remove name="WebDAVModule" /> <!-- allow PUT and DELETE methods -->
<add name="FormsAuthenticationDisposition" type="Madam.FormsAuthenticationDispositionModule, Madam" />
</modules>
Remember to add the valid sections to the web.config (SO didn't let me paste the code), you can get an example from the web project in the download.
With this setup any requests made to URLs starting with "API/" will get a 401 response instead of the 301 produced by the Forms Authentication.
I was able to get this to work on a previous project, but it did require using an HTTP module to perform the custom basic authentication, since account validation is against a database rather than Windows.
I set up the test as you specified with one one web application at the root of the test website, and a folder containing the REST service. The config for the root application was configured to deny all access:
<authentication mode="Forms">
<forms loginUrl="Login.aspx" timeout="2880" />
</authentication>
<authorization>
<deny users="?"/>
</authorization>
I then had to create an application for the REST folder in IIS, and place a web.config file into the REST folder. In that config, I specified the following:
<authentication mode="None"/>
<authorization>
<deny users="?"/>
</authorization>
I also had to wire up the http module in the appropriate places within the REST directory's config. This module must go into a bin directory under the REST directory. I used Dominick Baier's custom basic authentication module, and that code is located here. That version is more IIS 6 specific, however there is a version for IIS 7 as well on codeplex, but I haven't test that one (warning: the IIS6 version does not have the same assembly name and namespace as the IIS7 version.) I really like this basic auth module since it plugs right into ASP.NET's membership model.
The last step was to ensure that only anonymous access was allowed to both the root application and the REST application within IIS.
I've included the full configs below for completeness. The test app was just a ASP.NET web form application generated from VS 2010, it was using the AspNetSqlProfileProvider for the membership provider; here's the config:
<?xml version="1.0"?>
<configuration>
<connectionStrings>
<add name="ApplicationServices"
connectionString="data source=.\SQLEXPRESS;Integrated Security=SSPI;Database=sqlmembership;"
providerName="System.Data.SqlClient" />
</connectionStrings>
<system.web>
<compilation debug="true" targetFramework="4.0" />
<authentication mode="Forms">
<forms loginUrl="~/Account/Login.aspx" timeout="2880" />
</authentication>
<authorization>
<deny users="?"/>
</authorization>
<membership>
<providers>
<clear/>
<add name="AspNetSqlMembershipProvider" type="System.Web.Security.SqlMembershipProvider" connectionStringName="ApplicationServices"
enablePasswordRetrieval="false" enablePasswordReset="true" requiresQuestionAndAnswer="false" requiresUniqueEmail="false"
maxInvalidPasswordAttempts="5" minRequiredPasswordLength="6" minRequiredNonalphanumericCharacters="0" passwordAttemptWindow="10"
applicationName="/" />
</providers>
</membership>
<profile>
<providers>
<clear/>
<add name="AspNetSqlProfileProvider" type="System.Web.Profile.SqlProfileProvider" connectionStringName="ApplicationServices" applicationName="/"/>
</providers>
</profile>
<roleManager enabled="false">
<providers>
<clear/>
<add name="AspNetSqlRoleProvider" type="System.Web.Security.SqlRoleProvider" connectionStringName="ApplicationServices" applicationName="/" />
<add name="AspNetWindowsTokenRoleProvider" type="System.Web.Security.WindowsTokenRoleProvider" applicationName="/" />
</providers>
</roleManager>
</system.web>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
</system.webServer>
</configuration>
The REST directory contained an empty ASP.NET project generated from VS 2010, and I put a single ASPX file into that, however the contents of the REST folder didn't have to be a new project. Just dropping in a config file after the directory has had an application associated with it should work. The config for that project follows:
<?xml version="1.0"?>
<configuration>
<configSections>
<section name="customBasicAuthentication" type="Thinktecture.CustomBasicAuthentication.CustomBasicAuthenticationSection, Thinktecture.CustomBasicAuthenticationModule"/>
</configSections>
<customBasicAuthentication
enabled="true"
realm="testdomain"
providerName="AspNetSqlMembershipProvider"
cachingEnabled="true"
cachingDuration="15"
requireSSL="false" />
<system.web>
<authentication mode="None"/>
<authorization>
<deny users="?"/>
</authorization>
<compilation debug="true" targetFramework="4.0" />
<httpModules>
<add name="CustomBasicAuthentication" type="Thinktecture.CustomBasicAuthentication.CustomBasicAuthenticationModule, Thinktecture.CustomBasicAuthenticationModule"/>
</httpModules>
</system.web>
</configuration>
I hope this will meet your needs.
In .NET 4.5 you can now set
Response.SuppressFormsAuthenticationRedirect = true
Check this page: https://msdn.microsoft.com/en-us/library/system.web.httpresponse.suppressformsauthenticationredirect.aspx
This may not be the most elegant of solutions but I think it is a good start
1)Create a HttpModule.
2)handle the AuthenticateRequest event.
3)in the event handler check that the request is to the directory that you want to allow access to.
4)If it is then manually set the auth cookie: (or see if you can find another way now that you have control and authentication has not yet happened)
FormsAuthentication.SetAuthCookie("Anonymous", false);
5) Oh almost forgot, you would want to make sure the auth cookie was cleared if the request was not to the directory that you wanted to grant access to.
After looking at your comments to my previous answer, I wondered if you could have your web app automate the deployment of an application on your REST directory. That would allow you to have the benefits of a second application, and would also reduce the deployment burden on your system admins.
My thought was that you could put a routine into the Application_Start method of the global.asax that would check that the REST directory exists, and that it does not already have an application associated with it. If the test returns true, then the process of associating a new application to the REST directory occurs.
Another thought I had was that you could use WIX (or another deployment technology) to build a install package that your admins could run to create the application, however I don't think that's as automatic as having the app configure its dependency.
Below, I've included a sample implementation that checks IIS for a given directory and applies an application to it if it does not already have one. The code was tested with IIS 7, but should work on IIS 6 as well.
//This is part of global.asax.cs
//This approach may require additional user privileges to query IIS
//using System.DirectoryServices;
//using System.Runtime.InteropServices;
protected void Application_Start(object sender, EventArgs evt)
{
const string iisRootUri = "IIS://localhost/W3SVC/1/Root";
const string restPhysicalPath = #"C:\inetpub\wwwroot\Rest";
const string restVirtualPath = "Rest";
if (!Directory.Exists(restPhysicalPath))
{
// there is no rest path, so do nothing
return;
}
using (var root = new DirectoryEntry(iisRootUri))
{
DirectoryEntries children = root.Children;
try
{
using (DirectoryEntry rest = children.Find(restVirtualPath, root.SchemaClassName))
{
// the above call throws an exception if the vdir does not exist
return;
}
}
catch (COMException e)
{
// something got unlinked incorrectly, kill the vdir and application
foreach (DirectoryEntry entry in children)
{
if (string.Compare(entry.Name, restVirtualPath, true) == 0)
{
entry.DeleteTree();
}
}
}
catch (DirectoryNotFoundException e)
{
// the vdir and application do not exist, add them below
}
using (DirectoryEntry rest = children.Add(restVirtualPath, root.SchemaClassName))
{
rest.CommitChanges();
rest.Properties["Path"].Value = restPhysicalPath;
rest.Properties["AccessRead"].Add(true);
rest.Properties["AccessScript"].Add(true);
rest.Invoke("AppCreate2", true);
rest.Properties["AppFriendlyName"].Add(restVirtualPath);
rest.CommitChanges();
}
}
}
Portions of this code came from here. Good luck with your app!

Asp.net User Roles Management: Where to Begin

I'm new to User Roles Management. I was reading my Wrox Programming book on asp.net 3.5 user role management...but it was hard to follow along, as I do not have a local server set up to test on (I do...but...thats a separate question), but rather currently test on a remote server (where the website is hosted, theres not enough hits where I can get away with testing on a live server).
Any ways...Where do I begin in user role management. I'm not necessarily asking to be given a 30 pg hard description, but more of a summary. My GoDaddy hosting account seems to offer asp.net schemea SQL database set up for user role management, but I have yet to learn how to integrate it into my development.
Any input would be appreciated.
I would open up Visual Studio, create a new ASP.NET Web Application project, and click the "Configure ASP.NET" button on the top-right hand corner of the Solution Explorer. If you navigate to the Security section, you can start creating Users and Roles. The tool basically describes exactly how they work to you.
Here's the first place I'd go:
http://www.asp.net/Learn/Security/
Check out tutorials 9 through 11.
You can use SqlRoleProviders and SqlMembershipProviders with the .NET default management, or you can write your own providers.
http://www.odetocode.com/Articles/427.aspx
http://msdn.microsoft.com/en-us/library/aa478949.aspx
Then these are used in conjunction with asp .net forms authentication.
<authentication mode="Forms">
<forms name=".ASPXFORMSAUTH" loginUrl="~/Common/Login.aspx" timeout="450" />
</authentication>
<authorization>
<deny users="?" />
<allow roles="Admin" />
</authorization>
The configuration of all of this is via the web.config your membership and roles may be similar to this if you use the out of the box aspnetdb.
<membership defaultProvider="IDTSqlMembershipProvider" userIsOnlineTimeWindow="15">
<providers>
<clear />
<add
name="IDTSqlMembershipProvider"
type="System.Web.Security.SqlMembershipProvider"
connectionStringName="SqlMembershipConnectionString"
applicationName="ConsumerSynergy"
enablePasswordRetrieval="false"
enablePasswordReset="true"
requiresQuestionAndAnswer="false"
requiresUniqueEmail="true"
passwordFormat="Hashed"
maxInvalidPasswordAttempts="20"
minRequiredPasswordLength="6"
minRequiredNonalphanumericCharacters="0" />
</providers>
</membership>
<roleManager enabled="true" defaultProvider="IDTSqlRoleProvider" cacheRolesInCookie="true" cookieProtection="All">
<providers>
<clear/>
<add
name="IDTSqlRoleProvider"
type="System.Web.Security.SqlRoleProvider"
connectionStringName="SqlMembershipConnectionString"
applicationName="ConsumerSynergy"/>
</providers>
</roleManager>
My personal favorite about roles.
Examining ASP.NET's Membership, Roles, and Profile - Part 2
https://web.archive.org/web/20210417083524/https://www.4guysfromrolla.com/articles/121405-1.aspx

ASP:Login Not Authenticating

I am currently learning form authentication using a SQLMembership provider. The ASP:Login control does not seem to authenticate. Here is the structure of my test site on my local machine:
~/LoginTest/
Default.aspx
CreateUser.aspx
lostpassword.aspx
web.config
/login/
Login.aspx
ProtectedStuff.aspx
web.config
In the web.config file of the LoginTest folder I have added the following nodes:
<connectionStrings>
<add name="EvgSqlConnection" connectionString="connection string" />
</connectionStrings>
<authentication mode="Forms">
<forms name="LoginTest" loginUrl="~/login/Login.aspx" path="/login"
cookieless="UseCookies" />
</authentication>
<membership defaultProvider="mySqlProvider" userIsOnlineTimeWindow="15">
<providers>
<clear/>
<add
name="mySqlProvider"
type="System.Web.Security.SqlMembershipProvider"
connectionStringName="EvgSqlConnection"
applicationName="LoginTest"
enablePasswordRetrieval="false"
enablePasswordReset="true"
requiresQuestionAndAnswer="true"
requiresUniqueEmail="true"
passwordFormat="Hashed" />
</providers>
</membership>
<roleManager enabled="true" defaultProvider="mySqlRoleProvider" cacheRolesInCookie="true" cookieProtection="All">
<providers>
<clear/>
<add name="mySqlRoleProvider" applicationName="LoginTest" connectionStringName="EvgSqlConnection"
type="System.Web.Security.SqlRoleProvider"/>
</providers>
</roleManager>
In the web.config in the login folder I have the following:
<configuration>
<appSettings/>
<connectionStrings/>
<system.web>
<authorization>
<deny users="?" />
<allow users="*" />
</authorization>
</system.web>
</configuration>
So what this is supposed to do from what I have read is deny users access to anything in the login folder. In this case my test file is ProtectedStuff.aspx which is nothing more than a page with a label. What is currently happening is that everything seems to work except the ASP:Login control. I can currently create a new user with the ASP:CreateUserWizard on CreateUser.aspx. I can recover a new password using the question and answer set up using the ASP:PasswordRecovery control on lostpassword.aspx. I can enter the correct name and password in the ASP:Login control on Login.aspx. The only thing that doesn't seem to work is the actual authentication. Whenever I try to go to ProtectedStuff.aspx it kicks me back to Login.aspx like it is supposed to when you are not authenticated. Further, I can enter the wrong user name or wrong password and the Login control complains. I can see my user in the website administration page, I can see that the user is assigned a role.
There is no custom code behind any of these controls, all I have done is copied in the SqlProvider name into the MembershipProvider attribute of these controls. SQL Server 2000 is configured with an NT AUTHORITY\Network Service user that has aspnet_Membership Full Access checked. the config files seem to be okay, all the controls seem to be able to read and write to the database correctly, only the Login control doesn't seem to authenticate the user. What else should I be looking for?
I'd start by removing the path attribute from your Forms element:
Specifies the path for cookies issued by the application. The default value is a slash (/), because most browsers are case-sensitive and will not send cookies back if there is a path case mismatch.
If that still fails, I'd get hold of Fiddler and see what cookies are being sent back to the client and to the server after logging in.

Resources