Sunday, September 27, 2009

Updated Custom SharePoint Membership/Role Provider

 

Note:  This is an update to my previous post describing a custom SharePoint Membership/Role Provider.  I have left the other post intact in the event you need to see what I did that didn’t work.  This solution seems to work better.

The Problem

Wiring up a membership provider in SharePoint is fairly straight forward.  Especially if you have worked with .net membership providers in the past.  A quick Google search for SharePoint custom membership provider will return numerous examples on how to get this going.

We had a need to use an ASP.NET SQL Membership Provider to expose a secure SharePoint site externally to people who did not have an account in our Domain.  The problem was, people with domain accounts also needed to be able to access this sight externally and we didn’t want our users to have to remember two usernames and passwords.  Isn’t that thoughtful of us?  In an asp.net web application this would not be a big deal.  Define two membership providers in the web.config, set one as the default and if authentication failed on the default provider it would automatically try the other providers.  It doesn’t exactly work that way in SharePoint.  Apparently SharePoint is only aware of one membership provider.  We wired up a asp.net sql membership provider and we were able to make SharePoint authenticate to that, then we changed it to the built in SharePoint LDAP membership provider and we were able to authenticate against our Domain.  We just couldn’t get both to work simultaneously.

The Solution

After mucking around with config files for an entire day, it became very evident that to accomplish our goal, it would require a custom membership and role provider that would try to authenticate to the sql database and if that failed, hit the domain for authentication.  If they both fail, well, you’re not supposed to be here, go away.  As I mentioned earlier, the built in .net SQL membership provider worked well and the built in SharePoint LDAP membership provider worked well on it’s own.  However, when I tried to programmatically instantiate the SharePoint LDAP Provider, there were a couple of methods that I could not get to work.  Apparently this class wasn’t meant to used in another provider.  Our custom membership provider would inherit the SQLMemberShipProvider and SQLRoleProvider classes, so that would be our base class and our first attempt at authentication.  We would then programmatically instantiate an instance of a custom developed LDAPMembershipProvider and LDAPRoleProvider if the first attempt at authentication failed and give that a try.  Below is the code for our custom providers.

Custom Membership Provider

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.Security;
using Microsoft.SharePoint;
using System.DirectoryServices.AccountManagement;
using System.Collections.Specialized;


namespace FBA.Extranet.MembershipProvider
{
    public class FBAMembershipProvider : SqlMembershipProvider
    {

        public override string ApplicationName
        {
            get
            {
                return SPContext.Current.Site.ID.ToString();
            }
        }

        private FBALDAPMembershipProvider _fbaLDAPProvider = null;
        private FBALDAPMembershipProvider FBALDAPProvider
        {
            get
            {
                if (_fbaLDAPProvider == null)
                    _fbaLDAPProvider = new FBALDAPMembershipProvider();
                return _fbaLDAPProvider;
            }
        }

        public override bool ValidateUser(string username, string password)
        {
            if (base.ValidateUser(username, password))
                return true;
            else if (FBALDAPProvider.ValidateUser(username, password))
                return true;
            else
                return false;
        }

        public override MembershipUser GetUser(string username, bool userIsOnline)
        {
            if (base.GetUser(username, userIsOnline) != null)
                return base.GetUser(username, userIsOnline);
            else
                return FBALDAPProvider.GetUser(username, userIsOnline);
        }

        public override MembershipUser GetUser(object providerUserKey, bool userIsOnline)
        {
            if (base.GetUser(providerUserKey, userIsOnline) != null)
                return base.GetUser(providerUserKey, userIsOnline);
            else
                return FBALDAPProvider.GetUser(providerUserKey, userIsOnline);
        }

        public override MembershipUserCollection FindUsersByEmail(string emailToMatch, int pageIndex, int pageSize, out int totalRecords)
        {
            if (base.FindUsersByEmail(emailToMatch, pageIndex, pageSize, out totalRecords).Count > 0)
                return base.FindUsersByEmail(emailToMatch, pageIndex, pageSize, out totalRecords);
            else
                return FBALDAPProvider.FindUsersByEmail(emailToMatch, pageIndex, pageSize, out totalRecords);
        }

