ActiveDirectoryRoleProvider Problems

Vote:
 

I'm having some problem to get the ActiveDirectoryRoleProvider to work.

When I access the site I get an error message: (The account exists in the AD)

2008-08-29 14:21:35,021 ERROR [7] EPiServer.Global.Global_Error - 1.2.5 Unhandled exception in ASP.NET
System.Web.HttpUnhandledException: Exception of type 'System.Web.HttpUnhandledException' was thrown. ---> System.Configuration.Provider.ProviderException: The user DOMAIN\username does not exist.
   at EPiServer.Security.ActiveDirectoryRoleProvider.GetRolesForUser(String username) in C:\Inetpub\EPiServerCMS5\security\ActiveDirectoryRoleProvider.cs:line 200

Configuration 

The user used to access the AD has the required permissions.

<roleManager enabled="true" defaultProvider="ActiveDirectoryRoleProvider" cacheRolesInCookie="true">
      <providers>
        <clear />
        <add name="MultiplexingRoleProvider" type="EPiServer.Security.MultiplexingRoleProvider, EPiServer" provider1="SqlServerRoleProvider" provider2="WindowsRoleProvider" providerMap1="SqlServermembershipProvider" providerMap2="WindowsMembershipProvider" />
        <add name="WindowsRoleProvider" applicationName="EPiServerSample" type="EPiServer.Security.WindowsRoleProvider, EPiServer" />
        <add name="SqlServerRoleProvider" connectionStringName="EPiServerDB" applicationName="EPiServerSample" type="System.Web.Security.SqlRoleProvider, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
        <add name="ActiveDirectoryRoleProvider"
        type="EPiServer.Security.ActiveDirectoryRoleProvider, EPiServer.Templates.Public"
        connectionStringName="ActiveDirectoryProviderConnection"
        connectionUsername="xx"
        connectionPassword="xx"/>
      </providers>
    </roleManager>
    <membership defaultProvider="ActiveDirectoryMembershipProvider" userIsOnlineTimeWindow="10">
      <providers>
        <clear />
        <add name="MultiplexingMembershipProvider" type="EPiServer.Security.MultiplexingMembershipProvider, EPiServer" provider1="SqlServerMembershipProvider" provider2="WindowsMembershipProvider" />
        <add name="WindowsMembershipProvider" type="EPiServer.Security.WindowsMembershipProvider, EPiServer" deletePrefix="BUILTIN\" searchByEmail="true" />
        <add name="SqlServerMembershipProvider" type="System.Web.Security.SqlMembershipProvider, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" connectionStringName="EPiServerDB" requiresQuestionAndAnswer="false" applicationName="EPiServerSample" requiresUniqueEmail="true" passwordFormat="Hashed" maxInvalidPasswordAttempts="5" minRequiredPasswordLength="7" minRequiredNonalphanumericCharacters="0" passwordAttemptWindow="10" passwordStrengthRegularExpression="" />
        <add name="ActiveDirectoryMembershipProvider"
    type="System.Web.Security.ActiveDirectoryMembershipProvider, System.Web,
    Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
    connectionStringName="ActiveDirectoryProviderConnection"
    connectionUsername="xx"
    connectionPassword="xx"
    enableSearchMethods="true" attributeMapUserName="sAMAccountName"/>
      </providers>

#23555
Sep 09, 2008 15:38
Vote:
 

Hi,

I haven't got a simple solution, but I've experienced the same situation and got it working.

What authentication mode are you using? If you're using "Windows" I think you should set the defaultProviders to "WindowsRoleProvider" and "WindowsMembershipProvider".

If you're using "Forms" you need to get the user to log on using the format "[user name]@[domain]"

My two cents.. someone smarter is welcome to explain how it's really done =)

Regards,

Peter

#23560
Sep 09, 2008 16:13
jo
Vote:
 

 Hi Jonas!

Make sure that the ActiveDirectoryRoleProvider connects to the same AD node as the ActiveDirectoryMembershipProvider, as the ActiveDirectoryRoleProvider only looks for users contained in or _beneath_ the node it connects to (as specified in the ldap connection string).

