Error trying to work with a locked account

Topics: FBA, Forms Based Authentication, MOSS, SharePoint
Dec 11, 2008 at 4:10 PM
Hi,

We're using the FBA toolkit in a production environment and have come across an issue with a user account.
For whatever reason, a user in our system has had their account locked-out (too many unsuccessful login attempts maybe?). The problem is, when I go into the 'Manage FBA Users' and click on this account, the account loads, but I can't do anything to it (like reset their password for example). I get this exception:

The user account has been locked out.   at System.Web.Security.SqlMembershipProvider.ResetPassword(String username, String passwordAnswer)
   at System.Web.Security.MembershipUser.ResetPassword(String passwordAnswer)
   at System.Web.Security.MembershipUser.ResetPassword()
   at ASP._layouts_fba_management_useredit_aspx.OnResetPassword(Object sender, EventArgs e) in c:\Program Files\Common Files\Microsoft Shared\web server extensions\12\TEMPLATE\LAYOUTS\FBA\MANAGEMENT\UserEdit.aspx:line 135
   at System.Web.UI.WebControls.Button.OnClick(EventArgs e)
   at System.Web.UI.WebControls.Button.RaisePostBackEvent(String eventArgument)
   at System.Web.UI.WebControls.Button.System.Web.UI.IPostBackEventHandler.RaisePostBackEvent(String eventArgument)
   at System.Web.UI.Page.RaisePostBackEvent(IPostBackEventHandler sourceControl, String eventArgument)
   at System.Web.UI.Page.RaisePostBackEvent(NameValueCollection postData)
   at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)



I would think that the FBA toolkit should better handle this exception (and probably needs to provide an 'unlock user account' button on the edit page).
I may implement this and submit the code back to the group when I have time, but to resolve the problem I'm currently having on our live site, has anyone else come across this problem? What did you do to resolve it?

Thanks,
-Mike
Mar 5, 2009 at 2:59 PM
I just ran into this as well and for what it's worth, I just set the IsLockedOut flag in the aspnet_Membership table back to False.  I couldn't find any way to correct this using the FBA management page with the version I'm using.

I would be interested if anyone has a better solution but I'm planning to migrate to Live ID Authentication in the future.  It seems like less of a hassle than trying to maintain the accounts myself.
Jul 28, 2009 at 10:06 PM

Here is what I did to provide a way to manage the isLockedOut status of member users...

Modify the UserEdit.aspx page within the "_layouts\FBA\MANAGEMENT" web folder.

Add a second checkbox control below the one already there for indicating the account's active status...

<wssuc:InputFormSection runat="server" id="CategorySection1" Title="Active">
 <Template_InputFormControls>
  <wssuc:InputFormControl runat="server">
   <Template_Control>
    <wssawc:InputFormCheckBox ID="isActive" ToolTip="If checked the account is active." LabelText="Check the box if the user's account is active." runat="server"/>
    <wssawc:InputFormCheckBox ID="isLockedOut" ToolTip="If checked the account is locked out." LabelText="Uncheck the box to unlock the user's account." runat="server"/>
   </Template_Control>
  </wssuc:InputFormControl>
 </Template_InputFormControls>
</wssuc:InputFormSection>

Add code to set the current value to the existing Page_Load script (in the same file)...

isActive.Checked = user.IsApproved;
isLockedOut.Checked = user.IsLockedOut;

Add code in the OnSubmit method to unlock user account when found in locked state and UI check box has been cleared...

user.Email = txtEmail.Text;
user.IsApproved = isActive.Checked;
if (user.IsLockedOut && !isLockedOut.Checked)
{
   user.UnlockUser();
}
Membership.UpdateUser(user);

 

Simple as that!
-Alan

Aug 2, 2009 at 9:52 PM

Thanks alot for the above info, it appears to be exactly what I am after.

My only query is I can find where to put the wssawc:InputFormCheckBox section in my useredit.aspx file but I cant seem to work out exactly where to put the second sections?
I am fairly new to the coding side of things so still a little green at this side of things. Thanks for any extra info you can provide.

Nov 1, 2010 at 12:21 PM