        public override MembershipUserCollection FindUsersByName(string usernameToMatch, int pageIndex, int pageSize, out int totalRecords)
        {
            if (base.FindUsersByName(usernameToMatch, pageIndex, pageSize, out totalRecords).Count > 0)
                return base.FindUsersByName(usernameToMatch, pageIndex, pageSize, out totalRecords);
            else
                return FBALDAPProvider.FindUsersByName(usernameToMatch, pageIndex, pageSize, out totalRecords);
        }

        public override MembershipUserCollection GetAllUsers(int pageIndex, int pageSize, out int totalRecords)
        {
            if (base.GetAllUsers(pageIndex, pageSize, out totalRecords).Count > 0)
                return base.GetAllUsers(pageIndex, pageSize, out totalRecords);
            else
                return FBALDAPProvider.GetAllUsers(pageIndex, pageSize, out totalRecords);

        }

        public override string GetUserNameByEmail(string email)
        {
            if (!string.IsNullOrEmpty(base.GetUserNameByEmail(email)))
                return base.GetUserNameByEmail(email);
            else
                return FBALDAPProvider.GetUserNameByEmail(email);

        }

    }
}

Custom Role Provider

using System;
using System.Collections.Generic;
using System.DirectoryServices.AccountManagement;
using System.Linq;
using System.Text;
using System.Web.Security;
using Microsoft.SharePoint;

namespace FBA.Extranet.MembershipProvider
{
    public class FBARoleProvider : SqlRoleProvider
    {
        public override string ApplicationName
        {
            get
            {
                return SPContext.Current.Site.ID.ToString();
            }
        }

        private FBALDAPRoleProvider _fbaLDAPRoleProvider = null;
        private FBALDAPRoleProvider FBALDAPRoleProvider
        {
            get
            {
                if (_fbaLDAPRoleProvider == null)
                    _fbaLDAPRoleProvider = new FBALDAPRoleProvider();
                return _fbaLDAPRoleProvider;
            }
        }

        public override string[] GetRolesForUser(string username)
        {
            List<string> test = new List<string>();
            test.AddRange(base.GetRolesForUser(username));
            test.AddRange(FBALDAPRoleProvider.GetRolesForUser(username));
            return test.ToArray();
        }

        public override bool RoleExists(string roleName)
        {
            if (base.RoleExists(roleName))
                return true;
            else
                return FBALDAPRoleProvider.RoleExists(roleName);
        }

        public override string[] GetUsersInRole(string roleName)
        {
            if (base.GetUsersInRole(roleName).Length > 0)
                return base.GetUsersInRole(roleName);
            else
                return FBALDAPRoleProvider.GetUsersInRole(roleName);
          
        }
    }
}

Custom LDAP Membership Provider

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.DirectoryServices.AccountManagement;
using Microsoft.SharePoint;
using System.Web.Security;

namespace FBA.Extranet.MembershipProvider
{
    public class FBALDAPMembershipProvider : System.Web.Security.MembershipProvider
    {

        private string _applicationName = string.Empty;
        public override string ApplicationName
        {
            get
            {
                if (_applicationName == string.Empty)
                {
                    _applicationName = SPContext.Current.Site.ID.ToString();
                }
                return _applicationName;
            }
            set
            {
                this._applicationName = SPContext.Current.Site.ID.ToString();
            }
        }

        public override MembershipUserCollection FindUsersByEmail(string emailToMatch, int pageIndex, int pageSize, out int totalRecords)
        {
            try
            {
                MembershipUserCollection coll = new MembershipUserCollection();
                int resultRecords = 0;
                int startIndex = pageIndex * pageSize;
                int endIndex = startIndex + pageSize;
                SPSecurity.RunWithElevatedPrivileges(new SPSecurity.CodeToRunElevated(delegate()
                {
                    using (PrincipalContext context = new PrincipalContext(ContextType.Domain))
                    {
                        using (UserPrincipal userFilter = new UserPrincipal(context))
                        {
                            userFilter.EmailAddress = emailToMatch.Replace("%", "*");
                            using (PrincipalSearcher search = new PrincipalSearcher(userFilter))
                            {
                                PrincipalSearchResult<Principal> users = search.FindAll();
                                resultRecords = users.Count();
                                if (resultRecords < endIndex + 1)
                                {
                                    startIndex = 0;
                                    endIndex = resultRecords - 1;
                                }
                                for (int i = startIndex; i <= endIndex; i++)
                                {
                                    coll.Add(GetMembershipUser(users.ElementAt(i) as UserPrincipal));
                                }
                            }
                        }
                    }
                }));
                totalRecords = resultRecords;
                return coll;
            }
            catch (Exception ex)
            {
                //TODO: Log Something
                totalRecords = 0;
                return null;
            }
        }

