Reading AuthorizationSection from web.config provides incorrect values - c#

Edit #2: config.FilePath is showing that it's looking at a different file than what I'm expecting: "C:\Windows\Microsoft.NET\Framework64\v4.0.30319\Config\web.config". I was expecting it to use the web.config in my project. Need to figure out why that's happening.
I have a method in my web API where I'm trying to read the values from the authorization section in my web.config. Based on what I've found, this should work:
public AuthorizationSetting GetAuthorizationSettings()
{
var config = WebConfigurationManager.OpenWebConfiguration(null);
var section = config.GetSection("system.web/authorization") as AuthorizationSection;
foreach (AuthorizationRule rule in section.Rules)
{
if (rule.Action.ToString().ToLower() == "allow")
{
Debug.WriteLine(rule);
}
}
return new AuthorizationSetting();
}
And this is the section of the web.config that contains the authorization info:
<system.web>
<compilation debug="true" targetFramework="4.5" />
<httpRuntime targetFramework="4.5" />
<identity impersonate="true" />
<authentication mode="Windows" />
<authorization>
<allow roles="role1,role2,role3"/>
<deny users="*"/>
</authorization>
</system.web>
You can see that there is one allow and one deny. When I run the code, it appears that there is only one rule. Shouldn't there be two since there is an allow and a deny? And the one rule looks to have an Action of Allow and "*" for Users. That's not what's in the web.config. What am I missing here?
** Edit **
I've considered the possibility that it's reading a different web.config file. But there is only one other web.config file in the solution (under Views). I also changed it to have the same authorization section, but I still get the same result.

As you already figured out using Null in for the path parameter of OpenWebConfiguration loads the server root web.config in
%SystemRoot%\Microsoft.NET\Framework64\v4.0.30319\Config\
the documentation says:
The virtual path to the configuration file. If null, the root Web.config file is opened.
but one could assume it would be the root web config of the site, not the server. Anyway, try using:
var config = WebConfigurationManager.OpenWebConfiguration("~");

Related

Receiving a 500 error when configuring an ASP.NET login page

I want to add a login page to an ASP.NET Framework site, but the compiler doesn’t even load the view, instead throwing an error on the configuration.
The web.config contains the following configuration:
<authentication mode="Forms">
<forms loginUrl="/Login/Login"></forms>
</authentication>
My LoginController contains the following:
public class LoginController : Controller
{
[HttpGet]
public ActionResult Login()
{
return View();
}
}
But this is the error I receive:
The configuration section 'authentication' cannot be read because it is missing a section declaration
The <authentication/> element was first introduced in ASP.NET 2.0 as part of Forms-Based Authentication, which appears to be what you’re trying to configure.
If so, it is expected under the <system.web /> element (source):
<configuration>
<system.web>
<authentication mode="Forms">
<forms loginUrl="/Login/Login"></forms>
</authentication>
</system.web>
</configuration>
You don’t provide the full context for your web.config file, but according to the screenshot of the error message, it appears as though you’ve inadvertently placed your <authentication /> element as a sibling of the <system.web /> element, not as a child.
The error message here certainly isn’t intuitive. But placing the <authentication /> element under the system.web element should resolve your issue.
Note: Since Internet Information Server (IIS) 7, there is also an <authentication /> element located under the <system.webServer /> element, under <security/> (source). This is a used to configure IIS’s authentication, and is independent of the ASP.NET Framework’s Form-Based Authentication.

How can I set Microsoft Identity to respect default file names [duplicate]