Unlocking locked users in FBA

 

 

Update "UserEdit.aspx and UserEdit.cs" with below given code.

Edit "UserEdit.aspx" page present under "C:\Inetpub\wwwroot\wss\VirtualDirectories\WebApplication80\LAYOUTS\FBA\MANAGEMENT\UserEdit.aspx"(If you have already installed and configured FBA. ) and in FBA code also. Replace below given code and save the page.

 

____UserEdit.aspx______________________________________________________________________________________________________________________________________________________________

<%@ Assembly Name="Microsoft.SharePoint.ApplicationPages, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>

<%@ Page Inherits="CKS.FormsBasedAuthentication.UserEdit, CKS.FormsBasedAuthentication, Version=1.0.0.0, Culture=neutral, PublicKeyToken=d0c9b215512a2c5d"
    Language="C#" MasterPageFile="~/_layouts/application.master" %>

<%@ Register Src="~/_controltemplates/ToolBar.ascx" TagName="ToolBar" TagPrefix="wssuc" %>
<%@ Register Src="~/_controltemplates/ToolBarButton.ascx" TagName="ToolBarButton"
    TagPrefix="wssuc" %>
<%@ Register Src="~/_controltemplates/InputFormSection.ascx" TagName="InputFormSection"
    TagPrefix="wssuc" %>
<%@ Register Src="~/_controltemplates/InputFormControl.ascx" TagName="InputFormControl"
    TagPrefix="wssuc" %>
<%@ Register Src="~/_controltemplates/ButtonSection.ascx" TagName="ButtonSection"
    TagPrefix="wssuc" %>
<%@ Register Assembly="Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c"
    Namespace="Microsoft.SharePoint.WebControls" TagPrefix="SharePoint" %>
<asp:Content ID="Content1" runat="server" ContentPlaceHolderID="PlaceHolderPageTitle">
    <SharePoint:EncodedLiteral ID="PageTitle" runat="server" EncodeMethod="HtmlEncode"
        Text="Edit Forms Based Authentication User">
    </SharePoint:EncodedLiteral>
</asp:Content>
<asp:Content ID="Content2" runat="server" ContentPlaceHolderID="PlaceHolderPageTitleInTitleArea">
    <SharePoint:EncodedLiteral ID="TitleArea" runat="server" EncodeMethod="HtmlEncode"
        Text="Edit Forms Based Authentication User">
    </SharePoint:EncodedLiteral>
</asp:Content>
<asp:Content ID="Content3" runat="server" ContentPlaceHolderID="PlaceHolderAdditionalPageHead">

    <script type="text/javascript">
        function confirmPasswordReset()
        {
            return confirm("<SharePoint:EncodedLiteral runat='server' text='Are you sure you want to reset the password? The user will be emailed the new password' EncodeMethod='EcmaScriptStringLiteralEncode'/>");
        }
    </script>