        public override MembershipUserCollection FindUsersByName(string usernameToMatch, int pageIndex, int pageSize, out int totalRecords)
        {
            try
            {
                MembershipUserCollection coll = new MembershipUserCollection();
                int resultRecords = 0;
                int startIndex = pageIndex * pageSize;
                int endIndex = startIndex + pageSize;
                SPSecurity.RunWithElevatedPrivileges(new SPSecurity.CodeToRunElevated(delegate()
                {
                    using (PrincipalContext context = new PrincipalContext(ContextType.Domain))
                    {
                        using (UserPrincipal userFilter = new UserPrincipal(context))
                        {
                            userFilter.SamAccountName = usernameToMatch.Replace("%", "*");
                            using (PrincipalSearcher search = new PrincipalSearcher(userFilter))
                            {
                                PrincipalSearchResult<Principal> users = search.FindAll();
                                resultRecords = users.Count();
                                if (resultRecords < endIndex + 1)
                                {
                                    startIndex = 0;
                                    endIndex = resultRecords - 1;
                                }
                                for (int i = startIndex; i <= endIndex; i++)
                                {
                                    coll.Add(GetMembershipUser(users.ElementAt(i) as UserPrincipal));
                                }
                            }
                        }
                    }
                }));
                totalRecords = resultRecords;
                return coll;
            }
            catch (Exception ex)
            {
                //TODO: Log Something.
                totalRecords = 0;
                return null;
            }
        }

        public override MembershipUserCollection GetAllUsers(int pageIndex, int pageSize, out int totalRecords)
        {
            try
            {
                MembershipUserCollection memUserCollection = new MembershipUserCollection();
                int resultRecords = 0;
                int startIndex = pageIndex * pageSize;
                int endIndex = startIndex + pageSize;
                SPSecurity.RunWithElevatedPrivileges(new SPSecurity.CodeToRunElevated(delegate()
                {
                    using (PrincipalContext context = new PrincipalContext(ContextType.Domain))
                    {
                        using (UserPrincipal userFilter = new UserPrincipal(context))
                        {
                            using (PrincipalSearcher search = new PrincipalSearcher(userFilter))
                            {
                                PrincipalSearchResult<Principal> user = search.FindAll();
                                resultRecords = user.Count();
                                if (resultRecords < endIndex + 1)
                                {
                                    startIndex = 0;
                                    endIndex = resultRecords - 1;
                                }
                                for (int i = startIndex; i <= endIndex; i++)
                                {
                                    memUserCollection.Add(GetMembershipUser(user.ElementAt(i) as UserPrincipal));
                                }
                            }
                        }
                    }
                }));
                totalRecords = resultRecords;
                return memUserCollection;
            }
            catch (Exception ex)
            {
                //Log something.
                totalRecords = 0;
                return null;
            }
            
        }

        public override MembershipUser GetUser(string username, bool userIsOnline)
        {
            try
            {
                MembershipUser memUser = null;
                SPSecurity.RunWithElevatedPrivileges(new SPSecurity.CodeToRunElevated(delegate()
                {
                    using (PrincipalContext context = new PrincipalContext(ContextType.Domain))
                    {
                        using (UserPrincipal userFilter = new UserPrincipal(context))
                        {
                            userFilter.SamAccountName = username.Replace("%", "*");
                            using (PrincipalSearcher search = new PrincipalSearcher(userFilter))
                            {
                                UserPrincipal user = search.FindOne() as UserPrincipal;
                                if (!(user == null))
                                {
                                    memUser = GetMembershipUser(user);
                                }

                            }
                        }
                    }
                }));
                return memUser;
            }
            catch (Exception ex)
            {
                //Log something.
                return null;
            }
        }

