Programmatically check if page requires authentication based on web.config settings - c#

I would like to know if there is a way to check if a page requies authentication based on the web.config settings. Basically if there is a node like this
<location path="account">
<system.web>
<authorization>
<deny users="?"/>
</authorization>
</system.web>
</location>
then I would like to check on any page if it requires authentication or not and to return true if it is under the account directory. Is this possible?

The solution is to create an anonymous identity (principal), and pass it into the CheckUrlAccessForPrincipal method. It will determine if the page is public, or requires authentication.
See code below:
var principal = new GenericPrincipal(new GenericIdentity(String.Empty, String.Empty), new string[]{});
bool requiredAuthentication = UrlAuthorizationModule.CheckUrlAccessForPrincipal(Page.AppRelativeVirtualPath, principal, Request.HttpMethod);

Are you checking the page that the user has requested? Its unlikely as the request will never get to the page. Check the url authorization workflow.
http://www.asp.net/web-forms/tutorials/security/membership/user-based-authorization-cs

I am a little confused as to what you are asking exactly, but to use your web.config to enforce authentication on a page-for-page basis, you need something like this:
<location path="Forms/Administration/Default.aspx">
<system.web>
<authorization>
<allow roles="Administrator, User, AdditionalUser" />
</authorization>
</system.web>
</location>
If you need to be more granular than that, you need to add the logic to your middle-tier and then check on page load or url request (if MVC).

Related

Application won't read username on IIS

I have this application where I login by the PC user. I'm using this:
public static bool IsAuthenticated()
{
if (HttpContext.Current.User.Identity.IsAuthenticated)
{
CurrentUser = Factory.Users.List(item => item.Username.ToLower() == cToLower()).FirstOrDefault();
}
return CurrentUser != null;
}
Note: .List(), is a method I created to list all database Users (in
this case).
Everything works fine. But when I publish my Website on my IIS, HttpContext.Current.User.Identity.Name is returning nothing, no user at all. What is wrong with it? Any suggestion?
You have to enable IIS Windows Authentication and Deny Annomyous acces. You can either configure your IIS or update your configuration file as follows,
<configuration>
<system.web>
<authentication mode="Windows" />
<authorization>
<deny users="?"/>
</authorization>
</system.web>
</configuration>

Setting authorization section of multiple location elements in one web.config from code behind

I have two location elements in a single web.config file, and would like to change the authorization in the code behind.
The web.config location sections are like this:
<configuration>
<location path="~">
<system.web>
<compilation debug="false" targetFramework="4.0"/>
<authorization>
<allow roles=""/>
<deny users="*"/>
</authorization>
</system.web>
</location>
<location path="~/SubPage">
<system.web>
<compilation debug="false" targetFramework="4.0"/>
<authorization>
<allow roles=""/>
<deny users="*"/>
</authorization>
</system.web>
</location>
</configuration>
From the code behind I would like to go through the location elements, and then make the changes to that specific location element. For example, c# code behind would be:
Configuration myConfig = WebConfigurationManager.OpenWebConfiguration("~");
ConfigurationLocationCollection locations = myConfig.Locations;
foreach (ConfigurationLocation location in locations)
{
if (location.Path = "~")
{
//define & clear the authorization section of the particular location element.
//create and apply rule for allow in that authorization section.
//create and apply rule for deny in that authorization section.
//save the change
}
if (location.Path = "~/SubPage")
{
//define & clear the authorization section of the particular location element.
//create and apply rule for allow in that authorization section.
//create and apply rule for deny in that authorization section.
//save the change
}
}
I have tried several different things here, but I don't have one solution that actually works so far... I need to consoldiate any change to the web.config in the root directory (~) (any change would have to be reflected in this file, not other files in the subpage). Any recommended working solution to fill in the blanks? The purpose is to allow admin users to make changes on an admin user interface to decide which users or windows groups on the internal network will be allowed to view the two locations, so I would particularly like to change the allowed roles from the code behind.
Thanks.
After several attempts, abandoned trying to make all the changes on the same file, and instead simply opened a new configuration manager instance in each location.Path.
WebConfigurationManager.OpenWebConfiguration(location.Path), then applied the rules to each individual web.config at each location. I couldn't centralize all the authorizations in one place, but at least it was working.

