Introduction
This trick will guide how to start customizing default login page of FBA in SharePoint 2013. Target audiences who are familiar with developing custom solution using Visual Studio like farm solution, sandbox solution and so on.
When to Use FBA
Mainly Form Based Authentication is preferred in on premise deployment when organizations/companies want to open their site for partners or vendors. More precisely, your organization is A and A has several partners like B, C, D..... Now A wants to share some sites with the partners/vendors. If A includes their partners in Active Directory, the partners will have the same privilege as regular employees unless some group policies are applied. Also, there might be some security issues. So, for this scenario, FBA has come to play. If you expose sites via FBA to the vendors/partners, then they will have the permission to access those sites only, not in whole networks.
So before exposing your site to the vendors/partners, you might be concerned about your branding!!!!
FBA Configuration
Configuring Form Base Authentication is a long walkthrough. But there are no worries. This post by Sean Earp has made our life easy. He discussed everything regarding FBA configuration step by step. If your configuration is ok, landing page of your site should look like....

Figure-1: Landing page after successful FBA configuration
When FBA authentication will be selected from the above dropdown, the following login page will appear and we are going to customize that page.

Figure-2: Default login page
Customizing Default Login Page
Before diving into the deep, have a look at the source code of default login page. It can be found in the following directory. The file name is default.aspx.
C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\15\TEMPLATE\IDENTITYMODEL\FORMS
<%@ Assembly Name="Microsoft.SharePoint.IdentityModel, Version=15.0.0.0,
Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
<%@ Assembly Name="Microsoft.SharePoint, Version=15.0.0.0, Culture=neutral,
PublicKeyToken=71e9bce111e9429c"%>
<%@ Page Language="C#" Inherits="Microsoft.SharePoint.IdentityModel.Pages.FormsSignInPage"
MasterPageFile="~/_layouts/15/errorv15.master"%>
<%@ Import Namespace="Microsoft.SharePoint.WebControls" %>
<%@ Register Tagprefix="SharePoint" Namespace="Microsoft.SharePoint.WebControls"
Assembly="Microsoft.SharePoint, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
<%@ Register Tagprefix="Utilities" Namespace="Microsoft.SharePoint.Utilities"
Assembly="Microsoft.SharePoint, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
<%@ Import Namespace="Microsoft.SharePoint" %> <%@ Assembly Name="Microsoft.Web.CommandUI,
Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
<asp:Content ContentPlaceHolderId="PlaceHolderPageTitle" runat="server">
<SharePoint:EncodedLiteral runat="server"
EncodeMethod="HtmlEncode" Id="ClaimsFormsPageTitle" />
</asp:Content>
<asp:Content ContentPlaceHolderId="PlaceHolderMain" runat="server">
<div id="SslWarning" style="color:red;display:none">
<SharePoint:EncodedLiteral runat="server"
EncodeMethod="HtmlEncode" Id="ClaimsFormsPageMessage" />
</div>
<script language="javascript" >
if (document.location.protocol != 'https:')
{
var SslWarning = document.getElementById('SslWarning');
SslWarning.style.display = '';
}
</script>
<asp:login id="signInControl" FailureText="<%$Resources:wss,
login_pageFailureText%>" runat="server" width="100%">
<layouttemplate>
<asp:label id="FailureText" class="ms-error" runat="server"/>
<table width="100%">
<tr>
<td nowrap="nowrap"><SharePoint:EncodedLiteral runat="server"
text="<%$Resources:wss,login_pageUserName%>" EncodeMethod='HtmlEncode'/></td>
<td width="100%"><asp:textbox id="UserName" autocomplete="off"
runat="server" class="ms-inputuserfield" width="99%" /></td>
</tr>
<tr>
<td nowrap="nowrap"><SharePoint:EncodedLiteral runat="server"
text="<%$Resources:wss,login_pagePassword%>"
EncodeMethod='HtmlEncode'/></td>
<td width="100%"><asp:textbox id="password"
TextMode="Password"
autocomplete="off" runat="server" class="ms-inputuserfield"
width="99%"/></td>
</tr>
<tr>
<td colspan="2" align="right"><asp:button id="login"
commandname="Login" text="<%$Resources:wss,login_pagetitle%>"
runat="server" /></td>
</tr>
<tr>
<td colspan="2"><asp:checkbox id="RememberMe"
text="<%$SPHtmlEncodedResources:wss,login_pageRememberMe%>"
runat="server" /></td>
</tr>
</table>
</layouttemplate>
</asp:login>
</asp:Content>
To be frank, I got the idea to customize login page from the above page. Now notice something important about the above page:
- Page is inherited from
Microsoft.SharePoint.IdentityModel.Pages.FormsSignInPage
- Master page URL is
~/_layouts/15/errorv15.master
In our custom login page, the above things should be the same. Otherwise custom login page may break. Now, follow the below steps to create custom login page.
- Create a SharePoint 2013 empty project. Name it like
Sp.Login.Custom
.

- Deploy as farm solution:

- Right click on the project and add SharePoint "Layouts" Mapped folder
- Add an application page inside Layouts Mapped folder. Name it like
Login
.