        public override string GetUserNameByEmail(string email)
        {
            try
            {
                string username = string.Empty;
                SPSecurity.RunWithElevatedPrivileges(new SPSecurity.CodeToRunElevated(delegate()
                {
                    using (PrincipalContext context = new PrincipalContext(ContextType.Domain))
                    {
                        using (UserPrincipal userFilter = new UserPrincipal(context))
                        {
                            userFilter.EmailAddress = email;
                            using (PrincipalSearcher search = new PrincipalSearcher(userFilter))
                            {
                                UserPrincipal user = search.FindOne() as UserPrincipal;
                                if (!(user == null))
                                {
                                    username = user.SamAccountName;
                                }
                            }
                        }
                    }
                }));
                return username;
            }
            catch (Exception ex)
            {
                //log something.
                return string.Empty;
            }
        }

        public override bool ValidateUser(string username, string password)
        {
            bool isValid = false;
            try
            {
                SPSecurity.RunWithElevatedPrivileges(new SPSecurity.CodeToRunElevated(delegate()
                {
                    using (PrincipalContext context = new PrincipalContext(ContextType.Domain))
                    {
                        isValid = context.ValidateCredentials(username, password);
                    }
                }));
                
            }
            catch (Exception ex)
            {
                //log something.
                isValid = false;
            }
            return isValid;
        }

        private MembershipUser GetMembershipUser(UserPrincipal user)
        {
            return new MembershipUser("FBAMemberProvider",
                user.SamAccountName, user.DistinguishedName,
                user.EmailAddress, string.Empty,
                string.Empty, user.Enabled.Value, !user.Enabled.Value,
                DateTime.MinValue, DateTime.Now, DateTime.Now,
                DateTime.MinValue, DateTime.MinValue);
        }

        #region Not Implemented Methods
        public override bool ChangePassword(string username, string oldPassword, string newPassword)
        {
            throw new NotImplementedException();
        }

        public override bool ChangePasswordQuestionAndAnswer(string username, string password, string newPasswordQuestion, string newPasswordAnswer)
        {
            throw new NotImplementedException();
        }

        public override System.Web.Security.MembershipUser CreateUser(string username, string password, string email, string passwordQuestion, string passwordAnswer, bool isApproved, object providerUserKey, out System.Web.Security.MembershipCreateStatus status)
        {
            throw new NotImplementedException();
        }

        public override bool DeleteUser(string username, bool deleteAllRelatedData)
        {
            throw new NotImplementedException();
        }

        public override bool EnablePasswordReset
        {
            get { throw new NotImplementedException(); }
        }

        public override bool EnablePasswordRetrieval
        {
            get { throw new NotImplementedException(); }
        }

        public override int GetNumberOfUsersOnline()
        {
            throw new NotImplementedException();
        }

        public override string GetPassword(string username, string answer)
        {
            throw new NotImplementedException();
        }

        public override MembershipUser GetUser(object providerUserKey, bool userIsOnline)
        {
            throw new NotImplementedException();
        }

        public override int MaxInvalidPasswordAttempts
        {
            get { throw new NotImplementedException(); }
        }

        public override int MinRequiredNonAlphanumericCharacters
        {
            get { throw new NotImplementedException(); }
        }

        public override int MinRequiredPasswordLength
        {
            get { throw new NotImplementedException(); }
        }

        public override int PasswordAttemptWindow
        {
            get { throw new NotImplementedException(); }
        }

        public override System.Web.Security.MembershipPasswordFormat PasswordFormat
        {
            get { throw new NotImplementedException(); }
        }

        public override string PasswordStrengthRegularExpression
        {
            get { throw new NotImplementedException(); }
        }

        public override bool RequiresQuestionAndAnswer
        {
            get { throw new NotImplementedException(); }
        }

        public override bool RequiresUniqueEmail
        {
            get { throw new NotImplementedException(); }
        }