This question already has answers here:
How to specify root (/) location in web.config?
(10 answers)
Closed 4 years ago.
I am attempting to migrate from Forms Authentication / Membership to asp.net identity.
One issue I have encountered: If I set the LoginPath to "/account/", logged out users end up with an infinite redirect loop (not really; it keeps extending the returnURL until the server blocks the request for having an overly long query string). This occurs on /account/, but /account/default.aspx is accessible to logged out users. I believe that the issue is that somehow default documents are treated differently by the OWIN middleware than they are by forms authentication/IIS. Currently, "default.aspx" is configured as a Default Document.
I tried setting using UseFileServer to set DefaultFileNames to include "default.aspx", but this did not seem to help. I also tried using path="." inheritInChildApplications=false" instead of path="default.aspx", but this caused a, "Config section 'system.web/authorization' already defined" exception, presumably because it overlapped with the previous system.web declaration.
I realize that there are several possible work-arounds:
tolerate default.aspx in the path:
use MapPageRoutes instead of relying on default pages
set the web.config to allow /account and then use location path to manually disable every subdirectory
Is there a way to convince Microsoft Identity that loading /account/ does not require authentication without using the workarounds in the bullet points above?
public void Configuration(IAppBuilder app)
{
app.UseFileServer(new FileServerOptions() {
DefaultFilesOptions = {DefaultFileNames = {"default.aspx"}}});
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
LoginPath = new PathString("/account/")
});
}
<!--/account/web.config-->
<configuration>
<system.web>
<authorization>
<allow roles="activeuser" />
<deny users="*" />
</authorization>
</system.web>
<location path="Default.aspx">
<system.web>
<authorization>
<allow users="*" />
</authorization>
</system.web>
</location>
</configuration>
Voting to close my own question as a duplicate. For reference, this can be resolved by modifying the root web.config as follows:
<urlMappings>
<add url="~/account/" mappedUrl="~/account/default.aspx"/>
</urlMappings>
Somehow I completely failed to find https://stackoverflow.com/a/19154854/18192 while investigating this problem.

Why can't I open a custom web.config file in my web ASP app?

I can't open a web.config file in my ASP web project.
I can add config files in my project for set the authorization pages.
I need to open these pages to be able to update the "Roles" names from my admin page.
After following the sample from Microsoft, it should be working normally:
http://msdn.microsoft.com/en-us/library/vstudio/4c2kcht0(v=vs.100).aspx
Here is the C# code I use :
//Open the web.config custom
Configuration config = WebConfigurationManager.OpenWebConfiguration("~/WebAuthorizationPilotageGeneral") as Configuration;
//Get the authorization section
// section is always == NULL !!!!
-> section = (System.Web.Configuration.AuthorizationSection)config.GetSection("authorization");
//Remove all Roles before add news Roles
section.Rules.Clear();
autho = new System.Web.Configuration.AuthorizationRule(System.Web.Configuration.AuthorizationRuleAction.Allow);
foreach (string role in Roles.GetAllRoles())
{
if (role != ttbx_RoleName.Text)
{
autho.Roles.Add(role);
}
}
//Add the news Roles
section.Rules.Add(autho);
//Save the web.config custom
config.Save(ConfigurationSaveMode.Full, true);
My web.config custom file I try to load to update "authorization" section
<!-- WebAuthorizationPilotageGeneral.config - access pilotage page -->
<authorization>
<allow roles="Administrator" />
<allow roles="Audit" />
<allow roles="Copil" />
<allow roles="System" />
<allow roles="User" />
<allow roles="visitor" />
<deny users="*" />
</authorization>
The weird things is after load the config file, my config object still have 22 sections, and should have only one => "authorization" , it's look like my (web.config) root file and not the (WebAuthorizationPilotageGeneral) config file.
UPDATE : I try to put my 4 config files on only one folder
Web.config file
In the MS examples, there is used relative config path without "~" symbol. Have you tried to remove it?
// Set the root path of the Web application that contains the
// Web.config file that you want to access.
string configPath = "/MyAppRoot";
// Get the configuration object to access the related Web.config file.
Configuration config = WebConfigurationManager.OpenWebConfiguration(configPath);

Modify web.config via c# insert above a particular line

