If I am using Windows Authentication in an ASP.NET app, and I want to use custom roles instead of using Windows security groups as roles, do I need to write a custom Role provider? The solution needs to be able to map Windows users and groups to application specific roles.
ASP.NET Windows Authentication with Custom Roles
asp.net
Related Solutions
Here's how I do it.
I decided to use IPrincipal instead of IIdentity because it means I don't have to implement both IIdentity and IPrincipal.
Create the interface
interface ICustomPrincipal : IPrincipal { int Id { get; set; } string FirstName { get; set; } string LastName { get; set; } }
CustomPrincipal
public class CustomPrincipal : ICustomPrincipal { public IIdentity Identity { get; private set; } public bool IsInRole(string role) { return false; } public CustomPrincipal(string email) { this.Identity = new GenericIdentity(email); } public int Id { get; set; } public string FirstName { get; set; } public string LastName { get; set; } }
CustomPrincipalSerializeModel - for serializing custom information into userdata field in FormsAuthenticationTicket object.
public class CustomPrincipalSerializeModel { public int Id { get; set; } public string FirstName { get; set; } public string LastName { get; set; } }
LogIn method - setting up a cookie with custom information
if (Membership.ValidateUser(viewModel.Email, viewModel.Password)) { var user = userRepository.Users.Where(u => u.Email == viewModel.Email).First(); CustomPrincipalSerializeModel serializeModel = new CustomPrincipalSerializeModel(); serializeModel.Id = user.Id; serializeModel.FirstName = user.FirstName; serializeModel.LastName = user.LastName; JavaScriptSerializer serializer = new JavaScriptSerializer(); string userData = serializer.Serialize(serializeModel); FormsAuthenticationTicket authTicket = new FormsAuthenticationTicket( 1, viewModel.Email, DateTime.Now, DateTime.Now.AddMinutes(15), false, userData); string encTicket = FormsAuthentication.Encrypt(authTicket); HttpCookie faCookie = new HttpCookie(FormsAuthentication.FormsCookieName, encTicket); Response.Cookies.Add(faCookie); return RedirectToAction("Index", "Home"); }
Global.asax.cs - Reading cookie and replacing HttpContext.User object, this is done by overriding PostAuthenticateRequest
protected void Application_PostAuthenticateRequest(Object sender, EventArgs e) { HttpCookie authCookie = Request.Cookies[FormsAuthentication.FormsCookieName]; if (authCookie != null) { FormsAuthenticationTicket authTicket = FormsAuthentication.Decrypt(authCookie.Value); JavaScriptSerializer serializer = new JavaScriptSerializer(); CustomPrincipalSerializeModel serializeModel = serializer.Deserialize<CustomPrincipalSerializeModel>(authTicket.UserData); CustomPrincipal newUser = new CustomPrincipal(authTicket.Name); newUser.Id = serializeModel.Id; newUser.FirstName = serializeModel.FirstName; newUser.LastName = serializeModel.LastName; HttpContext.Current.User = newUser; } }
Access in Razor views
@((User as CustomPrincipal).Id) @((User as CustomPrincipal).FirstName) @((User as CustomPrincipal).LastName)
and in code:
(User as CustomPrincipal).Id
(User as CustomPrincipal).FirstName
(User as CustomPrincipal).LastName
I think the code is self-explanatory. If it isn't, let me know.
Additionally to make the access even easier you can create a base controller and override the returned User object (HttpContext.User):
public class BaseController : Controller
{
protected virtual new CustomPrincipal User
{
get { return HttpContext.User as CustomPrincipal; }
}
}
and then, for each controller:
public class AccountController : BaseController
{
// ...
}
which will allow you to access custom fields in code like this:
User.Id
User.FirstName
User.LastName
But this will not work inside views. For that you would need to create a custom WebViewPage implementation:
public abstract class BaseViewPage : WebViewPage
{
public virtual new CustomPrincipal User
{
get { return base.User as CustomPrincipal; }
}
}
public abstract class BaseViewPage<TModel> : WebViewPage<TModel>
{
public virtual new CustomPrincipal User
{
get { return base.User as CustomPrincipal; }
}
}
Make it a default page type in Views/web.config:
<pages pageBaseType="Your.Namespace.BaseViewPage">
<namespaces>
<add namespace="System.Web.Mvc" />
<add namespace="System.Web.Mvc.Ajax" />
<add namespace="System.Web.Mvc.Html" />
<add namespace="System.Web.Routing" />
</namespaces>
</pages>
and in views, you can access it like this:
@User.FirstName
@User.LastName
It's instantiated once. A quick look at the docs confirmed this:
For each role provider specified in the configuration for an application, ASP.NET instantiates a single role-provider instance that is used for all of the requests served by an HttpApplication object. As a result, you can have multiple requests executing concurrently. ASP.NET does not ensure the thread safety of calls to your provider. You will need to write your provider code to be thread safe. For example, creating a connection to a database or opening a file for editing should be done within the member that is called, such as AddUsersToRoles , rather than opening a file or database connection when the Initialize method is called.
Related Topic
- IIS AppPoolIdentity and file system write access permissions
- Asp.net-mvc – ASP.NET MVC and Windows Authentication with custom roles
- Asp.net-mvc – Simple custom roles for windows authentication in asp. net
- Asp.net-mvc – ASP.NET 5 Custom roles for Windows Authentication
- Asp.net-mvc – Adding ASP.NET MVC5 Identity Authentication to an existing project
Best Answer
If I understand your question - no you don't need to use roles from Active Directory security groups as roles for your ASP.NET application. And you dont need to implement a custom Role provider. The default one simply retrieves the Roles from the ASP.NET application database.
You can simply have application defined roles in this database, that you create with the
aspnet_regsql.exe
utility (in the .NET 2.0 framework folder).Probably the greatest collections of resources/information on this topic: http://weblogs.asp.net/scottgu/archive/2006/02/24/ASP.NET-2.0-Membership_2C00_-Roles_2C00_-Forms-Authentication_2C00_-and-Security-Resources-.aspx