Copied to clipboard

Flag this post as spam?

This post will be reported to the moderators as potential spam to be looked at


  • Rune Hammerskov 5 posts 35 karma points
    May 06, 2015 @ 14:29
    Rune Hammerskov
    0

    Custom Users membership provider with fallback

    I am trying to add Active directory authentication to the Umbraco backoffice. In the AD users are in one of three groups { ad-admin, ad-editor, ad-writer }. When a users tries to log on a users should be assigned permissions based on which of the three groups he/she is in. This part I have more or less figured out. 

    The difficult par comes from the requirement that existing users (created before this integration) should still work. I have tried to do the following (slightly simplified):

    public class ActiveDirectoryMembershipProvider : Umbraco.Web.Security.Providers.UsersMembershipProvider
    { public override bool ValidateUser(string username, string password) { if(ValidateAgainstAD(username,password)) { // Create user in database and set correct permissions return true } return base.ValidateUser(username,password); }
    }

    Falling back to base.ValidateUser does not work. I have also tried to call Membership.Providers["UsersMembershipProvider"].ValidateUser instead, but with the same result. My best guess is that there is something being initialized by Umbraco that does not occur when i have my ActiveDirectoryMembershipProvider set as the DefaultBackofficeProvider. 

    Any ideas about what I am missing here? 

  • Shannon Deminick 1526 posts 5272 karma points MVP 3x
    Jun 03, 2015 @ 12:32
    Shannon Deminick
    0

    What does this mean?

    Falling back to base.ValidateUser does not work.

    Please provide more details about what exactly you are attempting to do and exactly what the result that you are expecting is.

  • Rune Hammerskov 5 posts 35 karma points
    Jun 08, 2015 @ 09:33
    Rune Hammerskov
    0

    As I wrote, in the AD users can be in one of three groups:

    • ad-admin
    • ad-editor
    • ad-writer

    Each of these should map to the corresponding three roles in Umbraco. The administrator of the AD should be able to control which users can log in to Umbraco, and what permissions they have, simply by controlling the AD.

    It should also be possible to have users that only exist in Umbraco and not in the AD.

    So what I am looking to do is first check if the users is a member of the AD and which of the three roles he/she is part of. If the user is a member of the AD then create the user in Umbraco and assign the correct role. The user should not be prompted to change password since the password is in the AD. If a user is not a member of the AD check if the user exists in Umbraco and log him/her in using the built in UsersMembershipProvider.

    Hope this makes more sense.

  • Shannon Deminick 1526 posts 5272 karma points MVP 3x
    Jun 15, 2015 @ 07:50
    Shannon Deminick
    100

    Ok, so now I know what you are trying to achieve, but you have not explained what

    Falling back to base.ValidateUser does not work

    actually means.

    It's worth noting that any membership provider used will create a local Umbraco user, it is not possible to have the user only exist outside of Umbraco. When the provider authenticates, it creates/updates the local user. This might be a transparent process but that is how it works. If you want to update user permissions based on your AD authentication model, then those permissions need to be copied locally. Umbraco Users don't use 'Roles', the security permissions for user's are a custom implementation and security goes beyond just sections, it also accounts for node security. The User types are in fact not 'groups', they just give the user their default node permission structures. We are aware that the User security model should be enhanced, but that is the way it is currently so you'll need to work within those boundaries.

  • Rune Hammerskov 5 posts 35 karma points
    Jul 06, 2015 @ 06:53
    Rune Hammerskov
    0

    Sorry about the delay but the project that I was working on was hit by sickness and some political problems causing this issue to be almost forgotten.

    The idea behind calling base.ValidateUser was to allow the normal flow of Umbraco.Web.Security.Providers.UsersMembershipProvider to happen if I determine that the user is not in the AD. In essence what I want is to check if a user is in the AD; if so, use custom code to handle user; if not, use Umbraco.Web.Security.Providers.UsersMembershipProvider.

    Am I going about this completely wrong

  • Shannon Deminick 1526 posts 5272 karma points MVP 3x
    Jul 06, 2015 @ 07:27
    Shannon Deminick
    0

    Hi Rune,

    I understand what you are attempting to do but you still haven't told me what

    Falling back to base.ValidateUser does not work

    actually means :P I can't help you with an issue if I don't know what the issue actually is. What errors, behavior, etc... are you actually seeing?

  • Rune Hammerskov 5 posts 35 karma points
    Jul 07, 2015 @ 14:35
    Rune Hammerskov
    0

    Hi Shannon

    I don't know what to say. Since I posted the first question I have changed developer machine and when I tried to execute on this machine everything worked as expected. So thank you for your help but it seems the reason you couldn't quite understand my problem is because there wasn't one.

    For everyone else reading this here is the code (slightly condensed) I have been trying to get to work:

    using System;
    using System.Collections.Generic;
    using System.DirectoryServices.AccountManagement;
    using System.Linq;
    using Umbraco.Core;
    using Umbraco.Web.Security.Providers;
    
    namespace MyProject
    {
      public class ActiveDirectoryMembershipProvider : UsersMembershipProvider
      {
        public override bool ValidateUser(string username, string password)
        {
          IDictionary<string, UserPermissions> userPermissions = new Dictionary<string, UserPermissions>(StringComparer.OrdinalIgnoreCase)
          {   
            { "AD-admin", new UserPermissions("admin", new [] { "content", "media", "settings", "developer", "forms", "member", "users" }) },
            { "AD-editor", new UserPermissions("editor", new [] { "content", "media" }) },
            { "AD-writer", new UserPermissions("writer", new [] { "content", "media" }) }
          };
    
          using (var context = new PrincipalContext(ContextType.Domain))
          {
            if (context.ValidateCredentials(username, password))
            {
              var adUser = UserPrincipal.FindByIdentity(context, username);
              var adGroups = adUser.GetAuthorizationGroups().Select(x => x.Name);
    
              var permissions = userPermissions.FirstOrDefault(x => adGroups.Any(ag => ag.Equals(x.Key))).Value;
              if (permissions == null)
                return false;
    
              var user = MemberService.GetByUsername(username) ??
                         MemberService.CreateWithIdentity(username, username, new Guid().ToString(), permissions.UserType.Alias);
    
              user.AllowedSections.ToList().ForEach(user.RemoveAllowedSection);
              permissions.AllowedSections.ForEach(user.AddAllowedSection);
    
              user.UserType = permissions.UserType;
              user.IsLockedOut = false;
              user.IsApproved = true;
    
              MemberService.Save(user);
    
              return true;
            }
          }                     
    
          return base.ValidateUser(username, password);
        }
      }
    }
    
Please Sign in or register to post replies

Write your reply to:

Draft