        public override string ResetPassword(string username, string answer)
        {
            throw new NotImplementedException();
        }

        public override bool UnlockUser(string userName)
        {
            throw new NotImplementedException();
        }

        public override void UpdateUser(System.Web.Security.MembershipUser user)
        {
            throw new NotImplementedException();
        }
        #endregion
    }
}

Custom LDAP Role Provider

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.DirectoryServices.AccountManagement;
using System.Web.Security;
using Microsoft.SharePoint;

namespace FBA.Extranet.MembershipProvider
{
    public class FBALDAPRoleProvider : RoleProvider
    {

        private string _applicationName = string.Empty;
        public override string ApplicationName
        {
            get
            {
                if (_applicationName == string.Empty)
                {
                    _applicationName = SPContext.Current.Site.ID.ToString();
                }
                return _applicationName;
            }
            set
            {
                this._applicationName = SPContext.Current.Site.ID.ToString();
            }
        }

        public override string[] GetRolesForUser(string username)
        {
            try
            {
                List<string> userGroups = new List<string>();
                SPSecurity.RunWithElevatedPrivileges(new SPSecurity.CodeToRunElevated(delegate()
                {
                    using (PrincipalContext context = new PrincipalContext(ContextType.Domain))
                    {
                        using (UserPrincipal user = UserPrincipal.FindByIdentity(context, username))
                        {
                            if (!(user == null))
                            {
                                PrincipalSearchResult<Principal> results = user.GetAuthorizationGroups();
                                foreach (GroupPrincipal group in results)
                                {
                                    userGroups.Add(group.SamAccountName);
                                }
                            }
                        }
                    }
                }));
                return userGroups.ToArray();
            }
            catch (Exception ex)
            {
                //Log Something
                return null;
            }
        }

        public override string[] GetUsersInRole(string roleName)
        {
            try
            {
                List<string> groupMembers = new List<string>();
                SPSecurity.RunWithElevatedPrivileges(new SPSecurity.CodeToRunElevated(delegate()
                {
                    using (PrincipalContext context = new PrincipalContext(ContextType.Domain))
                    {
                        using (GroupPrincipal groupFilter = new GroupPrincipal(context))
                        {
                            groupFilter.SamAccountName = roleName;
                            foreach (GroupPrincipal group in groupFilter.GetMembers(true))
                            {
                                groupMembers.Add(group.SamAccountName);
                            }
                        }
                    }
                }));
                return groupMembers.ToArray();
            }
            catch (Exception ex)
            {
                //Log something.
                return null;
            }
        }

        public override bool RoleExists(string roleName)
        {
            try
            {
                bool result = false;
                SPSecurity.RunWithElevatedPrivileges(new SPSecurity.CodeToRunElevated(delegate()
                {
                    using (PrincipalContext context = new PrincipalContext(ContextType.Domain))
                    {
                        using (GroupPrincipal groupFilter = GroupPrincipal.FindByIdentity(context, IdentityType.SamAccountName, roleName))
                        {
                            if (groupFilter != null)
                            {
                                result = groupFilter.IsSecurityGroup.Value;
                            }
                        }
                    }
                }));
                return result;
            }
            catch (Exception ex)
            {
                //Log something.
                return false;
            }
        }

        #region Not Implemented Methods
        public override void AddUsersToRoles(string[] usernames, string[] roleNames)
        {
            throw new NotImplementedException();
        }

        public override void CreateRole(string roleName)
        {
            throw new NotImplementedException();
        }

        public override bool DeleteRole(string roleName, bool throwOnPopulatedRole)
        {
            throw new NotImplementedException();
        }

        public override string[] FindUsersInRole(string roleName, string usernameToMatch)
        {
            throw new NotImplementedException();
        }

        public override string[] GetAllRoles()
        {
            throw new NotImplementedException();
        }

        public override bool IsUserInRole(string username, string roleName)
        {
            throw new NotImplementedException();
        }

        public override void RemoveUsersFromRoles(string[] usernames, string[] roleNames)
        {
            throw new NotImplementedException();
        }

        #endregion
    }
}

Implementation