So, if the ActiveDirectoryMembershipProvider is connected to a node "higher up" in the hierarchy it may authenticate users that the ActiveDirectoryRoleProvider will not be able to find.

Regards,
Johan Olofsson

#23562
Sep 09, 2008 16:22
jo
Vote:
 

Also note that the default attribute used to find user is 'userPrincipalName'.

The ActiveDirectoryMembershipProvider in your sample web.config specifies the attributeMapUsername to 'sAMAccountName', you would most likely want the same specified for the ActiveDirectoryRoleProvider.

/johan

 

#23563
Sep 09, 2008 16:27
Vote:
 

Yes we are using windows authentication and if I change to WindowsMembershipProvider I can login without any problems.

But we need the functionality in the ActivDirectoryMembershipProvider because the customer has a large number of users and groups in the Active Directory.

/Jonas

#23564
Sep 09, 2008 16:30
Vote:
 

What's the actual difference when using different defaultProviders? Isn't the ActiveDirectoryMembershipProvider loaded "anyway"? I.e. acts as a fall-back if WindowsMembership isn't able to confirm the user?

// Peter

#23587
Sep 10, 2008 10:32
jo
Vote:
 

No, only the provider specified as the "defaultProvider" will be used during authentication.

Thats the reason we came up with the MultiplexingProvider in EPiServerCMS5.

/johan

#23588
Sep 10, 2008 10:34
Vote:
 

If I remove my domain name from my username "DOMAIN\username" -> "username" in the method "GetUsersInRole(userName)" then my user is found.

Is there any settings for changing the handling of username's with the Domain name included?

/Jonas

#23826
Sep 17, 2008 11:13
jo
Vote:
 

Did you try to set the attribute 'attributeMapUsername' for the ActiveDirectoryRoleProvider to have the same value, 'sAMAccountName' as specified for the ActiveDirectoryMembershipProvider.

Your earlier posted configurations implied that this attribute was left out for the roleprovider, which in that case woudl fallback to use the default 'userPrincipalName' attribute to locate user.

Regards,
johan

#23827
Sep 17, 2008 11:53
Vote:
 

Yes, i have set the attributeMapUsername for both, but i it gives me the same result.

    <roleManager enabled="true" defaultProvider="ActiveDirectoryRoleProvider" cacheRolesInCookie="true">
      <providers>
        <clear />
        <add name="MultiplexingRoleProvider" type="EPiServer.Security.MultiplexingRoleProvider, EPiServer" provider1="SqlServerRoleProvider" provider2="WindowsRoleProvider" providerMap1="SqlServermembershipProvider" providerMap2="WindowsMembershipProvider" />
        <add name="WindowsRoleProvider" applicationName="EPiServerSample" type="EPiServer.Security.WindowsRoleProvider, EPiServer" />
        <add name="SqlServerRoleProvider" connectionStringName="EPiServerDB" applicationName="EPiServerSample" type="System.Web.Security.SqlRoleProvider, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
        <add name="ActiveDirectoryRoleProvider"
        type="EPiServer.Security.ActiveDirectoryRoleProvider, EPiServer.Templates.Public"
        connectionStringName="ActiveDirectoryProviderConnection"
        connectionUsername="xx"
        connectionPassword="xx"
        attributeMapUsername="sAMAccountName"/></providers>
    </roleManager>
    <membership defaultProvider="ActiveDirectoryMembershipProvider" userIsOnlineTimeWindow="10">
      <providers>
        <clear />
        <add name="MultiplexingMembershipProvider" type="EPiServer.Security.MultiplexingMembershipProvider, EPiServer" provider1="SqlServerMembershipProvider" provider2="WindowsMembershipProvider" />
        <add name="WindowsMembershipProvider" type="EPiServer.Security.WindowsMembershipProvider, EPiServer" deletePrefix="BUILTIN\" searchByEmail="true" />
        <add name="SqlServerMembershipProvider" type="System.Web.Security.SqlMembershipProvider, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" connectionStringName="EPiServerDB" requiresQuestionAndAnswer="false" applicationName="EPiServerSample" requiresUniqueEmail="true" passwordFormat="Hashed" maxInvalidPasswordAttempts="5" minRequiredPasswordLength="7" minRequiredNonalphanumericCharacters="0" passwordAttemptWindow="10" passwordStrengthRegularExpression="" />
        <add name="ActiveDirectoryMembershipProvider"
    type="System.Web.Security.ActiveDirectoryMembershipProvider, System.Web,
    Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
    connectionStringName="ActiveDirectoryProviderConnection"
    connectionUsername="xx"
    connectionPassword="xx"
    enableSearchMethods="true"
    attributeMapUsername="sAMAccountName"/></providers>
    </membership>

