Go Back

Membership and Role Providers

Notes for the Role Provider webinars

  • Visual Studio – admin
  • Microsoft SQL Server Management Studio
  • Virtual PC – Windows Server VHD
  • Softerra LDAP Browser
  • Delete profile from LDAP Browser

Overview ASP.NET Membership & Role Providers

The Membership and Role Provider model was introduced with ASP.NET 2.0. 

--

Overview of User Management in Sitefinity

The Administrator role is created by default and granted Unrestricted access in the ~/web.config:

<security defaultProvider="DefaultSecurityProvider" cmsProvidersName="Sitefinity">
  <roles>
    <clear/>
    <add name="Administrators" permission="Unrestricted"/>
  </roles>
</security>

Additional Unrestricted roles can be added by adding additional Roles.

Roles permissions are also configured inside Sitefinity:

  • Administration –> Users (Roles)
  • Administration –> Permissions
  • Modules –> Blogs –> Permissions
  • Pages –> Permissions

There are two types of Membership Providers offered in Sitefinity:

Default Sitefinity Security Providers

  1. Telerik.DataAccess.AspnetProviders.TelerikMembershipProvider
  2. Telerik.Security.ActiveDirectory.TelerikRoleProvider

Active Directory Sitefinity Security Providers

  1. Telerik.DataAccess.AspnetProviders.TelerikADRoleProvider
  2. Telerik.Security.ActiveDirectory.TelerikADMembershipProvider

--

Adding Custom Fields to the Sitefinity Membership Provider

Modify ~/web.config to contain mappings for custom fields:

<configuration>
  <system.web>
    <profile defaultProvider="Sitefinity">
      <properties>
        <add name="Address"/>
        <add name="City"/>
        <add name="State"/>
        <add name="Zip"/>
      </properties>
    </profile>
  </system.web>
</configuration>

Modify ~/Sitefinity/Admin/CmsAdmin/Users.aspx to contain new fields:

<cc1:ManageUsers runat="server" ID="manageUsers">
    <ListTemplate>
        <!-- Insert Form Elements for new Fields -->
    </ListTemplate>
    <InsertTemplate>
        <!-- Insert Form Elements for new Fields -->
    </InsertTemplate>
    <EditTemplate>
        <!-- Insert Form Elements for new Fields -->
    </EditTemplate>
</cc1:ManageUsers>

Insert form fields for new custom fields into ~/Sitefinity/Admin/CmsAdmin/Users.aspx:

<li>
  <cc2:FieldLabel ID="lblAddress" Text="Address" runat="server" />
  <asp:TextBox ID="Address" runat="server" />
</li>
<li>
  <cc2:FieldLabel ID="lblCity" Text="City" runat="server" />
  <asp:TextBox ID="City" runat="server" />
</li>
<li>
  <cc2:FieldLabel ID="lblState" Text="State" runat="server" />
  <asp:TextBox ID="State" runat="server" />
</li>
<li>
  <cc2:FieldLabel ID="lblZip" Text="Zip" runat="server" />
  <asp:TextBox ID="Zip" runat="server" />
</li>

Insert form fields for new custom fields into ~/Sitefinity/Admin/CmsAdmin/MyProfile.aspx:

<li>
  <cc2:FieldLabel ID="lblAddress" Text="Address" runat="server" />
  <asp:TextBox ID="Address" runat="server" />
</li>
<li>
  <cc2:FieldLabel ID="lblCity" Text="City" runat="server" />
  <asp:TextBox ID="City" runat="server" />
</li>
<li>
  <cc2:FieldLabel ID="lblState" Text="State" runat="server" />
  <asp:TextBox ID="State" runat="server" />
</li>
<li>
  <cc2:FieldLabel ID="lblZip" Text="Zip" runat="server" />
  <asp:TextBox ID="Zip" runat="server" />
</li>

--

Overview of the Active Directory

Setup an Active Directory for Testing

Setup users and roles in Active Directory Users and Computers

  • Log into VHD Server as Administrator
  • Manage Users and Computers in Active Directory

