Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sitecore active directory problem with permissions and roles-in-roles

Question

I have written custom membership/role/profile providers to authenticate users against an Active Directory domain. I'm trying to use roles-in-roles to provide uers in the ADDOMAIN with sitecore permissions by adding their AD group as a member of the appropriate sitecore role. If I log in as an AD user, I don't seem to have the permissions of the sitecore role, however, if I log in as a sitecore user in the same sitecore role, I do get the permissions. Is there something that I'm missing in the membership/role providers that I need to include to make this work or is there something else at play here?

We're using Sitecore version 6.4 if that makes any difference.

SOLUTION: The answer from @Yan completely solved the issue. The problem is language permissions are only explicitly granted to sitecore domain users (via sitecore\Everyone). When creating AD users, they are in a different domain and don't inherit those language permissions. The fix is to grant the read/write permissions specifically to the AD domain, or as I have done, create another sitecore role and assign the necessary permissions to that role and then assign my AD roles into that role.

The permissions you need to set are lang:read and lang:write in the master database on the /System/Languages/[LANGUAGE: en in my case] item. If you can't see these permissions in the security editor, then click the columns button and choose those columns.

More details

My apologies in advance for the level of detail.

I have written custom membership/role/profile providers to authenticate users against an Active Directory domain. We're not using the AD module provided by sitecore as we only want our users to see particular groups and users instead of every user/group within the AD. I am also only trying to provide authentication and role membership services as I don't want the sitecore administrators to be able to modify AD users or roles.

The role I'm testing is called sitecore\Content Author in that it has the permissions that I want my AD users to have. The AD users are part of the ADDOMAIN\Web-Authors-Group group within the AD and within sitecore, I have set this group up as belonging to sitecore\Content Author. User ADDOMAIN\sitecoreauthor1 is a member of ADDOMAIN\Web-Authors-Group within the AD and I also have a sitecore user sitecore\bcauthor user who is a member of the sitecore\Content Author role. I have also set up a separate sitecore role called sitecore\SecondAuthorRole and the user sitecore\secondAuthor in that role to test that the roles-in-roles functionality works normally.

In case that's confusing, here's a visual representation:

Sitecore Roles

    sitecore\Content Author
      - sitecore\bcauthor
      - ADDOMAIN\Web-Authors-Group
      - sitecore\SecondAuthorRole
    sitecore\SecondAuthorRole
      - sitecore\secondAuthor

ActiveDirectory Groups

    ADDOMAIN\Web-Authors-Group
      - ADDOMAIN\sitecoreauthor1

If I log in as sitecore\bcauthor, I can do everything that the sitecore\Content Author role can do. If I log in as sitecore\secondAuthor, I can also do everything that the sitecore\Content Author role can do. However, if I log in as the ADDOMAIN\sitecoreauthor1 user, I don't seem to have any of the permissions of the sitecore\Content Author role.

Even more information