#23832
Sep 17, 2008 12:33
jo
Vote:
 

Ok, I can now reproduce the same error, the key factor here is that the membershipprovider does take some extra steps to conform the passed in username depending on wether the userPrincipalName or sAMAccountName attribute are to be used to query the user, whereas the roleprovider simply uses the passed in username "as is" without any modifications.

And, when using WindowsAuthentication, the Domain/ will always prefix the username, so the roleprovider will query for "(sAMAccountName=DOMAIN\user)" whereas the membershipprovider will do a "(sAMAccountName=user)".

The solution would of course be to have the roleprovider determine if it too needs to take these extra steps to massage the username into its expected format before using it in the directory query.

I'll continue to investigate this a little further to see if we can come up with some quick and elegant solution.

/johan

#23841
Sep 17, 2008 14:17
jo
Vote:
 

Ehum, a little further investigation reveals that the ActiveDirectoryMembershipProvider isn't involved at all up until the point where the roleprovider gets called in its GetRolesForUser() method ... (!)
(The above only applies to when Windows authentication is used)

And, you do get the exact same error (null returned) if you were to try to call the ActiveDirectoryMembershipProvider.GetUser(userName) with the username in the form "DOMAIN\user".

So, I guess the solution would be to extract the username from the DOMAIN\username ´, and then just pass it on to the query.

To get the membership to work as well, youd have to write a custom membershipprovider and derive it from the ActiveDirectoryMembershipProvider, then override the necessare methods where a userName is passed and perform the same DOMAIN extraction before passing on to the base implementation.

/johan

 

#23852
Sep 17, 2008 15:52
Vote:
 

Ok, but what's the difference between using windows authentication in EPiServer CMS4 and configure the EPsLdapXXX settings in web.config (Using a Windows 2003 Active Directiry) (as we did in the version 4 site that we now upgrading to version 5), and using the WindowsMembership and WindowsRoleProvider in EPiServer CMS?

(We can get all AD groups in the permission dialogs and so on with the WindowsRole / Membership provider)

Need to know if I should spend more time on the ActiveDirectoryMembershipProvider.

One other strange problem is that the permissions in the page tree doesn't work after upgraded to version5, i needed to reset all permission (Save permissions recrusive) in the page tree before it worked.
(The groups and permissions was shown in the permission dialog but they didn't work with my user)
This is a problem because we have a lot of different permissions in the sub levels of the page tree.

/Jonas

#23894
Sep 18, 2008 11:13
jo
Vote:
 

Well, the EPiServer4's code for querying the AD did just exactly such a "normalization" (removing the DOMAIN-part) of the logged on username before running the query on the username.

This was done in the method DetermineDistinguishedNameFromLogonName() on the LdapConnection type found in the Ldapper.dll assembly.

When all that proprietary code was dropped in EPIServerCMS5 (in favour of the Asp.Net Membership/Role-architecture), you will have to add the functionality yourself, possibly "on top" of the existing providers.

/johan

 

 

#23902
Edited, Sep 18, 2008 14:07
This thread is locked and should be used for reference only. Please use the Episerver CMS 7 and earlier versions forum to open new discussions.