- Now add
Microsoft.SharePoint.IdentityModel
reference at your project. This DLL can be reached from the following directory:
C:\Windows\Microsoft.NET\assembly\GAC_MSIL\Microsoft.SharePoint.IdentityModel\v4.0_15.0.0.0__71e9bce111e9429c
- Inherit code behind page (Login.aspx.cs) from
FormsSignInPage
as we saw earlier that default page is also inherited from FormsSignInPage
.
Have a look at my code behind page:
using System;
using Microsoft.SharePoint;
using Microsoft.SharePoint.WebControls;
using Microsoft.SharePoint.IdentityModel.Pages;
namespace Sp.Login.Custom.Layouts.Sp.Login.Custom
{
public partial class Login : FormsSignInPage
{
protected void Page_Load(object sender, EventArgs e)
{
}
}
}
- Now open the Login.aspx
page and change the MasterPageFile
value by following
~/_layouts/15/errorv15.master
- Now copy all ASP controls from default login page to Login.aspx page and apply your own branding.
Have a look at my code...
<%@ Assembly Name="$SharePoint.Project.AssemblyFullName$" %>
<%@ Import Namespace="Microsoft.SharePoint.ApplicationPages" %>
<%@ Register TagPrefix="SharePoint" Namespace="Microsoft.SharePoint.WebControls"
Assembly="Microsoft.SharePoint, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
<%@ Register TagPrefix="Utilities" Namespace="Microsoft.SharePoint.Utilities"
Assembly="Microsoft.SharePoint, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
<%@ Register TagPrefix="asp" Namespace="System.Web.UI"
Assembly="System.Web.Extensions, Version=4.0.0.0, Culture=neutral,
PublicKeyToken=31bf3856ad364e35" %>
<%@ Import Namespace="Microsoft.SharePoint" %>
<%@ Assembly Name="Microsoft.Web.CommandUI, Version=15.0.0.0, Culture=neutral,
PublicKeyToken=71e9bce111e9429c" %>
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Login.aspx.cs"
Inherits="Sp.Login.Custom.Layouts.Sp.Login.Custom.Login"
MasterPageFile="~/_layouts/15/errorv15.master" %>
<asp:Content ContentPlaceHolderID="PlaceHolderPageTitle" runat="server">
<SharePoint:EncodedLiteral runat="server"
EncodeMethod="HtmlEncode" Id="ClaimsFormsPageTitle" />
</asp:Content>
<asp:Content ContentPlaceHolderID="PlaceHolderMain" runat="server">
<div id="SslWarning" style="color: red; display: none">
<SharePoint:EncodedLiteral runat="server"
EncodeMethod="HtmlEncode" Id="ClaimsFormsPageMessage" />
</div>
<link href="/_layouts/15/Sp.Login.Custom/DesignFiles/Css/customLogin.css" rel="stylesheet" />
<asp:Login ID="signInControl" FailureText="<%$Resources:wss,
login_pageFailureText%>" runat="server" Width="100%">
<LayoutTemplate>
<asp:Label ID="FailureText" class="ms-error" runat="server" />
<div id="customLoginMain">
<table>
<tr id="customLoginHeader">
<td colspan="2" align="center">Please sign in to continue</td>
</tr>
<tr>
<td nowrap="nowrap">
<SharePoint:EncodedLiteral runat="server"
text="User Name" EncodeMethod='HtmlEncode' />
</td>
<td width="100%">
<asp:TextBox ID="UserName" autocomplete="off"
runat="server" class="ms-inputuserfield userNameIcom" Width="94%" />
</td>
</tr>
<tr>
<td nowrap="nowrap">
<SharePoint:EncodedLiteral runat="server"
text="Password" EncodeMethod='HtmlEncode' />
</td>
<td width="100%">
<asp:TextBox ID="password" TextMode="Password"
autocomplete="off" runat="server"
class="ms-inputuserfield passwordIcom" Width="94%" /></td>
</tr>
<tr>
<td colspan="2" align="center">
<asp:CheckBox ID="RememberMe" Text="Remember Me" runat="server" />
</td>
</tr>
<tr>
<td colspan="2" align="center">
<asp:Button ID="login" CommandName="Login"
Text="<%$Resources:wss,login_pagetitle%>" runat="server" />
</td>
</tr>
<tr>
<td colspan="2" align="center"
class="sign-in-bottom">If you are a windows user click
<a href="/_windows/default.aspx?
ReturnUrl=%2f_layouts%2f15%2fAuthenticate.aspx%3fSource%3d%252F&
Source=%2F">here</a> to sign in.
</td>
</tr>
</table>
</div>
</LayoutTemplate>
</asp:Login>
</asp:Content>
The above code will give us the following cool look and feel:

To achieve this, I have added some design files inside Layouts Mapped folder.

Now right click on the project and deploy. The solution will be added in the following directory. Folder name will be the same as project name (Sp.Login.Custom
).
C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\15\TEMPLATE\LAYOUTS
Now change Sign In Page URL from your Web application and browse site.

Note: Don't forget to change the last part after ~/_layouts/
by yourself.
Now, we are all done customizing our default login page. But there is an issue. When you will sign out from Windows authentication, the following error will appear. This error is not applicable when you will sign out from FBA. It will redirect to the custom login page smoothly.

It's not a very serious issue. Nothing will break for it. To omit this error, we have to change our default Signout page.
Run the following PowerShell command to change Signout page and that will cure the above error.
Set-SPCustomLayoutsPage -identity "Signout"
-RelativePath "/_layouts/Sp.Login.Custom/Login.aspx"
-WebApplication "your web application url"
That's all about customizing default login page of FBA. Now start hacking my code given in the attachment.