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>
Related
I am an active directory user and I am simply trying to print the name of the current user out in a Respnse.Write() method. From what I read from several other questions posted here I need to use
using System.Security.Principal;
string username = WindowsIdentity.GetCurrent().Name
However, when I try to write the username to the screen I get
NT AUTHORITY\NETWORK SERVICE
instead of
domain\12345678
Here is the code I am using to write to the screen:
Response.Write(WindowsIdentity.GetCurrent().Name);
and I have identity impersonate set to true in my web.config. What do I do next?
Edited to show suggested answers
my pageload
protected void Page_Load(object sender, EventArgs e)
{
string userName = User.Identity.Name;
Response.Write(userName);
//currently returning null
}
In your web.config you need authentication mode switched on to Windows and you need to disabled anonymous users
<system.web>
<authentication mode="Windows" />
<anonymousIdentification enabled="false" />
<authorization>
<deny users="?" />
</authorization>
</system.web>
The reason your approach isn't working is because User.Identity isn't physically referencing your Active Directory Membership. For all intensive purposes, is trying to grab your active user through Internet Information Systems (IIS) which it can't do in the current state. Since your utilizing Web-Forms, the easiest approach would be:
<asp:LoginView> : The following template will allow you to specify visible data for an anonymous user, logged in user, or logged out user. Which will help manage your membership system accordingly.
Membership Not Needed - Membership isn't regulated, but would like to display or access whom is logged in for certain instances.
To implement:
<connectionStrings>
<add name="ADConnectionString" connectionString="LDAP://..." />
</connectionStrings>
That will be your connectionString to your directory. Now to ensure the application authenticates correctly:
<authentication mode="Windows">
<forms loginUrl="~/Account/Login.aspx" timeout="2880" />
</authentication>
<membership>
<providers>
<clear />
<add name="MyADMembershipProvider" type="System.Web.Security.ActiveDirectoryMembershipProvider, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" connectionStringName="ADConnectionString" />
</providers>
</membership>
Now you'll be able to properly run User.Identity.
Hopefully that helps.
string yourVariable = User.Identity.Name;
I am trying to use FormsAuthentication.RedirectFromLoginPage(username,true,cookiepath);
On using FormsAuthentication.RedirectFromLoginPage it's redirecting to the DefaultUrl provided in the web.config.
Authentication section in web.config:
<authentication mode="Forms">
<forms name=".ASPXADMINAUTH"
loginUrl="/Default.aspx"
defaultUrl="homepage.aspx"
protection="All"
timeout="30" path="/admin" slidingExpiration="true" enableCrossAppRedirects="false" cookieless="UseCookies" domain="localhost" ticketCompatibilityMode="Framework20" ></forms>
</authentication>
In httpModules Section:
<add name="FormsAuthentication" type="System.Web.Security.FormsAuthenticationModule" />
The page is redirecting from the Loginpage to the "homepage.aspx" but it didn't set the Authentication cookie.
In my Response header, Set-Cookie contains the Authentication cookie, but it is not set in the homepage.aspx page.
So the LoginStaus and LoginName control is not working.
The problems in your code are path="/admin" domain="localhost"
According to your code
After user logins, a cookie is set under /admin. As the result, every pages under /admin folder knows that the user is authenticated such as ~/admin/default.aspx.
However ~/homepage.aspx does not know about user, because ~/homepage.aspx cannot read cookie written under /admin.
var path = FormsAuthentication.FormsCookiePath;
FormsAuthentication.RedirectFromLoginPage("win", false, path);
How to fix it?
You want to start slowly using simple one. Then tweak depending on what you need.
<forms loginUrl="~/Default.aspx" timeout="2880" defaultUrl="~/homepage.aspx" />
FYI: Please do not add properties which are default such as slidingExpiration="true",
enableCrossAppRedirects="false" and so on.
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).
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
I'm having problem with our login procedure.
Some customers complain that they can't login. I can see in our logs that their login is successful and that they are redirected from the login page to the member area. But there somehow the login isn't detected and they are bounced back to the login page.
I've asked customers to check if cookies are supported (http://www.html-kit.com/tools/cookietester/) but problem remains even if this test returns true.
This is how I've implemented the login procedure (simplyfied):
protected void Login(string email, string password)
{
FormsAuthentication.SignOut();
Guid clientId = /* Validate login by checking email and password, if fails display error otherwise get client id */
FormsAuthentication.SetAuthCookie(clientId.ToString(), true);
HttpContext.Current.Response.Redirect("~/Members.aspx");
}
On the member page I check for authentication by in Page_Load function:
public static void IsAuthenticated()
{
if (!HttpContext.Current.User.Identity.IsAuthenticated)
{
HttpContext.Current.Response.Redirect("~/Login.aspx", true);
}
}
Maybe I'm using FormsAuthentication completely wrong?
I've asked this before but still haven't been able to figure this out, I'd appreciate any help.
From my Web.Config:
<system.web>
<compilation debug="false">
<assemblies>
...
</assemblies>
</compilation>
<authentication mode="Forms"/>
<sessionState mode="InProc" cookieless="false" timeout="180"/>
<customErrors mode="On"/>
<httpHandlers>
...
</httpHandlers>
<httpModules>
...
</httpModules> </system.web>
public static void IsAuthenticated()
{
if (!HttpContext.Current.User.Identity.IsAuthenticated)
{
HttpContext.Current.Response.Redirect("~/Login.aspx", true);
}
}
is not necessary when you use forms authentication.
When you specify the forms authentication in the web.config (in which you also specify the login page)
<authentication mode="Forms">
<forms loginUrl="/Authorization/Login" timeout="60" />
</authentication>
and you deny all non-athenticated users access
<authorization>
<deny users="?" />
</authorization>
you don't have to check the authentication of a user yourself, the framework takes care of that.
I would place the FormsAuthentication.SignOut(); code behind a 'logout' link
Seperate the call of SignOut() and SetAuthCookie() in different methods. You may call FormsAuthentication.SignOut(); when the Login page loads first time - simply just do away from calling SignOut() on Login page. And Call
FormsAuthentication.SetAuthCookie(clientId.ToString(), true); after authentication is successful.
Normally you would use FormsAuthentication.Authenticate together with some membership provider, but this should work, and it actually does in my machine.
Are you removing the FormsAuthentication from your registered HTTP modules? Normally, this is in the machine wide web.config:
<configuration>
<system.web>
<httpModules>
<add name="FormsAuthentication" type="System.Web.Security.FormsAuthenticationModule" />
</httpModules>
</system.web>
</configuration>
If you put a <clear /> inside that same section of your own web.config, you're effectively removing that module.
My tested Web.config is pretty clean, it only has <authentication mode="Forms"/> configured.