Take the 2-minute tour ×
SharePoint Stack Exchange is a question and answer site for SharePoint enthusiasts. It's 100% free, no registration required.

I've searched online at all different documents regarding FBA custom login page for Sharepoint 2010. Nearly everyone I have found, either shows you a custom page, adds a login control and no code behind, and the page works. (I've tried this and can confirm it works). However I need to have code behind as I'm testing if a user requires them to change their password.

Using reflecter I've been able to create my login page using FormsSignInPage as a base class. My OnLogginIn event and OnAUthenticate micks what microsoft does in their code in a round about way. However, once the user has been authenticated I was hoping to call my custom membership provider find out if the user needs to change thier password and open a pop up dialog pointing to a layouts page that allows them to change thier password. If they change their password, the user is redirected to site, if they cancel or close the dialog, the code logs them out as they are required to change thier password to continue using the site.

Using my code, and removing any redirects, I expected my code to authenticate and update a label on the page saying "User to change password" or "User doesn't need to change password". However with my code, even without any redirects on the page, it still redirects the user to the original page they were heading to, before needing to login. I cannot work out why, how, or what I need to change. My code is shown below which might help other people out when creating their own page.

ASP.NET

<asp:Content ID="Content2" ContentPlaceHolderId="PlaceHolderMain" runat="server">
    <asp:Literal ID="litInfo" runat="server"/>
          <center>
            <div id="content" class="rounded" style="width: 300px; height: auto; margin-top: 15%; background:black;">
                <!--//Standard Login control with set custom MembershipProvider FBAMembershipProvider -->
                <asp:Login ID="hlsignInControl" 
                           style="width: 250px" 
                           FailureText="<%$Resources:wss,login_pageFailureText%>" 
                           runat="server" 
                           DisplayRememberMe="true" 
                           TextBoxStyle-Width="250px" 
                           RememberMeSet="false" 
                           LoginButtonStyle-CssClass="ms-buttonheightwidth" 
                           UserNameLabelText="User name" 
                           TextLayout="TextOnTop" 
                           PasswordLabelText="Password" 
                           LabelStyle-Font-Bold="false" 
                           LabelStyle-Font-Size="Large" 
                           LabelStyle-ForeColor="White" 
                           LabelStyle-Font-Names="Calibri" 
                           LabelStyle-CssClass="ms-standardheader ms-inputformheader" 
                           TextBoxStyle-CssClass="ms-input" 
                           CheckBoxStyle-Font-Bold="false" 
                           CheckBoxStyle-Font-Names="Calibri" 
                           CheckBoxStyle-ForeColor="White" 
                           CheckBoxStyle-CssClass="ms-standardheader ms-inputformheader" 
                           CheckBoxStyle-Font-Size="Large" 
                           FailureTextStyle-Wrap="true" 
                           FailureTextStyle-Font-Names="Calibri" 
                           FailureTextStyle-Font-Size="Small" 
                           LoginButtonStyle-Font-Names="Calibri" 
                           LoginButtonStyle-Font-Size="Large" 
                           TitleText="" 
                           TitleTextStyle-ForeColor="White" 
                           TitleTextStyle-Font-Bold="true" 
                           TitleTextStyle-Wrap="true" 
                           TitleTextStyle-Font-Names="Calibri" 
                           TitleTextStyle-Font-Size="Larger"
                           OnAuthenticate = "hlsignInControl_Authenticate"
                           OnLoggingIn = "hlsignInControl_LoggingIn"
                           OnLoggedIn = "hlsignInControl_LoggedIn"/> 

         </div>  
       </center>
          <!-- //Required from inherited class "FormsSignInPage"-->
            <SharePoint:EncodedLiteral runat="server" EncodeMethod="HtmlEncode" ID="ClaimsFormsPageMessage" Visible="false" /> 
                          </asp:Content> 

C# Code