I have created an aspx page where I can type a name into a texbox and it will add a line under the 'autorization' section in my web.config file (E.g. 'allow users="peter" '), the problem is the line is always added below 'deny users="" ' which automatically stops any user added below that line from logging in. Is there a way to find the 'deny users="" ' line via my C# code and insert the 'allow users' line above?
Thanks
Default.aspx.cs (Add user code)
protected void btnWrite_Click(object sender, EventArgs e)
{
System.Configuration.Configuration configuration = WebConfigurationManager.OpenWebConfiguration("~");
AuthorizationSection authorization = (AuthorizationSection)configuration.GetSection("system.web/authorization");
AuthorizationRule accessRule = new AuthorizationRule(AuthorizationRuleAction.Allow);
accessRule.Users.Add(txtAddUser.Text);
authorization.Rules.Add(accessRule);
configuration.Save(ConfigurationSaveMode.Minimal);
}
Web.config (authorization section)
<authentication mode="Forms">
<forms name=".ASPNET" loginUrl="login.aspx" defaultUrl="Default/default.aspx" />
</authentication>
<authorization>
<allow users="john" />
<deny users="*" />
<allow users="peter" />
<allow users="david" />
</authorization>
You can use linq to select the decendants of authorization and add the element at the first or last where ever you want
you can use something like this
XDocument xDoc = new XDocument(#"your config file name. extention");
xDoc.Element("authorization")
.Elements("allow")
.Where(item => item.Attribute("users").Value == "john").FirstOrDefault()
.AddAfterSelf(new XElement("allow", new XAttribute("users", "put the user name your want here")));
to use this you need to add using statement at the top (using system.linq)
Hope you will understand this please replace the string as you want.

Configuring custom authorization with ELMAH

How can I configure ELMAH to display only for certain people without default ASP.NET authorization roles manager?
I (as well as many others, I think) use my own authorization logic and build my projects from zero without using provided templates. I want to log errors but it seems that it is impossible to configure ELMAH (somehow override functionality) to make it work with some other authorization or even to make it work only for particular IP addresses.
Since I will have access to web.config I tried to change these values in order to NOT display elmah by default.
<add key="elmah.mvc.disableHandler" value="false" />
<add key="elmah.mvc.disableHandleErrorFilter" value="false" />
<add key="elmah.mvc.requiresAuthentication" value="false" />
And when I want to view errors switch them from true to false and see errors, then switch back. But it seems that when I change these values all logs are erased.
What can I do?
I think the easiest approach would be to make some minor alterations to your custom authorization so the ELMAH authorization will work.
Option 1: Set the FormsAuthentication cookie on login. This way, in the web.config the allow users="username" should work. On successful login you can set the cookie with
FormsAuthentication.SetAuthCookie(theUsername, true).
The ELMAH authorization would look something like:
<location path="elmah.axd" inheritInChildApplications="false">
<system.web>
<authorization>
<allow users="theUserName" />
<deny users="*" />
</authorization>
</system.web>
...other config settings
</location>
Option 2: If you are using putting users into roles, you can override the default role provider to use the function you made to get roles. This way is a little more involved but then lets you harness role-basing authentication in the web.config, which is really nice for securing things like static file (.pdf etc) delivery. I can add code for this if interested.
I was using the ASP.NET Identity Framework, so this answer is regarding that setup. I also used the Elmah.MVC package in NuGet. I edited the following lines in web.config. (you need to supply your own user name in the allowedUser setting)
<add key="elmah.mvc.requiresAuthentication" value="true" />
<add key="elmah.mvc.allowedRoles" value="*" />
<add key="elmah.mvc.allowedUsers" value="your_user_name" />
It appears that ELMAH does get the authentication information from the current thread principal, which the ASP.NET Identity Framework will establish on your behalf upon login.
It doesn't matter how the system gets the username or roles in this case. Whether it be from the built-in providers, a provider you implement yourself, or if during your custom authentication you populate this information yourself. All it takes is to manually set the principal during something like the Application_PostAuthenticationRequest event. This should give you the jist of it.
protected void Application_PostAuthenticateRequest(object sender, EventArgs e)
{
//Obtain username and roles from application datastore and use them in the next line
Thread.CurrentPrincipal = new GenericPrincipal(
new GenericIdentity("userNameHere"),
new string[] { "Admin", "CanDeleteStuff", "CanEditStuff", "OtherRole" }
);
}
This will let you use something like this in your web.config
<location path="elmah.axd" inheritInChildApplications="false">
<system.web>
<authorization>
<allow roles="Elmah"/>
<deny users="*"/>
</authorization>
</system.web>
</location>
Not to mention being able to use User.IsInRole("CanEditStuff") in your code.

Categories