</asp:Content>
<asp:Content ID="Content4" runat="server" ContentPlaceHolderID="PlaceHolderMain">
    <table border="0" cellpadding="0" cellspacing="0" class="ms-descriptiontext" width="100%">
        <wssuc:InputFormSection runat="server" Title="User Name">
            <template_inputformcontrols>
            <wssuc:InputFormControl runat="server" LabelText="Username is read only:">
                <Template_Control>
                <SharePoint:InputFormTextBox Title="Username" Enabled="false" ReadOnly="true" class="ms-input" Columns="40" maxlength="255" ID="txtUsername" Direction="LeftToRight" Runat="server" />
                <SharePoint:InputFormRequiredFieldValidator ID="InputFormRequiredFieldValidator1" ControlToValidate="txtUsername" Display="Dynamic" Runat="server"/>
                <asp:Label ID="usernameMessage" runat="server" Text="" ForeColor="red"></asp:Label>
                </Template_Control>
            </wssuc:InputFormControl>
        </template_inputformcontrols>
        </wssuc:InputFormSection>
        <wssuc:InputFormSection runat="server" Title="Full Name">
            <template_inputformcontrols>
            <wssuc:InputFormControl runat="server" LabelText="Type the full name:">
                <Template_Control>
                    <SharePoint:InputFormTextBox Title="Full Name" class="ms-input" Columns="40" maxlength="255" ID="txtFullName" Direction="LeftToRight" Runat="server" />
                    <SharePoint:InputFormRequiredFieldValidator ID="InputFormRequiredFieldValidator2" ControlToValidate="txtFullName" Display="Dynamic" Runat="server"/>
                </Template_Control>
            </wssuc:InputFormControl>
        </template_inputformcontrols>
        </wssuc:InputFormSection>
        <wssuc:InputFormSection runat="server" Title="Email">
            <template_inputformcontrols>
            <wssuc:InputFormControl runat="server" LabelText="Type the user's email address:">
                <Template_Control>
                <SharePoint:InputFormTextBox Title="txtEmail" class="ms-input" Columns="40" maxlength="255" ID="txtEmail" Direction="LeftToRight" Runat="server" />
                <SharePoint:InputFormRegularExpressionValidator ID="InputFormRegExpressionFieldValidator1"  ControlToValidate="txtEmail" Display="Dynamic" runat="server" ValidationExpression="^[a-zA-Z][\w\.-]*[a-zA-Z0-9]@[a-zA-Z0-9][\w\.-]*[a-zA-Z0-9]\.[a-zA-Z][a-zA-Z\.]*[a-zA-Z]$" ErrorMessage="Enter a valid email address."/>
                </Template_Control>
            </wssuc:InputFormControl>
        </template_inputformcontrols>
        </wssuc:InputFormSection>
        <wssuc:InputFormSection id="CategorySection1" runat="server" Title="Active">
            <template_inputformcontrols>
            <wssuc:InputFormControl runat="server">
                <Template_Control>
                    <SharePoint:InputFormCheckBox ID="isActive" ToolTip="If checked the account is active." LabelText="Check the box if the user's account is active." runat="server"/>
                    <SharePoint:InputFormCheckBox ID="isLockedOut" ToolTip="If checked the account is locked out." LabelText="Uncheck the box to unlock the user's account." runat="server"/>
                </Template_Control>
            </wssuc:InputFormControl>
        </template_inputformcontrols>
        </wssuc:InputFormSection>
        <wssuc:InputFormSection id="GroupSection" runat="server" Title="Groups">
            <template_inputformcontrols>
            <wssuc:InputFormControl runat="server" LabelText="Choose atleast one group to add the user to:">
                <Template_Control>
                    <SharePoint:InputFormCheckBoxList ID="groupList" CssClass="ms-RadioText" ToolTip="Select the roles for this user" runat="server"/>
                </Template_Control>
            </wssuc:InputFormControl>
        </template_inputformcontrols>
        </wssuc:InputFormSection>
        <wssuc:InputFormSection id="RolesSection" runat="server" Title="Roles">
            <template_inputformcontrols>
            <wssuc:InputFormControl runat="server">
                <Template_Control>
                    <SharePoint:InputFormCheckBoxList ID="rolesList" CssClass="ms-RadioText" ToolTip="Select the roles for this user" runat="server"/>
                </Template_Control>
            </wssuc:InputFormControl>
        </template_inputformcontrols>
        </wssuc:InputFormSection>
        <wssuc:ButtonSection runat="server">
            <template_buttons>
            <asp:Button UseSubmitBehavior="false" runat="server" class="ms-ButtonHeightWidth" Width="100px" OnClick="OnResetPassword" OnClientClick="if (!confirmPasswordReset()) return false;" Text="Reset Password" id="BtnReset" accesskey="P"/>
            <asp:Button UseSubmitBehavior="false" runat="server" class="ms-ButtonHeightWidth" OnClick="OnSubmit" Text="Save" id="BtnOk" accesskey="<%$Resources:wss,okbutton_accesskey%>"/>       
        </template_buttons>
        </wssuc:ButtonSection>
    </table>
</asp:Content>

_____________________________________________________________________________________________________________________________________________________________________________

 

After this, edit "UserEdit.cs" from source code and replace below given code.

 