using System;
using System.IdentityModel.Tokens;
using System.Web.UI.WebControls;
using SharePoint.FBA.Code.HelperClasses;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Administration;
using Microsoft.SharePoint.Administration.Claims;
using Microsoft.SharePoint.IdentityModel;
using Microsoft.SharePoint.IdentityModel.Pages;
using Microsoft.SharePoint.Utilities;
using Microsoft.SharePoint.WebControls;

namespace SharePoint.FBA.Layouts.Login
{
   public partial class Login : FormsSignInPage
   {
        protected override void OnLoad(EventArgs e)
        {
            //base.OnLoad(e);
            hlsignInControl.Focus();
            CheckBox box = null;
            if (SPSecurityTokenServiceManager.Local.UseSessionCookies && ((box = this.hlsignInControl.FindControl("RememberMe") as CheckBox) != null))
            {
                box.Enabled = false;
                box.Visible = false;
            }
        }



        protected void hlsignInControl_LoggedIn(object sender, EventArgs e)
        {
            var s = "I'm Logged in now what!";

        }

        protected void hlsignInControl_Authenticate(object sender, System.Web.UI.WebControls.AuthenticateEventArgs e)
        {
            bool flag = false;
            var loginControl = sender as System.Web.UI.WebControls.Login;
            SecurityToken securityToken = null;
            if (loginControl == null)
            {
                throw new ArgumentException(null, "sender");
            }
            using (new SPMonitoredScope("Login.Authenticate: Retrieve Security token and establish session."))
            {
                securityToken = this.GetSecurityToken(loginControl);
                if (securityToken == null)
                {
                    flag = false;
                }
                else
                {
                    SPSessionTokenWriteType writeDefaultCookie = SPSessionTokenWriteType.WriteDefaultCookie;
                    if (!SPSecurityTokenServiceManager.Local.UseSessionCookies && !loginControl.RememberMeSet)
                    {
                        writeDefaultCookie = SPSessionTokenWriteType.WriteSessionCookie;
                    }
                    EstablishSessionWithToken(securityToken, writeDefaultCookie);
                    flag = true;
                }
            }
            e.Authenticated = flag;
            if (flag)
            {

                var mem = (MyMembershipProvider)Utils.BaseMembershipProvider();
                HLMembershipUser memUser;

                memUser = (MyMembershipUser)mem.GetUser(loginControl.UserName, true);
                if (memUser.IsPasswordChanged)
                {
                    litInfo.Text = "Password need Changing";
                    //
                }
                else
                {
                    litInfo.Text = "Password fine";
                    //Removed this line to prevent redirect, although it redirects anyway.
                    //RedirectToSuccessUrl();
                }


            }
        }

        protected void hlsignInControl_LoggingIn(object sender, System.Web.UI.WebControls.LoginCancelEventArgs e)
        {
            var login = sender as System.Web.UI.WebControls.Login;
            if (login == null)
            {
                throw new ArgumentException(null, "sender");
            }
            login.UserName = login.UserName.Trim();
            if (string.IsNullOrEmpty(login.UserName))
            {
                ClaimsFormsPageMessage.Text = "The server could not sign you in. The user name cannot be empty.";
                e.Cancel = true;
            }

            if (string.IsNullOrEmpty(login.Password))
            {
                ClaimsFormsPageMessage.Text = "The server could not sign you in. The password cannot be emtpy.";
                e.Cancel = true;
            }
        }

        private SecurityToken GetSecurityToken(System.Web.UI.WebControls.Login loginControl)
        {
            SPIisSettings iisSettings = IisSettings;
            Uri appliesTo = new Uri(SPContext.Current.Web.Url);
            if (!iisSettings.UseClaimsAuthentication || !iisSettings.UseFormsClaimsAuthenticationProvider)
            {
                throw new InvalidOperationException();
            }
            if (string.IsNullOrEmpty(loginControl.UserName) || (loginControl.Password == null))
            {
                return null;
            }

            SPFormsAuthenticationProvider formsClaimsAuthenticationProvider =
                iisSettings.FormsClaimsAuthenticationProvider;
            return SPSecurityContext.SecurityTokenForFormsAuthentication(appliesTo,
                                                                         formsClaimsAuthenticationProvider.
                                                                             MembershipProvider,
                                                                         formsClaimsAuthenticationProvider.RoleProvider,
                                                                         loginControl.UserName, loginControl.Password,
                                                                         loginControl.RememberMeSet);

        }