Test connection to AD from local computer:

  • Use Softerra’s LDAP Browser to test connection and credentials
  • Create new Profile
  • Hostname: WS03R2EE (your Virtual Server's hostname)
  • Base: DC=SitefinityWatch,DC=local
  • Username: SitefinityWatch\Administrator

Sample LDAP queries:

  • Finds the Administrator account:
    (&(sAMAccountType=805306368)(sAMAccountName=Administrator))
  • Find the Administrators role:
    (&(objectClass=group)(sAMAccountName=Administrators))
  • Finds all user accounts:
    sAMAccountType=805306368
  • Finds all account roles:
    (objectClass=group)

--

Enabling Sitefinity Active Directory Integration

Enabling Sitefinity Active Directory integration requires 3 steps:

  1. Create <connectionString> to Active Directory
  2. Create <roleManager> to TelerikADRoleManager
  3. Create <membership> to TelerikADMembershipManager

Sitefinity’s Active Directory Membership and Role Provider is configured in the ~/web.config:

<configuration>
  <connectionStrings>
    <add name="ADService" connectionString="LDAP://WS03R2EE/DC=SitefinityWatch,DC=local" />
  </connectionStrings>
  <system.web>
    <roleManager enabled="true" cacheRolesInCookie="true" defaultProvider="Sitefinity">
      <providers>
        <clear />
        <add applicationName="/" description="Telerik Role provider for Active Directory"
          connectionStringName="ADService"
          connectionUsername="Administrator"
          connectionPassword="Evaluation1"
          domainName="WS03R2EE"
          searchScope="subtree"
          name="Sitefinity"
          type="Telerik.Security.ActiveDirectory.TelerikADRoleProvider, Telerik.Security" />
      </providers>
    </roleManager>
    <membership defaultProvider="Sitefinity" userIsOnlineTimeWindow="15" hashAlgorithmType="">
      <providers>
        <clear/>
        <add name="Sitefinity"
          connectionStringName="ADService"
          enableSearchMethods="true"
          attributeMapUsername="sAMAccountName"
          connectionUsername="Administrator"
          connectionPassword="Evaluation1"
          type="Telerik.Security.ActiveDirectory.TelerikADMembershipProvider, Telerik.Security"/>
      </providers>
    </membership>
  </system.web>
</configuration>

Full explanation of the Telerik Active Directory Membership and Role providers.

<roleManager enabled="true" cacheRolesInCookie = "true" defaultProvider = "Sitefinity">
<providers>
  <clear/>
  <add name="Sitefinity"
            applicationName="/"
            description="Telerik Role provider for Active Directory"
            authenticationType="Secure"
              userSearchFilter="(&(sAMAccountType=805306368)(sAMAccountName={0}))"
            roleSearchFilter="(&(objectClass=group)(sAMAccountName={0}))"
            userDefinitionFilter="sAMAccountType=805306368"
            groupDefinitionFilter="(objectClass=group)"
           
            connectionStringName="ActiveDirectory"
            type="Telerik.Security.ActiveDirectory.TelerikADRoleProvider, Telerik.Security"
            connectionUsername="username"
            connectionPassword="password"
            groupMaps="Administrators, Users"
            domainName="telerik.com"
            searchScope="subtree"
  />
</providers>
</roleManager>

--

Creating a custom Membership and Role Provider

Add project references to the following assemblies:

  • System.Configurations
  • System.Web

MembershipProvider.cs

using System.Configuration.Provider;
using System.Linq;
using Telerik.OpenAccess;

namespace SitefinityWatch.Security
{
    public class MembershipProvider : System.Web.Security.MembershipProvider
    {

    }
}

RoleProvider.cs

using System.Configuration.Provider;
using System.Linq;
using Telerik.OpenAccess;

namespace SitefinityWatch.Security
{
    public class RoleProvider : System.Web.Security.RoleProvider
    {

    }
}

--

Creating a custom Role Provider for use with Active Directory

Create Roles database table:

SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

SET ANSI_PADDING ON
GO

CREATE TABLE [dbo].[Roles](
	[ID] [uniqueidentifier] NOT NULL,
	[Name] [varchar](50) NOT NULL,
 CONSTRAINT [PK_Roles] PRIMARY KEY CLUSTERED 
(
	[ID] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

GO

SET ANSI_PADDING OFF
GO

ALTER TABLE [dbo].[Roles] ADD  CONSTRAINT [DF_Roles_ID]  DEFAULT (newid()) FOR [ID]
GO

Create MemberRoles database table:

SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

SET ANSI_PADDING ON
GO

CREATE TABLE [dbo].[MemberRoles](
	[ID] [uniqueidentifier] ROWGUIDCOL  NOT NULL,
	[Username] [varchar](50) NOT NULL,
	[RoleID] [uniqueidentifier] NOT NULL,
 CONSTRAINT [PK_MemberRoles] PRIMARY KEY CLUSTERED 
(
	[ID] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

GO

SET ANSI_PADDING OFF
GO

ALTER TABLE [dbo].[MemberRoles]  WITH CHECK ADD  CONSTRAINT [FK_MemberRoles_Roles] FOREIGN KEY([RoleID])
REFERENCES [dbo].[Roles] ([ID])
GO

ALTER TABLE [dbo].[MemberRoles] CHECK CONSTRAINT [FK_MemberRoles_Roles]
GO

ALTER TABLE [dbo].[MemberRoles] ADD  CONSTRAINT [DF_MemberRoles_ID]  DEFAULT (newid()) FOR [ID]
GO

Use OpenAccess ORM reverse mapping to create:

  • Roles.cs
  • MemberRoles.cs

Use OpenAccess ORM forward mapping to generate GUIDs for Primary Keys

  • Generate new GUIDs for new Roles
  • Generate new GUIDs for new MemberRoles

RoleManager.cs

using System.Collections.Generic;
using System.Linq;
using Telerik.OpenAccess;
using Telerik.OpenAccess.Query;

namespace SitefinityWatch.Security
{
    public class RoleManager
    {
        private IObjectScope scope;

        public RoleManager()
            : this(ObjectScopeProvider1.GetNewObjectScope())
        {
        }

        public RoleManager(IObjectScope _scope)
        {
            scope = _scope;
        }

        public void AddUserToRole(string username, string roleName)
        {
            if (RoleExists(roleName))
            {
                if (!IsUserInRole(username, roleName))
                {
                    var role = scope.Extent<Role>().First(r => r.Name == roleName);

                    var memberRole = new MemberRole();
                    memberRole.Role = role;
                    memberRole.Username = username;

                    scope.Transaction.Begin();
                    scope.Add(memberRole);
                    scope.Transaction.Commit();
                }
            }
        }

        public bool RoleExists(string roleName)
        {
            return (from r in scope.Extent<Role>()
                    where r.Name == roleName
                    select r).Any();
        }

        public bool IsUserInRole(string username, string roleName)
        {
            return (from r in scope.Extent<MemberRole>()
                    where r.Username == username && r.Role.Name == roleName
                    select r).Any();
        }

        public void CreateRole(string roleName)
        {
            if (!RoleExists(roleName))
            {
                var role = new Role
                {
                    Name = roleName
                };

                scope.Transaction.Begin();
                scope.Add(role);
                scope.Transaction.Commit();
            }
        }

        public void DeleteRole(string roleName)
        {
            if (RoleExists(roleName))
            {
                var role = scope.Extent<Role>().First(r => r.Name == roleName);

                scope.Transaction.Begin();
                scope.Remove(role);
                scope.Transaction.Commit();
            }
        }

        public string[] FindUsernamesInRole(string roleName, string usernameToMatch)
        {
            return (from r in scope.Extent<MemberRole>()
                    where r.Role.Name == roleName && r.Username.Contains("usernameToMatch")
                    select r.Username).ToArray();
        }

        public bool RoleHasMembers(string roleName)
        {
            var query = from r in scope.Extent<MemberRole>()
                        where r.Role.Name == roleName
                        select r;

            return query.Any();
        }

        public void RemoveAllRoleMembers(string roleName)
        {
            var query = from r in scope.Extent<MemberRole>()
                        where r.Role.Name == roleName
                        select r;

            scope.Transaction.Begin();
            scope.Remove(query);
            scope.Transaction.Commit();
        }

        public List<Role> GetAllRoles()
        {
            var query = from r in scope.Extent<Role>()
                        orderby r.Name
                        select r;

            return query.ToList();
        }

        public List<Role> GetRolesForUser(string username)
        {
            var query = from r in scope.Extent<MemberRole>()
                        where r.Username == username
                        orderby r.Role.Name
                        select r.Role;

            return query.ToList();
        }

        public string[] GetUsersInRole(string roleName)
        {
            var query = (from r in scope.Extent<MemberRole>()
                         where r.Role.Name == roleName
                         select r.Username).ToArray();

            return query.ToArray();
        }

        public void RemoveUsersFromRoles(string[] usernames, string[] roleNames)
        {
            var usernamesList = new List<string>(usernames);
            var rolenamesList = new List<string>(roleNames);

            var query = from r in scope.Extent<MemberRole>()
                        where usernamesList.Contains(r.Username) && rolenamesList.Contains(r.Role.Name)
                        select r;

            scope.Transaction.Begin();
            scope.Remove(query);
            scope.Transaction.Commit();
        }
    }
}

RoleProvider.cs

using System.Configuration.Provider;
using System.Linq;
using Telerik.OpenAccess;

namespace SitefinityWatch.Security
{
    public class RoleProvider : System.Web.Security.RoleProvider
    {
        private string _applicationName;
        private IObjectScope scope;
        private RoleManager _manager;

        public RoleManager manager
        {
            get
            {
                if (_manager == null)
                {
                    _manager = new RoleManager();
                }

                return _manager;
            }
        }

        public override void AddUsersToRoles(string[] usernames, string[] roleNames)
        {
            foreach (string username in usernames)
            {
                foreach (string role in roleNames)
                {
                    manager.AddUserToRole(username, role);
                }
            }
        }

        public override string ApplicationName
        {
            get
            {
                return _applicationName;
            }
            set
            {
                _applicationName = value;
            }
        }

        public override void CreateRole(string roleName)
        {
            manager.CreateRole(roleName);
        }

        public override bool DeleteRole(string roleName, bool throwOnPopulatedRole)
        {
            if (manager.RoleHasMembers(roleName))
            {
                if (throwOnPopulatedRole)
                {
                    throw new ProviderException(roleName + " has members!");
                }
                manager.RemoveAllRoleMembers(roleName);
            }
            manager.DeleteRole(roleName);

            return true;
        }

        public override string[] FindUsersInRole(string roleName, string usernameToMatch)
        {
            return manager.GetUsersInRole(roleName);
        }

        public override string[] GetAllRoles()
        {
            var query = from r in manager.GetAllRoles()
                        select r.Name;

            return query.ToArray();
        }

        public override string[] GetRolesForUser(string username)
        {
            if (username == "admin" || username == "Administrator")
            {
                return new string[] { "Administrators" };
            }

            var query = from r in manager.GetRolesForUser(username)
                        select r.Name;

            return query.ToArray();
        }

        public override string[] GetUsersInRole(string roleName)
        {
            return manager.GetUsersInRole(roleName);
        }

        public override bool IsUserInRole(string username, string roleName)
        {
            if ((username == "Administrator" && roleName == "Administrators") || (username == "admin" && roleName == "Administrators"))
            {
                return true;
            }

            return manager.IsUserInRole(username, roleName);
        }

        public override void RemoveUsersFromRoles(string[] usernames, string[] roleNames)
        {
            manager.RemoveUsersFromRoles(usernames, roleNames);
        }

        public override bool RoleExists(string roleName)
        {
            return manager.RoleExists(roleName);
        }
    }
}

Add references to the following:

  • System.Configuration
  • System.Web

~/web.config

<configuration>
  <connectionStrings>
    <add name="ADService" connectionString="LDAP://WS03R2EE/DC=SitefinityWatch,DC=local" />
  </connectionStrings>
  <system.web>
    <roleManager enabled="true" cacheRolesInCookie="true" defaultProvider="Sitefinity">
      <providers>
        <clear />
        <add applicationName="/" name="Sitefinity" type="SitefinityWatch.Security.RoleProvider, SitefinityWatch.Security"/>
      </providers>
    </roleManager>
  </system.web>
</configuration>

--

More Resources:

Post a comment!
  1. Formatting options
       
     
     
     
     
       
  2. I'm sorry for the CAPTCHA. You have spammers to thank for this: