Wednesday, 21 November 2012

Active Directory Role Provider with ASP.NET C#

Resources: 

Creating a custom role provider is pretty easy, all you have to do is create a new class and inherit RoleProvider:

public class ActiveDirectoryRoleProvider : RoleProvider
{}

References:
  • using System.Web.Security;
  • using System.Web.Configuration;
  • using System.Collections.Specialized;
  • using System.DirectoryServices;
  • using System.Globalization;
  • using System.Security;

Here's the the full code (minus the unimplemented inherited methods):
public class ActiveDirectoryRoleProvider : RoleProvider { private string ConnectionStringName { get; set; } private string ConnectionUsername { get; set; } private string ConnectionPassword { get; set; } private string AttributeMapUsername { get; set; } public override void Initialize(string name, NameValueCollection config) { ConnectionStringName = config["connectionStringName"]; ConnectionUsername = config["connectionUsername"]; ConnectionPassword = config["connectionPassword"]; AttributeMapUsername = config["attributeMapUsername"]; base.Initialize(name, config); } public override bool IsUserInRole(string username, string roleName) { string[] roles = GetRolesForUser(username); foreach (string role in roles) { if (role.Equals(roleName, StringComparison.OrdinalIgnoreCase)) { return true; } } return false; } public override string[] GetRolesForUser(string username) { var allRoles = new List<string>(); var root = new DirectoryEntry(WebConfigurationManager.ConnectionStrings[ConnectionStringName].ConnectionString, ConnectionUsername, ConnectionPassword); var searcher = new DirectorySearcher(root, string.Format(CultureInfo.InvariantCulture, "(&(objectClass=user)({0}={1}))", AttributeMapUsername, username)); searcher.PropertiesToLoad.Add("memberOf"); SearchResult result = searcher.FindOne(); if (result != null && !string.IsNullOrEmpty(result.Path)) { DirectoryEntry user = result.GetDirectoryEntry(); PropertyValueCollection groups = user.Properties["memberOf"]; foreach (string path in groups) { string[] parts = path.Split(','); if (parts.Length > 0) { foreach (string part in parts) { string[] p = part.Split('='); if (p[0].Equals("cn", StringComparison.OrdinalIgnoreCase)) { allRoles.Add(p[1]); } } } } } return allRoles.ToArray(); } }
Add the role provider to your Web.Config:


<system.web>
    <roleManager enabled="true" defaultProvider="ADRoleProvider" cacheRolesInCookie="true" cookieName=".ASPXROLES" cookiePath="/"
                 cookieTimeout="30" cookieRequireSSL="false" cookieSlidingExpiration="true" createPersistentCookie="false" cookieProtection="All">
        <providers>
            <clear />
            <add name="ActiveDirectoryRoleProvider" connectionStringName="ADConnectionString" connectionUsername="username"
                 connectionPassword="password" attributeMapUsername="sAMAccountName" type="ActiveDirectoryRoleProvider" />
        </providers>
    </roleManager>
</system.web>
You can then check the roles of your user in code like so:
Roles.IsUserInRole("My Group")
Or control access to entire directories via the Web.Config:
<location path="RestrictedSubDirectory">
    <system.web>
        <authorization>
            <allow roles="My Group"/>
            <deny users="*" />
        </authorization>
    </system.web>
</location>
Problem:
ActiveDirectoryRoleProvider does not implement inherited abstract member 'Systm.web.Security.RoleProvider.FindUsersInRole()

Solution:
  • Run the application and stop debugging and 
  • Just set the cursor to "RoleProvider", in the line: public class ActiveDirectoryRoleProvider : RoleProvider and a icon will come with option "Implement Role Provider" or hit "Ctrl + . ", then Enter.

No comments:

Post a Comment