Now that we have the code for the role provider it is a simple matter of deploying the .dll to the GAC and referencing the membership and role provider in the web.config.  You also need to do all the necessary configurations in SharePoint Central Admin, but as I said, that information is readily available via google.  The entries for the web.config are as follows:

Connection String
<connectionStrings>
  <add name="FBAMembershipConnectionString" connectionString="Data Source=.\OfficeServers;Initial Catalog=FBASQLMembership; Integrated Security=True" />
</connectionStrings>
Providers
<!-- membership provider -->
<membership defaultProvider="FBAMemberProvider">
  <providers>
    <add name="FBAMemberProvider" connectionStringName="FBAMembershipConnectionString" 
         enablePasswordRetrieval="false" enablePasswordReset="true" requiresQuestionAndAnswer="false" requiresUniqueEmail="false" passwordFormat="Hashed" maxInvalidPasswordAttempts="5" minRequiredPasswordLength="1" minRequiredNonalphanumericCharacters="0" passwordAttemptWindow="10" passwordStrengthRegularExpression="" type="FBA.Extranet.MembershipProvider.FBAMembershipProvider,FBA.Extranet.MembershipProvider, Version=1.0.0.0, Culture=neutral, PublicKeyToken=<token>" />
  </providers>
</membership>
<!-- role provider -->
<roleManager enabled="true" defaultProvider="FBARoleProvider">
  <providers>
    <add connectionStringName="FBAMembershipConnectionString" name="FBARoleProvider" type="FBA.Extranet.MembershipProvider.FBARoleProvider,FBA.Extranet.MembershipProvider, Version=1.0.0.0, Culture=neutral, PublicKeyToken=<token>" />
  </providers>
</roleManager>

Conclusion

I hope this post helps someone avoid some frustration and I look forward to your comments.