______________UserEdit.cs____________________________________________________________________________________________________________

 

using System;
using System.Web.Security;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Administration;
using Microsoft.SharePoint.WebControls;
using Microsoft.SharePoint.Utilities;
using System.Web.UI.WebControls;

namespace CKS.FormsBasedAuthentication
{
    /// <summary>
    /// Code behind for UserEdit.aspx
    /// </summary>
    public class UserEdit : LayoutsPageBase
    {
        protected InputFormSection GroupSection;
        protected InputFormSection RolesSection;
        protected InputFormCheckBoxList groupList;
        protected InputFormCheckBoxList rolesList;
        protected InputFormCheckBox isActive;
        protected InputFormCheckBox isLockedOut;
        protected InputFormTextBox txtEmail;
        protected InputFormTextBox txtPassword;
        protected InputFormTextBox txtFullName;
        protected InputFormTextBox txtUsername;
        protected Label lblMessage;
        protected Button BtnReset;

        private bool _showRoles;

        protected override bool RequireSiteAdministrator
        {
            get { return true; }
        }

        protected override void OnLoad(EventArgs e)
        {
            this.CheckRights();

            // If Membership.RequiresQuestionAndAnswer is true, then we need the password answer, which we don't have.
            // Also check to make sure ResetPassword is allowed. 
            if (System.Web.Security.Membership.RequiresQuestionAndAnswer || !System.Web.Security.Membership.EnablePasswordReset)
            {
                BtnReset.Visible = false;
            }

            // init
            _showRoles = (this.Site.Features[new Guid("F3808A5F-354C-4216-BF9E-DCFA8C44F0FC")] != null);
            SPIisSettings settings = Utils.GetFBAIisSettings(this.Site);

            // get user info
            string userName = this.Request.QueryString["USERNAME"];
            SPUser spuser = null;
            try
            {
                spuser = this.Web.AllUsers[settings.MembershipProvider + ":" + userName];
            }
            catch
            {
               
            }
            MembershipUser user = Membership.GetUser(userName);

            if (user != null)
            {
                if (!Page.IsPostBack)
                {
                    // load user props
                    if (spuser != null)
                    {
                        txtEmail.Text = spuser.Email;
                        txtFullName.Text = spuser.Name;
                    }
                    else
                    {
                        txtEmail.Text = user.Email;
                        txtFullName.Text = user.UserName;
                    }
                    txtUsername.Text = user.UserName;
                    isActive.Checked = user.IsApproved;
                    isLockedOut.Checked = user.IsLockedOut;

                    // if roles activated display roles
                    if (_showRoles)
                    {
                        RolesSection.Visible = true;
                        GroupSection.Visible = false;

                        try
                        {
                            // load roles
                            string[] roles = Roles.GetAllRoles();
                            rolesList.DataSource = roles;
                            rolesList.DataBind();

                            // select roles associated with the user
                            for (int i = 0; i < roles.Length; i++)
                            {
                                rolesList.Items.FindByText(roles[i].ToString()).Selected = Roles.IsUserInRole(user.UserName, roles[i].ToString());
                            }
                        }
                        catch (Exception ex)
                        {
                            Utils.LogError(ex, true);
                        }
                    }
                    // otherwise display groups
                    else if(spuser != null)
                    {
                        GroupSection.Visible = true;
                        RolesSection.Visible = false;

                        try
                        {
                            // load groups
                            groupList.DataSource = this.Web.Groups;
                            groupList.DataBind();

                            // select groups associated with the user
                            foreach (SPGroup group in spuser.Groups)
                            {
                                groupList.Items.FindByText(group.Name).Selected = true;
                            }
                        }
                        catch (Exception ex)
                        {
                            Utils.LogError(ex, true);
                        }
                    }
                }
            }
            else
            {
                SPUtility.TransferToErrorPage("User Not Found");
            }
        }