How to deny an image's path for a specific user

My website has a folder called uploads and inside there is a folder for each client.
My question is, what's the best practice to deny the user A to see the uploads from user B?
You could do this with web.config changes. See documentation here: http://support.microsoft.com/kb/815151
Basically your web.config will look like:
<?xml version="1.0"?>
<configuration>
<location path="uploads/UserA">
<system.web>
<authorization>
<allow users="UserA"/>
<deny users="*"/>
</authorization>
</system.web>
</location>
<location path="uploads/UserB">
<system.web>
<authorization>
<allow users="UserB"/>
<deny users="*"/>
</authorization>
</system.web>
</location>
</configuration>
Perhaps look at using an HttpHandler to intercept the request and generate a 403 (or whatever you want to do) if the user is not authorized to access the requested path.
Alternatively, you could put the logic in Global.asax in the BeginRequest method.
You could use NTFS permissions on the folders, forcing the user to authenticate. I did this for a website in 2000. Although in this case that's like using a cannon to kill a mosquito.
Assume you might have something like following data-structure:
You may write a file name to database column.
So you may add a column called "Allow-Anonymous" with True/False.
Now while accessing your content from server, check the db table,
If Allow-Anonymous is False and Visiting-User is other then owner then deny page display. Otherwise you may show the content.
DataBase mock:
Id Data Path OwnerId AllowAnonymous Status
1 Data-A ~/upload/Data-A 1 False True
Code mock:
if(AllowAnonymous == True && UserId == OwnerId && Status == True)
// Show data on page
else
// Redirect to deny page

simple web.config file question asp.net

i am using windows authentication with my asp.net application
different users will have different access to parts of the website.
i would like to do something like this in the config file:
<appSettings>
<role1>
<user>agordon</user><user>jsmith</user>
</role1>
<role2><user>dtodd</user><user>kveel</user></role2>
</appSettings>
is this possible to do?
when authenticating i would then get the username like this:
string username = HttpContext.Current.User.Identity.Name.ToString();
and check if that user exists in the specific role
Use the <authorization> element:
<configuration>
<system.web>
<authorization>
<allow users="*" />
<deny users="?"/>
</authorization>
</system.web>
</configuration>
You can then modify that for particular parts of your site:
<location path="Pages/Administration">
<system.web>
<authorization>
<deny roles="*"/>
<allow roles="Admin" />
</authorization>
</system.web>
</location>
You can do this, but it's really not the best way.
The problem here is that appSettings are not controlled by the Web.Config schema, so you'll need to programatically enumerate appSettings in a horrible fashion:
if (configurationSettings.HasKey("Role1")) { ... }
else if (configurationSettings.HasKey("Role2")) { ... }
else if (configurationSettings.HasKey("Role3")) { ... }
//continue ad.nauseum; it's not fun - trust me!
I know it's not what you're asking, but If you're using normal ASP.Net webforms then it's a little it of a slog; in each page/control you need to find out the current user and then determine if that user has access and then redirect or continue.
If you use ASP.Net MVC, it's a lot cleaner as you do this with attributes.
Authorize(Roles = "Managers")]
public ActionResult CompanySecrets()
{
return View();
}
What the code there is doing, is saying If the user doesn't have the Managers role, don't give them access.
To provide an opposite example, here's a similar method using Web form (msdn example):
http://support.microsoft.com/kb/311495

Issues with custom ASP.NET RoleProvider