        private SPIisSettings IisSettings
        {
            get { 
                SPWebApplication webApp = SPWebApplication.Lookup(new Uri(SPContext.Current.Web.Url));
                SPIisSettings settings = webApp.IisSettings[SPContext.Current.Site.Zone];
                return settings;
            }
        }

        private void EstablishSessionWithToken(SecurityToken securityToken, SPSessionTokenWriteType sessionCookie)
        {
            if (securityToken == null)
            {
                throw new ArgumentNullException("securityToken");
            }
            SPFederationAuthenticationModule fam = SPFederationAuthenticationModule.Current;
            if (fam == null)
            {
                throw new ArgumentException(null, "FederationAuthenticationModule");
            }

            SPSecurity.RunWithElevatedPrivileges(() => fam.SetPrincipalAndWriteSessionToken(securityToken));

        }


    }
}
share|improve this question
    
Have you seen this (Steve Peschka is the authority in this) blogs.technet.com/b/speschka/archive/2010/07/22/… –  C. Marius - MVP Aug 10 '12 at 10:14
    
I have, it hasn't helped me. –  Cann0nF0dder Aug 10 '12 at 10:54
add comment

2 Answers

up vote 0 down vote accepted

Thank you everyone who made a comment, In the end I went with the option not to use the ASP:Login as I couldn't control it the way I wanted to. As I posted 2 questions on here relating to the FBA, I've posted my final solution code in the other question. How to create a custom FBA login Page that forces user to change password and view license agreement if required

The simple code that logs a person into SharePoint which also allows them to log out with an invalid parameter Encoded message is:

 private void SignInUser()
        {
            var mem = (MyMembershipProvider) Utils.BaseMembershipProvider();
            var role = (MyRoleProvider) Utils.BaseRoleProvider();
            if (!mem.ValidateUser(_userName, _password))
            {
                return;
            }

            SecurityToken token = SPSecurityContext.SecurityTokenForFormsAuthentication
                                             (new Uri(SPContext.Current.Web.Url),
                                             mem.Name,
                                             role.Name,
                                             _userName,
                                             _password,
                                             _remember);
            SPFederationAuthenticationModule.Current.SetPrincipalAndWriteSessionToken(token);

            Response.Redirect(Request.QueryString["Source"]);
        }
share|improve this answer
add comment

It is the asp:Login control that does the redirect. When you set the Authenticated property on your EventArs to true, you're telling the page to redirect (since you've got Reflector check out the AttemptLogin() method of the Login webcontrol).

I've implemented something very similar to what you are trying and had to take a slightly different approach. I went ahead and called the GetSecurityToken() to make sure the credentials were good. If they were good I would do all my additional checks first. Once the they were finished with the additional screens, I sent them back to the main screen to do the login again. Basically I didn't set the cookie or the EventArgs flag until everything was done. This is fairly stripped down, but it was my general order of operations:

using (new SPMonitoredScope())
{
    securityToken = this.GetSecurityToken(formsSignInControl);
    flag = securityToken != null;
}

User user = GetUser(formsSignInControl);

/////////////////////////////
//Check Lockout
/////////////////////////////
if (user != null && user.IsLockedOut)
{
    lblMessage.Text = "Account Locked.";        
    return;
}

if (flag)
{
    //////////////////////////
    //Is First Time Signing On
    //////////////////////////
    if (user.IsFirstSignOn)
    {
        //Load Security Questions       
        //Show different panel
        return;
    }

    /////////////////////////
    //Password Reset
    /////////////////////////
    if (user.MustReset)
    {
        //Show 'Reset' message
        //Show different panel
        return;
    }
} 

e.Authenticated = flag;

if (flag)
{
    //SetPrincipalAndWriteSessionToken()    
    base.RedirectToSuccessUrl();
}
else
{
    //Show Error
}
share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.