FBA (IEE): user provision: problem adding to default group

Topics: Internet/Extranet Edition
Sep 9, 2008 at 12:14 PM
Edited Sep 9, 2008 at 12:15 PM
  

Hi there,

First off all, congrats for such excellent set of features and extensions.

I am mainly using the FBA(IEE) module with the following scenario:

* Default zone (www.mysite.local private site used for authoring only) with Windows authentication
* Internet zone (www.mysite.pt public site) with FBA on top of SQL (.net authentication DB)

The user creation/registration process is working fine, except for the part where the user is added to the default group.
I have debugged the problem (including SQL profile) to detect the problem and this is what I know:

1 - there is an exception raised when the following code is executed ()
    if (createStatus == MembershipCreateStatus.Success)
                    {
                        //Add the user to the default group
                        if (!String.IsNullOrEmpty(request.DefaultGroup))
                        {
                            web.Groups[request.DefaultGroup].AddUser(request.UserName.ToLower(), request.UserEmail, request.UserName.ToLower(), "Self Registration"); 
                                        // this throws the Microsoft.SharePoint.SPException 
                                        //with a message like "The user does not exist is not exclusive."
                        }
                    }

 

2 - the user exists in the database at the time of the call. During debug I checked the users table.

3 - the problem seems to be that the users list contains the list of WINDOWS users and not the DATABASE!
    I detected this inspecting the web.AllUsers collection, which had the windows users and not the database users.
    At this time, the "web" object is also pointing to the ".local" site that is configured with windows authentication

I suspect that configuring the default zone to the FBA would solve the problem, but in this zone I need windows authentication.

Please advise.
I have a deployment in place and detected this too close to production....
Thanks in advance

 Rui

 

Developer
Sep 9, 2008 at 3:03 PM
Is this when using the registration approval process (e.g. the Membership Review List feature is active) or automatic registration?  Also, what changeset are you running?

Regards,
Mike Sharp
Sep 11, 2008 at 5:06 PM
Mike,

thank you for your reply.
 

As I wasn't sure on the change set, I have downloaded a more recente one (17271) and tried the scenario.

 

The problem persists.

 

Problem description:

After users are added to the provider, they should be assigned to the default sharepoint group (there is code implemented to do this), but they don't.

 

So here are some evidences I could find:

  • Forms Based Authentication Site Membership Review List is deactivated
  • Site settings > FBA User Management > New user: works as a charm. No problem here.
  • Created a new page and added the membership request webpart:
    • When I access this page and fill the request form I get the message "The user does not exist or is not unique. "

  

Note: I had do add the safecontrol key in web.config manually.

      <SafeControl Assembly="CKS.FormsBasedAuthentication, Version=1.0.0.0, Culture=neutral, PublicKeyToken=d0c9b215512a2c5d" Namespace="CKS.FormsBasedAuthentication" TypeName="*" Safe="True" />

 

I will try to debug into the code to pinpoint the problem, but I will only be able to this tonight (GMT).

Thanks again,
Regards,
Rui Melo 

Developer
Sep 11, 2008 at 9:36 PM
Changeset 17271 was made after the FBA code was re-organized and cleaned up by Zac, in preparation for the upcoming release.  My comments below are based on changeset 17054.   If you use 17054 (temporarily, until the release is out), you should be able to fix this issue.  I think the problem with default groups may be a separate issue (but it may start working after you implement the change below).  

Anyway, I've seen the error you're seeing with the Membership Request Web part.  What is happening is that the CreateUserWizard base class is calling a private method called AttemptCreateUser, but it's doing it *after* you've already created yours, which is why you get the duplicate username error.  Unfortunately, you can't override that method, so you have to fix things after the user is created.

Here's what I did to fix it in MembershipRequestControl.cs.  My OnCreatingUser looks like this (which is also probably what yours looks like).  This code handles the case where your have the Membership Review List activated, and you're approving new members: 

        protected override void OnCreatingUser(LoginCancelEventArgs e)
        {
            SPSite site = SPControl.GetContextSite(Context);
            if (site.Features[new Guid("{69CE2076-9A2F-4c71-AEDF-F4252C01DE4E}")] != null)
            {
                /* bms Prevent user from being added to the list multiple times if the user */
                /* is already in use.                                                       */
                if (Membership.GetUser(this.UserName) == null)
                {
                    MembershipRequest request = new MembershipRequest();
                    request.UserEmail = this.Email;
                    request.UserName = this.UserName;
                    request.PasswordQuestion = this.Question;
                    request.PasswordAnswer = this.Answer;
                    request.FirstName = this.FirstName;
                    request.LastName = this.LastName;
                    request.DefaultGroup = this._DefaultGroup;
                    MembershipRequest.CopyToReviewList(request);
                }
                this.MoveTo(this.CompleteStep);
            }
            else
            {
                base.OnCreatingUser(e);
            }
        }

Now if you want members to auto-approve, you deactivate the Membership Review List (which is your case, I believe).  To handle this case I added a new method called OnCreatedUser which is called after the base class creates it's user.  Then when ApproveMembershipRequest is called, it deletes the temporarily created user and re-creates it with the proper password and group memberships.

        protected override void OnCreatedUser(EventArgs e)
        {
            SPSite site = SPControl.GetContextSite(Context);
            if (site.Features[new Guid("{69CE2076-9A2F-4c71-AEDF-F4252C01DE4E}")] == null)
            {
                // Note: this doesn't run using the privileges of the anonymous user, so we elevate them
                // Also, you can't use the original Site even with elevated privileges, otherwise it reverts back to anonymous.
                SPSecurity.RunWithElevatedPrivileges(delegate()
                {
                    using (SPSite site2 = new SPSite(this.Page.Request.Url.ToString()))
                    {
                        using (SPWeb web = site2.RootWeb)
                        {
                                MembershipRequest request = new MembershipRequest();
                                request.UserEmail = this.Email;
                                request.UserName = this.UserName;
                                if (System.Web.Security.Membership.RequiresQuestionAndAnswer)
                                {
                                    request.PasswordQuestion = this.Question;
                                    request.PasswordAnswer = this.Answer;
                                }
                                request.FirstName = this.FirstName;
                                request.LastName = this.LastName;
                                request.SiteName = web.Title;
                                request.SiteURL = web.Url;
                                request.ChangePasswordURL = string.Format("{0}/{1}", web.Url, web.Properties[MembershipReviewSiteURL.CHANGEPASSWORDPAGE]);
                                MembershipRequest.ApproveMembership(request, web);
                                this.MoveTo(this.CompleteStep);

                        }
                    }
                });

            }
            else
            {
                base.OnCreatedUser(e);
            }
        }


Give this a shot, and see if it helps.  But you might want to use Changeset 17054 with this change, though it should also work in the latest changeset--I just haven't tested it myself.

Regards,
Mike Sharp

Sep 12, 2008 at 12:41 AM
Mike,

I've tried your suggestion and it worked!
I have used the 17054 change set with the OnCreatedUser method.
Thanks a lot you for your time and support.

Regards,
Rui