        protected void OnSubmit(object sender, EventArgs e)
        {
            // get user info
            SPIisSettings settings = Utils.GetFBAIisSettings(this.Site);
            string userName = this.Request.QueryString["USERNAME"];
            SPUser spuser = null;
            // This could be done with EnsureUsers, which won't throw an exception if the user hasn't logged on to the site.
            try
            {
                spuser = this.Web.AllUsers[settings.MembershipProvider + ":" + userName];
            }
            catch
            {

            }
            MembershipUser user = Membership.GetUser(userName);

            // check user exists
            if (user != null)
            {
                try
                {
                    // TODO: If we want the Email to be used for the user account, we need to delete the user and create a new one with the new email address.
                    // This will mean we need to iterate over the groups that the user is a member of, in all site collections in all web apps, and add the new user
                    // to those groups.  In the meantime, we allow the email to be changed, but this won't update the account username.

                    // update membership provider info
                    user.Email = txtEmail.Text;
                    user.IsApproved = isActive.Checked;
                

                    if (user.IsLockedOut && !isLockedOut.Checked)
                    {
                       user.UnlockUser();
                    }

                       Membership.UpdateUser(user);




                    // update sharepoint user info
                    if (spuser != null)
                    {
                        spuser.Email = txtEmail.Text;
                        spuser.Name = txtFullName.Text;
                        spuser.Update();
                    }

                    // if roles enabled add/remove user to selected role(s)
                    if (_showRoles)
                    {
                        for (int i = 0; i < rolesList.Items.Count; i++)
                        {
                            if (rolesList.Items[i].Selected)
                            {
                                if (!Roles.IsUserInRole(user.UserName, rolesList.Items[i].Value))
                                    Roles.AddUserToRole(user.UserName, rolesList.Items[i].Value);
                            }
                            else
                            {
                                if (Roles.IsUserInRole(user.UserName, rolesList.Items[i].Value))
                                    Roles.RemoveUserFromRole(user.UserName, rolesList.Items[i].Value);
                            }
                        }
                    }
                    // or add/remove user to selected group(s)
                    else if(spuser != null)
                    {
                        for (int i = 0; i < groupList.Items.Count; i++)
                        {
                            string groupName = groupList.Items[i].Value;

                            // determine whether user is in group
                            bool userInGroup = false;
                            foreach (SPGroup group in spuser.Groups)
                            {
                                if (group.Name == groupName)
                                {
                                    userInGroup = true;
                                    break;
                                }
                            }

                            // if selected add user to group
                            if (groupList.Items[i].Selected)
                            {
                                // only add if not already in group
                                if (!userInGroup)
                                    this.Web.Groups[groupName].AddUser(spuser);
                            }
                            // else remove user from group
                            else
                            {
                                // only attempt remove if actually in the group
                                if (userInGroup)
                                    this.Web.Groups[groupName].RemoveUser(spuser);
                            }
                        }
                    }
                    Response.Redirect("UsersDisp.aspx");
                }
                catch (Exception ex)
                {
                    Utils.LogError(ex, true);
                }
            }
            else
            {
                SPUtility.TransferToErrorPage("User Not Found");
            }
        }

        protected void OnResetPassword(object sender, EventArgs e)
        {
            // If Membership.RequiresQuestionAndAnswer is true, then we need the password answer, which we don't have.
            // Also check to make sure ResetPassword is allowed. 
            if (!System.Web.Security.Membership.RequiresQuestionAndAnswer && System.Web.Security.Membership.EnablePasswordReset)
            {
                string userName = this.Request.QueryString["USERNAME"];
                MembershipUser user = Membership.GetUser(userName);
               
                // TODO: use xslt email

                if (user.IsLockedOut && !isLockedOut.Checked)
                {
                    user.UnlockUser();
                }

                Membership.UpdateUser(user);
                string newPassword = user.ResetPassword();

                string body = "Your new password is: " + newPassword;
                SPUtility.SendEmail(this.Web, false, false, user.Email, "Password Reset for " + this.Web.Title, body);
            }
        }
    }
}

_________________________________________________________________________________

Save the "UserEdit.cs and UserEdit.aspx" and rebuild project.Replace the DLL in (Webapplication)BIN/GAC(Reset IIS if placed in GAC.)

 

Done!!!!!!!!!!!!!!!!!

 

Thanks,

Avinash.Devkate.