Update user roles/groups in Episerver CMS5R2 without validate user

Vote:
 

Hi! I have a little special scenario where a 3rd party solution does the actual user validation. When the user enters different episerver sites, I can check if the user has done the 3rd party validation. Both the episerver and 3rd party solution works within active directory and ad grups controls access rights for pages in episerver. The problem is that when a user gains or loses membership to different groups in AD, I can't synchronize the episerver rights without doing a membership.validate(). I only have access to the username and can not do this. Do someone have a smart solution to this? My code so far :) :

EPiServer.Security.PrincipalInfo.CurrentPrincipal = EPiServer.Security.PrincipalInfo.CreatePrincipal("KNOWNUSERNAME");
                                  FormsAuthentication.Initialize();
FormsAuthenticationTicket ticket3 = new FormsAuthenticationTicket(1, "KNOWNUSERNAME", DateTime.Now, DateTime.Now.AddMinutes(240), false, "DUMMYPASSWORD", FormsAuthentication.FormsCookiePath);
            string cookiestr3 = FormsAuthentication.Encrypt(ticket3);
            FormsAuthentication.SetAuthCookie("KNOWNUSERNAME", false);

    

 

#44676
Oct 12, 2010 15:54
Vote:
 

Do you have Roles configured to cache user roles in a cookie?
This is controlled by <roleManager> section in web.config.

There is a method Roles.DeleteCookie() which will clear this.

/johan

#44685
Oct 12, 2010 17:54
Vote:
 

Hi, and thanks for the reply. I have Roles configured, and a Roles.DeleteCookie() clears roles in cache so they are updated. However, I think the problem is related to the

EPiServer.Security.PrincipalInfo.CurrentPrincipal = EPiServer.Security.PrincipalInfo.CreatePrincipal("KNOWNUSERNAME"); 

    

CreatePrincipal probably just set current principal to a known (or not known) prinsipal every time, it doesent update the principals roles. But if i run membership.validate(user,pass), the user's groups and rights and roles are updated, and the next time I use the code above, the created principal is updated with the correct rights. So what goes on behind the scene? :)  The sites are configured with the multiplexingprovider.

#44689
Oct 13, 2010 0:00
Vote:
 

Hi, and thanks for the reply. I have Roles configured, and a Roles.DeleteCookie() clears roles in cache so they are updated after I for example run membership.validate(), (Which I can't do without some pretty ugly hacking:)) However, I think the problem is related to the

EPiServer.Security.PrincipalInfo.CurrentPrincipal = EPiServer.Security.PrincipalInfo.CreatePrincipal("KNOWNUSERNAME"); 

    

CreatePrincipal probably just set current principal to a known (or not known) prinsipal every time, it doesent update the principals roles. But if i run membership.validate(user,pass), the user's groups and rights and roles are updated, and the next time I use the code above, the created principal is updated with the correct rights. So what goes on behind the scene? :)  The sites are configured with the multiplexingprovider.

#44690
Edited, Oct 13, 2010 0:03
Vote:
 

Actually, the code in PrincipalInfo.CreatePrincipal() looks like this:

new GenericPrincipal(new GenericIdentity(username), Roles.GetRolesForUser(username));
So, it will make a call to Roles.GetRolesForUser().

Are you using the EPiServer.Security.ActiveDirectoryRoleProvider? If so, then *it* will internally cache the DirectoryData-entry
(including the "memberOf" attribute).

Try (for tests) to make a call to ClearCache() for the ActiveDirectoryFroleProvider before creating the principal and see if that helps:

((ActiveDirectoryRoleProvider)Roles.Providers["MyActiveDirectoryRoleProvider"]).ClearCache();

/johan

#44699
Oct 13, 2010 9:33
Vote:
 

HI again! I can't seem to find the clrearcache() function. Actually am using the MultiplexingRoleProvider, and the users are identified as windowsmembership and WindowsRoleProvider. I'm not sure that it's related to caching either, it can be weeks between the user's groups in ad have changed, but still the roles are not changed for the createprincipal-user.

#44702
Edited, Oct 13, 2010 10:51
Vote:
 

Aha, the WindowsMembershipProvider/WindowsRoleProvider are a little "special" in that they
synchronize groupmembership to local DB (using procedures netWinMembershipGroup-Insert/Delete/List)

When the WindowsRoleProvider.GetRiolesForUser(username) is called, it first tries to cast the Identity of the CurrentPrincipal
into a Windowsidentity, and if that fails, it'll return the (previously synchronized) groups from DB:

    WindowsIdentity identity = PrincipalInfo.CurrentPrincipal.Identity as WindowsIdentity;

    if ((identity == null) ... )
    {
        return DB.MemberOfGroups(username);
    }
    else
   
    ... read groups from WindowsIdentity

This is exactly what happens in your case when you call the PrincipalInfo.CreatePrincipal, it'll return a GenericPrincipal/GenericIdentity
and the cast to WindowsIdentity will fail.

You may want to try creating the WindowsIdentity yourself:

            WindowsIdentity windowsIdentity = new WindowsIdentity(@"username");
            WindowsPrincipal windowsPrincipal = new WindowsPrincipal(windowsIdentity);

            EPiServer.Security.PrincipalInfo.CurrentPrincipal = windowsPrincipal;

/johan

#44704
Oct 13, 2010 11:33
Vote:
 

Thank you johan! Now things start to make sense to me :) I ended up with the code:

Roles.DeleteCookie();

                    WindowsIdentity windowsIdentity = new WindowsIdentity(username);
                    WindowsPrincipal windowsPrincipal = new WindowsPrincipal(windowsIdentity);
                    string[] groups = WindowsMembershipProvider.GroupNamesFromIdentity(windowsIdentity,WindowsMembershipProvider.GetDeletePrefix());
                    new WindowsProviderDB().SynchronizeGroups(username, groups);
                    EPiServer.Security.PrincipalInfo.CurrentPrincipal = windowsPrincipal;

    Not sure I need the DB().SynchronizeGroups, but it can't hurt can it?

#44719
Oct 13, 2010 13:52
Vote:
 

No I dont think you need the extra call to WindowsProviderDB.SynchronizeGroups(), it will be
called automatically in the WindowsRoleProvider.GetRolesForUser(user).

However, the only thing it may hurt would be performance.

/johan

#44721
Oct 13, 2010 13:56
This topic was created over six months ago and has been resolved. If you have a similar question, please create a new topic and refer to this one.
* You are NOT allowed to include any hyperlinks in the post because your account hasn't associated to your company. User profile should be updated.