FormsLoginPage Class Overview
By default, Active Directory® Federation Services (AD FS) 2.0 presents the FormsSignIn.aspx
page to collect username and password credentials. The code-behind class for the FormsSignIn.aspx
page derives from the FormsLoginPage class. You can customize this page to collect additional credentials and verify them with another authentication server before requesting a token from the STS.
The FormsLoginPage class provides the FormsLoginPage.SignIn method to authenticate to a security token service (STS) with a user name and password. You can catch the AuthenticationFailedException to handle incorrect user name and password errors.
Example: Adding CAPTCHA
The following example shows how to add a mock CAPTCHA control to the FormsSignIn.aspx
page. The control outputs a single image and expects “1234” as the response.
Warning
We recommend that you make backup copies of the FormsSignIn.aspx
and FormsSignIn.aspx.cs
files before you modify them.
The following code defines the SimpleCaptcha
class:
using System;
using System.ComponentModel;
using System.Web.UI;
using System.Web.UI.WebControls;
[DefaultProperty("IsValid")]
[ToolboxData("<{0}:SimpleCaptcha runat=server></{0}:SimpleCaptcha>")]
public class SimpleCaptcha : WebControl, IPostBackDataHandler
{
private string ImageURL = "CAPTCHA.jpg";
private bool validated = false;
public bool IsValid
{
get { return validated; }
}
protected override void RenderContents(HtmlTextWriter writer)
{
//<div>
writer.RenderBeginTag(HtmlTextWriterTag.Div);
//<img src="ImageURL" alt="CAPTCHA" />
writer.AddAttribute(HtmlTextWriterAttribute.Src, ImageURL);
writer.AddAttribute(HtmlTextWriterAttribute.Alt, "CAPTCHA");
writer.RenderBeginTag(HtmlTextWriterTag.Img);
writer.RenderEndTag();
writer.RenderEndTag();
//<div>
writer.RenderBeginTag(HtmlTextWriterTag.Div);
writer.AddAttribute(HtmlTextWriterAttribute.Id, UniqueID);
writer.AddAttribute(HtmlTextWriterAttribute.Name, UniqueID);
writer.AddAttribute(HtmlTextWriterAttribute.Type, "text");
// <input ID="UniqueID" type="text" />
writer.RenderBeginTag(HtmlTextWriterTag.Input);
writer.RenderEndTag();
writer.RenderEndTag();
}
protected override void Render(HtmlTextWriter writer)
{
writer.RenderBeginTag(HtmlTextWriterTag.Div);
RenderContents(writer);
writer.RenderEndTag();
}
#region IPostBackDataHandler Members
public bool LoadPostData(string postDataKey, System.Collections.Specialized.NameValueCollection postCollection)
{
if (Convert.ToString(postCollection[UniqueID]) == "1234")
{
validated = true;
}
else
{
validated = false;
}
return validated;
}
public void RaisePostDataChangedEvent()
{
}
#endregion
}
In the FormsSignIn.aspx
page, add the following table row to contain the CAPTCHA control:
<tr>
<td>
<span class="Label">Type the code: </span>
</td>
<td>
<cc:SimpleCaptcha ID="SimpleCaptcha1" runat="server" />
</td>
<td> </td>
</tr>
Finally, change FormsSignIn.aspx.cs
to check the CAPTCHA control before requesting a token from the STS:
protected void SubmitButton_Click( object sender, EventArgs e )
{
if (SimpleCaptcha1.IsValid)
{
SignIn(UsernameTextBox.Text, PasswordTextBox.Text);
}
else
{
ErrorTextLabel.Visible = true;
ErrorTextLabel.Text = "CAPTCHA is invalid";
}
}
Example: How to Pass a User Name to the Login Form using the Query String
This example shows how to modify the FormsSignIn.aspx.cs
code-behind file so that the user name can be passed to the login form. The user name is passed by adding a username parameter to the query string; for example (assuming that it is not the first parameter passed in the query string), &username=Bob@Contoso.com
.
With this code, when a sign-in request for user name-password authentication with this parameter in the query string arrives, the user name will be pre-populated in the Username box on the page. For example, for the following WS-Federation sign-in request, https://myadfs.contoso.com/adfs/ls/?wa=wsignin1.0&wtrealm=https%3a%2f%2fmyadfs.contoso.com%2fwsfedrp%2f&wctx=rm%3d0%26id%3dFederatedPassiveSignIn1&wct=2011-04-06T06%3a25%3a34Z&wreply=https%3a%2f%2fmyadfs.contoso.com%2fwsfedrp%2fLogin.aspx&wauth=urn:oasis:names:tc:SAML:2.0:ac:classes:Password&username=bob@contoso.com
, the User name box on the page will be pre-populated with “bob@contoso.com”.
To implement this functionality, you can overwrite the FormsSignIn.aspx.cs
file (default location C:\inetpub\adfs\ls) with the following code. You need administrator permissions to do this. The modifications are to the Page_Load
event handler and in the inclusion of some additional using
statements for necessary namespaces.
//-----------------------------------------------------------------------------
//
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
//-----------------------------------------------------------------------------
using System;
using System.Collections.Specialized;
using System.Web;
using Microsoft.IdentityServer.Web;
using Microsoft.IdentityServer.Web.UI;
/// <summary>
/// Attempts to authenticate the user via HTTP Forms Authentication.
/// </summary>
public partial class FormsSignIn : FormsLoginPage
{
protected void Page_Load( object sender, EventArgs e )
{
// Extract the username from the query string and set the text in the TextBox
string url = Context.Request.Url.AbsoluteUri;
NameValueCollection parameters = HttpUtility.ParseQueryString(url);
string userName = parameters["username"];
if (!String.IsNullOrEmpty(userName))
{
UsernameTextBox.Text = userName;
}
}
protected void HandleError( string message )
{
ErrorTextLabel.Visible = true;
ErrorTextLabel.Text = Resources.CommonResources.IncorrectUsernameText;
}
protected void SubmitButton_Click( object sender, EventArgs e )
{
try
{
SignIn( UsernameTextBox.Text, PasswordTextBox.Text );
}
catch ( AuthenticationFailedException ex )
{
HandleError( ex.Message );
}
}
}