What do the following three questions in the AD FS 2.0 forums have in common?
· Reducing default steps in Sign-In process and changing default look & feel in Sign-In process in Geneva server
· How to authenticate a non-Active Directory user in "Geneva" Server
· Posting a WSTrustClient token to Geneva Server
They’re three customer scenarios that are made easier with the release candidate!
During the lead up to the release candidate, we did some housekeeping in the sign-in webpages. For example, a developer looking at customizing the home realm discovery page in Beta 2 would have seen the following 450 lines of code:
Yikes! In the release candidate, that same file contains less logic and is easier for a new developer to dive into and start changing.
The first forum question was about look and feel. In the release candidate, the look and feel of the pages is controlled by ASP.NET Master Pages and options in the web.config file. This should be standard fare for most ASP.NET developers, so I’ll let MSDN do the explaining:
· Customizing the Sign-In Pages Using Web.config
· ASP.NET Master Pages Overview
The second and third forum question each describe variations on a common scenario: account stores that are either not Active Directory, or that are in domains that do not trust each other. Your users shouldn’t need to know the difference. In the example below, I’ve created an installation of AD FS that authenticates users in both its domain as well as Microsoft’s http://www.federatedidentity.net/ sandbox STS, but you can imagine substituting in the right values for your own STSes where needed.
Step 1: Add a claims provider trust for the STS in the other domain. In this case, the relevant values were:
· Claims provider identifier: http://ipsts.federatedidentity.net
· Token-signing certificate: the SSL certificate from https://ipsts.federatedidentity.net/
Step 2: Customize the logic in the FormsSignInPage.aspx.cs file. I added the following function:
const string OtherSTSAddress = "https://ipsts.federatedidentity.net/SecurityTokenService/InteropSts.svc/Sts";
const string YourSTSAddress = "https://your-sts/adfs/ls/";
private void SignInWithTokenFromOtherSTS( string username, string password )
// This function will use WIF's WSTrustChannel class to
// request a token from the other STS.
// If successful, it will attempt to sign the user in to
// the local STS using that token.
EndpointAddress endpointAddress = new EndpointAddress( OtherSTSAddress );
UserNameWSTrustBinding binding = new UserNameWSTrustBinding( SecurityMode.TransportWithMessageCredential );
// Configure the request with the appropriate credentials.
WSTrustChannelFactory factory = new WSTrustChannelFactory( binding, endpointAddress );
factory.Credentials.UserName.UserName = username;
factory.Credentials.UserName.Password = password;
factory.TrustVersion = System.ServiceModel.Security.TrustVersion.WSTrustFeb2005;
WSTrustChannel channel = (WSTrustChannel)factory.CreateChannel();
RequestSecurityToken rst = new RequestSecurityToken(
rst.AppliesTo = new EndpointAddress( YourSTSAddress );
// Make the request and sign in.
SecurityToken token = channel.Issue( rst );
SignIn( token );
And I changed the button click handler to look like the following:
protected void SubmitButton_Click( object sender, EventArgs e )
SignInWithTokenFromOtherSTS( UsernameTextBox.Text, PasswordTextBox.Text );
catch ( Exception ex )
// Fall back to signing in locally with the given username and password.
SignIn( UsernameTextBox.Text, PasswordTextBox.Text );
And voilà! Of course, this code isn’t quite ready for production – you might want to only contact the other STS if you see that the username is in a certain domain, you may want additional logging and auditing, and so on – but hopefully it gives you a feel of how you can easily customize the sign-in pages.
For all the details and the API reference, be sure to check out the MSDN documentation for AD FS 2.0.
SDE on the AD FS Protocols team