The permissions for the home item (which is the item I'm testing against) are:

 ar|sitecore\Content Author|pe|+item:rename|+item:write|+item:delete|+item:create|pd|+item:rename|+item:write|+item:delete|+item:create

Code

Here's the skeleton of the classes that implement the read-only providers for membership, roles and profile:

Membership Provider class

public class DirectoryMembershipProvider : System.Web.Security.MembershipProvider
{
    public override string ApplicationName { get; set; }
    public override bool EnablePasswordReset { get { return false; } }
    public override bool EnablePasswordRetrieval { get { return false; } }
    public override int MaxInvalidPasswordAttempts { get { return 100; } }
    public override int MinRequiredNonAlphanumericCharacters { get { return 0; } }
    public override int MinRequiredPasswordLength { get { return 1; } }
    public override MembershipPasswordFormat PasswordFormat { get { return MembershipPasswordFormat.Clear; } }
    public override string PasswordStrengthRegularExpression { get { return ""; } }
    public override bool RequiresQuestionAndAnswer { get { return false; } }
    public override bool RequiresUniqueEmail { get { return false; } }

    // Not implemented
    public override bool ChangePassword(string username, string oldPassword, string newPassword)
    public override bool ChangePasswordQuestionAndAnswer(string username, string password, string newPasswordQuestion, string newPasswordAnswer)
    public override MembershipUser CreateUser(string username, string password, string email, string passwordQuestion, string passwordAnswer, bool isApproved, object providerUserKey, out MembershipCreateStatus status)
    protected override byte[] DecryptPassword(byte[] encodedPassword)
    public override bool DeleteUser(string username, bool deleteAllRelatedData)
    protected override byte[] EncryptPassword(byte[] password)
    protected override byte[] EncryptPassword(byte[] password, MembershipPasswordCompatibilityMode legacyPasswordCompatibilityMode)
    protected override void OnValidatingPassword(ValidatePasswordEventArgs e)
    public override string ResetPassword(string username, string answer)
    public override bool UnlockUser(string userName)
    public override void UpdateUser(MembershipUser user)

    // Implemented functions
    public override MembershipUserCollection FindUsersByEmail(string emailToMatch, int pageIndex, int pageSize, out int totalRecords)
    public override MembershipUserCollection FindUsersByName(string usernameToMatch, int pageIndex, int pageSize, out int totalRecords)
    public override MembershipUserCollection GetAllUsers(int pageIndex, int pageSize, out int totalRecords)
    public override string GetPassword(string username, string answer)
    public override MembershipUser GetUser(object providerUserKey, bool userIsOnline)
    public override MembershipUser GetUser(string username, bool userIsOnline)
    public override string GetUserNameByEmail(string email)
    public override bool ValidateUser(string username, string password)
}

Role Provider

public class DirectoryRoleProvider : System.Web.Security.RoleProvider
{
    public override string ApplicationName { get; set; }

    // not implemented
    public override void AddUsersToRoles(string[] usernames, string[] roleNames)
    public override void CreateRole(string roleName)
    public override bool DeleteRole(string roleName, bool throwOnPopulatedRole)
    public override void RemoveUsersFromRoles(string[] usernames, string[] roleNames)

    // implemented functions
    public override string[] FindUsersInRole(string roleName, string usernameToMatch)
    public override string[] GetAllRoles()
    public override string[] GetRolesForUser(string username)
    public override string[] GetUsersInRole(string roleName)
    public override bool IsUserInRole(string username, string roleName)
    public override bool RoleExists(string roleName)
}

Profile Provider

public class DirectoryProfileProvider : System.Web.Profile.ProfileProvider
{
    public override string ApplicationName { get; set; }

    public override int DeleteInactiveProfiles(ProfileAuthenticationOption authenticationOption, DateTime userInactiveSinceDate) { return 0; }
    public override int DeleteProfiles(ProfileInfoCollection profiles) { return 0; }
    public override int DeleteProfiles(string[] usernames) { return 0; }

    // not implemented
    public override ProfileInfoCollection FindInactiveProfilesByUserName(ProfileAuthenticationOption authenticationOption, string usernameToMatch, DateTime userInactiveSinceDate, int pageIndex, int pageSize, out int totalRecords)
    public override ProfileInfoCollection GetAllInactiveProfiles(ProfileAuthenticationOption authenticationOption, DateTime userInactiveSinceDate, int pageIndex, int pageSize, out int totalRecords)

    // implemented functions
    public override ProfileInfoCollection FindProfilesByUserName(ProfileAuthenticationOption authenticationOption, string usernameToMatch, int pageIndex, int pageSize, out int totalRecords)
    public override ProfileInfoCollection GetAllProfiles(ProfileAuthenticationOption authenticationOption, int pageIndex, int pageSize, out int totalRecords)
    public override int GetNumberOfInactiveProfiles(ProfileAuthenticationOption authenticationOption, DateTime userInactiveSinceDate)
    public override SettingsPropertyValueCollection GetPropertyValues(SettingsContext context, SettingsPropertyCollection collection)
    public override void SetPropertyValues(SettingsContext context, SettingsPropertyValueCollection collection)
}
like image 716
Marko Avatar asked Mar 31 '11 04:03

Marko


1 Answers

Honestly, I didn't read the entire text, just the "question" part of it. And I suspect I know what the problem is. It has something to do with Language:Read and Language:Write permissions.

Take a look at my last post to this SDN forum thread. Be sure to check the attached archive with images for better understanding.

like image 64
Yan Sklyarenko Avatar answered Oct 05 '22 08:10

Yan Sklyarenko