20 comments:

  1. I can see so far that you're using classes available in Framework 3.5. So, it is possible to use these roles and membership providers in SharePoint 2007 without any additional configuration?

    ReplyDelete
  2. Miguel,

    It should work with no problem as long as you have the .NET 3.5 framework installed on the server that is running SharePoint.

    ReplyDelete
  3. Hi Mike.

    I build and deploy this solution and everything seems to work fine, except that when a Windows user (Active Directory) logs in and has total control permission, he/she cannot see the "Site actions" button.

    Am I doing anything wrong with the LDAP Roles Provider? or am I missing any configuration?

    ReplyDelete
  4. Miguel,

    I can't think of anything in my code that would be causing that problem. When you log in with an Active Directory account can you get to the administration pages manually? For example, can you navigate to http:///_layouts/settings.aspx after logging in? If you can, I would say the authentication is working and some other configuration issue is causing the problem.

    Make sure the user has permission necessary to perform site actions tasks. Remember, the Active Directory user, or a group they are a member of, has to be added to the appropriate sharepoint role for whatever you are wanting them to do.

    Hope that helps

    Mike

    ReplyDelete
  5. Hi
    I have to create my custom structure for the fba database table.
    Need some help here. What will be the structure of the table and what are the fields in the table.

    Thanks in advance.

    ReplyDelete
  6. BSukhwal:
    The .NET framework includes a tool that will create the .NET Membership Database objects for you. It can be found at C:\Windows\Microsoft.NET\Framework\v2.0.50727\aspnet_regsql.exe. If you double click on that application it will open a Wizard that walks you through creating the database objects. It can also be run as a command line utility.

    Here is a link to more information about the tool. http://msdn.microsoft.com/en-us/library/x28wfk74(v=VS.100).aspx

    ReplyDelete
  7. Mike,

    I have similar condition to verify user i.e with 2 LDAP provider - one at a time.So I just followed your exmaple and created 2 different LDAP Objects.But getting InvalidOperationException, I am a JAVA guy and trying to understand the flow which points me as 1 provider is initialized from web.config and 2nd trying to initialize as per your old posting.
    Can you give me some pointers how to handle it?


    My Implementaion class

    public class FBAMembershipProvider : FBALDAPMembershipProvider
    {

    public override string ApplicationName
    {
    get
    {
    return SPContext.Current.Site.ID.ToString();
    }
    }

    private OIDLDAPMembershipProvider _oidLDAPProvider = null;
    private OIDLDAPMembershipProvider OIDLDAPProvider
    {
    get
    {
    if (_oidLDAPProvider == null)
    _oidLDAPProvider = new OIDLDAPMembershipProvider();

    System.Collections.Specialized.NameValueCollection nvc = new System.Collections.Specialized.NameValueCollection();
    nvc.Add("server", "xxxx");
    nvc.Add("port", "389");
    nvc.Add("useSSL", "false");
    ......



    _oidLDAPProvider.Initialize("OIDLDAPMembershipProvider", nvc);

    return _oidLDAPProvider;
    }
    }

    public override bool ValidateUser(string username, string password)
    {
    if (base.ValidateUser(username, password))
    return true;
    else if (OIDLDAPProvider.ValidateUser(username, password))
    return true;
    else
    return false;
    }

    ReplyDelete
  8. tosaurav

    I think the process may be a bit simpler if you are using two Active Directory providers. Refer to this article, I don't think it is exactly what you are looking for but it may point you in the right direction.

    http://msdn.microsoft.com/en-us/library/ff650307.aspx

    Thanks

    Mike

    ReplyDelete
  9. Mike,

    Thank you for responding.
    I have AD and Oracle Internet Directory(OID) as providers.Out of these two,AD is primary and if the user doesn't exist in AD have to look into OID.

    Is the InvalidOperationException throws from OID initialization?

    ReplyDelete
  10. I'm afraid I am not familiar at all with OID. I know that the code I provided worked correctly for me in our AD environment. You might check the system event logs to see if you can gleen some more information about exactly what method is throwing the InvalidOperationException. The stack trace should point you in the right direction.

    Sorry I couldn't be of more help.

    Mike

    ReplyDelete
  11. Mike,
    I got success with AD and OID as provider to individual authentication but somehow in case where I need to first look for user in AD and then OID,it's failing due to incorrect sequence of OID initialization.I checked in the event log and the exception corresponds to "The provider is Already initialized" error.Can you please explain the initialization in your above example i.e SQL provider from web.config and then when you create new FBALDAP, initialize it.I believe you haven't repeated the config details from previous post.

    If i delete the below it works fine and finds the AD user but obviously not OID user.

    _oidLDAPProvider.Initialize("OIDLDAPMembershipProvider", nvc);

    ReplyDelete
  12. What type does your FBAMembershipProvider class inherit?

    ReplyDelete
  13. Hi Mike,

    I am at the corner to get it working but somehow couldn't set the AD LDAP config set.I would appreciate your help if you let me know where your are passing the AD config info and how you initializing it.

    Thanks,

    ReplyDelete
  14. I don't "initialize" the AD LDAP Provider. The following line does it for me. You will notice this line exists in every method of the FBALDAPMembershipProvider.

    using (PrincipalContext context = new PrincipalContext(ContextType.Domain))

    ReplyDelete
  15. It Inherits System.Web.Security.MembershipProvider

    public class FBALDAPMembershipProvider : System.Web.Security.MembershipProvider
    {

    In your example where do you have LDAP configuration and Intialization?Can you provide me
    snippet of the same?

    ReplyDelete
  16. Do you think it's possible to change the provider at runtime?

    ReplyDelete
  17. I would make my AD LDAP provider the base type for FBAMembershipProvider and use the built in .NET ad membership provider. Then I would write my own membership provider for the OID provider and call that one if the AD provider failed.

    ReplyDelete
  18. Thank you for suggestion.I have started with same direction but somehow stuck at writing OID provider.

    Is this PrincipalContext available to AD/MSAM only or any LDAP provider?

    using (PrincipalContext context = new PrincipalContext(ContextType.Domain))

    How to pass OID config info to OID provider

    ReplyDelete
  19. Principal context is going to be specific to AD/MSAM. I wish I could help you more but I have absolutely no experience with OID.

    ReplyDelete
  20. If I use LDAPMembershipProvider and set all config info in web.config,it works like a charm but I am not getting idea how to use it to write own provider( newbie in .net)

    ReplyDelete