I am having difficulties implementing a custom ASP.NET RoleProvider.
First off, let me show you the relevant settings in my web.config file:
<?xml version="1.0"?>
<configuration>
<system.web>
<authentication mode="Forms">
<forms loginUrl="Login.aspx"
name="FormsAuthentication"
path="Default.aspx"
timeout="20"/>
</authentication>
<membership defaultProvider="MembershipProvider">
<providers>
<clear />
<add name="MembershipProvider"
type="CompanyName.Security.MembershipProvider" />
</providers>
</membership>
<roleManager defaultProvider="RoleProvider"
enabled="true">
<providers>
<clear />
<add name="RoleProvider"
type="CompanyName.Security.RoleProvider" />
</providers>
</roleManager>
</system.web>
<location path="Employees.aspx">
<system.web>
<authorization>
<deny users="?"/>
<allow roles="Employees"/>
</authorization>
</system.web>
</location>
</configuration>
Here's the code for the login button's event handler:
if (Membership.ValidateUser(tbxUsername.Text, tbxPassword.Text))
Response.Redirect("./Employees.aspx");
else
{
tbxUsername.Text = string.Empty;
tbxPassword.Text = string.Empty;
tbxUsername.Focus();
lblLogin.Visible = true;
}
Side Note based on FormsAuthentication.RedirectFromLoginPage() suggestion:
[It has been suggested that I use FormsAuthentication.RedirectFromLoginPage() instead of Response.Redirect(). Eventually, I'd like to redirect the user to a different page based on his/her role. I don't know how FormsAuthentication.RedirectFromLoginPage() would allow me to do this as it does not accept a redirection url as a parameter. In addition, it is my understanding that I could call FormsAuthentication.SetAuthCookie() prior to Response.Redirect() in order to create the authentication cookie that FormsAuthentication.RedirectFromLoginPage() creates. Please let me know if my thought process here is wrong.]
After stepping through the source, I can see that Membership.ValidateUser() is executing the ValidateUser() function of my custom MembershipProvider class. However, when a valid user logs in, and is redirected to Employees.aspx, the user is returned to Login.aspx**?ReturnUrl=%2fEmployees.aspx**. I assume that this is because although the user authenticates, s/he is failing authorization to the Employees.aspx resource.
With that assumption, I created breakpoints on every function in my custom RoleProvider class to see where things run amuck. Not one of them breaks execution when I debug. Most of the code in my RoleProvider throws NotYetImplementetExceptions, but I would still expect to hit the breakpoints (and would then implement those required functions). Here are two dumbed-down functions I have implemented:
public override string[] GetRolesForUser(string username)
{
return new string[1] {"Employees"};
}
public override bool IsUserInRole(string username, string roleName)
{
return true;
}
I assume that since the RoleProvider code never executes, that something must be wrong with my web.config.
I've searched for an answer to this for the past two days and have tried various changes without success. Does anyone see where I'm going wrong?
Thanks in advance!
After authenticating the user using Membership.ValidateUser, you should call FormsAuthentication.RedirectFromLoginPage rather than Response.Redirect to create the forms authentication ticket.
See the MSDN documentation for Membership.ValidateUser for an example.
EDIT
Or if you want to redirect to a specific page, call FormsAuthentication.SetAuthCookie to create the forms authentication ticket before calling Response.Redirect.
It redirects authenticated users to default.aspx
Actually it redirects back to the page that was originally requested, which is not necessarily default.aspx
EDIT 2
Also there is a problem with your configuration:
The path attribute should not point to a specific page (Default.aspx in your case), but the root directory of the site. The default is "/" because most browsers are case-sensitive and so won't send the cookie if there is a case mismatch.
<forms loginUrl="Login.aspx"
name="FormsAuthentication"
path="/"
timeout="20"/>
Check if user is in role:
If (Roles.IsUserInRole("Employees"))
{
}
or try if it works without role checking:
<allow users="*"/>
maybe helps configuration change:
<location path="Employees.aspx">
<system.web>
<authorization>
<allow roles="Employees"/>
<deny users="*"/>
</authorization>
</system.web>
</location>
I changed the path value (see below) from "Default.aspx" to "/" and now the breakpoints in the custom RoleProvider are being hit!
Does not work:
<authentication mode="Forms">
<forms loginUrl="Login.aspx"
name="FormsAuthentication"
path="Default.aspx"
timeout="20"/>
</authentication>
Works:
<authentication mode="Forms">
<forms loginUrl="Login.aspx"
name="FormsAuthentication"
path="/"
timeout="20"/>
</authentication>

Categories

Resources