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.
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.
We recommend that you make backup copies of the |
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"; } }
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 );
}
}
}