IdpInitiatedSignOnPage Class Overview
Active Directory® Federation Services (AD FS) 2.0 provides the IdpInitiatedSignOn.aspx page to handle SAML-based IdP-initiated single sign-on (SSO). This functionality enables a user to sign on locally to the AD FS 2.0 server using the SAML protocol or to sign on to Web SSO-compatible relying party (RP) applications. To be Web SSO-compatible, an RP must support the SAML protocol.
The code-behind class for the IdpInitiatedSignOn.aspx page derives from the IdentityProviderInitiatedSignonPage class. This class provides several properties and methods that enable SAML-based IdP-initiated single sign-on, as well as single sign-out and local (IdP only) sign-out.
The RelyingParties property exposes a DataTable object that contains information about the Web SSO-compatible RP applications that are configured with the AD FS 2.0 server. The DataTable contains two columns. The Name column contains the display name of the RP. The Id column contains the identifier for the RP. This is equivalent to the SAML EntityID exposed in its metadata, and can also be observed from the AD FS 2.0 Management Console in the Identity column of the Relying Party Trust configured for the RP.
The IdentityProviderInitiatedSignonPage.SignIn method is called to sign on to an RP. The first parameter is the identity of the RP and the second parameter is an object that contains the set of parameters with which to sign on to the RP.
The LocalLogout method provides sign out from the IP and the SingleLogout method provides sign out from all RP applications to which the user is currently signed in. The IsAuthenticated property can be used to check the current login status of the user.
Performing IdP-Initiated Sign-On using the SignIn method
Invoke the IdentityProviderInitiatedSignonPage.SignIn(String, SignOnRequestParameters) method to sign on to an RP application or to the IdP itself.
The first parameter specifies the identity of the application to sign on to. To sign on to the IdP, set this parameter to null or an empty string. To sign on to an RP, set this parameter to the identifier for that RP. This identifier can be found in the Id column of the DataTable exposed by the RelyingParties property. It is equivalent to the ID specified by the SAML <EntityId> element exposed in the metadata for the RP.
The second parameter is a SignOnRequestParameters object that contains properties that modify the sign on request. By setting the following properties you can specify how AD FS 2.0 processes the request.
The Consent property contains the consent identifier for the request. The consent identifier is a URI that specifies how consent was obtained from the principal for the request. The consent identifiers are defined in section 8.4 of the SAML V2.0 Core specification on the SAML Specifications website.
The ForceAuthentication property contains a Boolean value that specifies whether AD FS 2.0 must authenticate the user regardless of the presence of a session with that user. If this property is true, AD FS 2.0 will force the user to authenticate even if a session with that user already exists.
The IsPassive property contains a Boolean value that specifies whether AD FS 2.0 should authenticate the user silently (without noticeable interaction from the user) using the session cookie if one exists. If it is true, AD FS 2.0 will attempt to authenticate the user from the session cookie.
The RequestedAuthenticationContext property can optionally specify a requested authentication context (represented by the Microsoft.IdentityServer.Protocols.Saml.RequestedAuthenticationContext class). The requested authentication context specifies one or more authentication context classes and a comparison rule that specifies how the classes should be processed to determine the authentication method.
You set properties on a RequestedAuthenticationContext object to set the authentication context classes and comparison rule that AD FS 2.0 should use to determine how to authenticate the user.
The References property contains a collection of URIs that specify SAML authentication context classes. The SAML authentication context classes are defined in section 3.4 of the Authentication Context for the OASIS Security Assertion Markup Language (SAML) V2.0 Specification (https://go.microsoft.com/fwlink/?LinkId=217497). Only a subset of the authentication context classes defined in this specification is supported by AD FS 2.0; for more information, see Supported SAML Authentication Context Classes and Strengths.
The Comparison property contains one of the AuthenticationContextComparisonType values that specifies the comparison rule for how AD FS 2.0 should treat the specified context classes in determining the method of authentication to use for the request. The possible values are Better, Exact, Minimum, and Maximum. For example, if Exact is specified, AD FS 2.0 will try to authenticate the user using a method specified by one of the authentication context classes in the References collection. If Better is specified, it will try to authenticate the user with a method that is stronger than that specified by at least one of the authentication context classes in the References collection. The relative strength of authentication context classes is determined by the order in which they are configured in the Authentication Context Order settings. For more information about the Authentication Context Order settings, see Supported SAML Authentication Context Classes and Strengths.
AD FS 2.0 evaluates the sign-on request parameters according to the following table.
Value of the IsPassive property |
Value of the ForceAuthentication attribute |
How the request is processed. |
---|---|---|
true |
false |
AD FS 2.0 authenticates the user using the session cookie. If a requested authentication context is specified, AD FS 2.0 evaluates it against the last method used to authenticate the user stored in the session cookie. If this method meets the requirements imposed by the requested authentication context, AD FS 2.0 redirects a response back to the requestor with a security token; otherwise, authentication fails. If no requested authentication context is specified, AD FS 2.0redirects a response back to the requestor with a security token. If there is no session already established with the user authentication fails. |
false |
true |
AD FS 2.0 ignores the session cookie and authenticates the user with one of the configured handlers. If no requested authentication context is specified, the first handler configured in web.config is invoked. If a requested authentication context is specified, it is evaluated against the configured handlers. Handlers are evaluated in the order in which they are configured in web.config. The first handler that can authenticate the user with a method that meets the requirements imposed by the requested authentication context is invoked. If none of the handlers can use a method that meets the requirements of the requested authentication context, authentication fails. |
false |
false |
AD FS 2.0 first tries to authenticate the user with the session cookie. If the user cannot be authenticated with the session cookie, either because there is no current session with the user or because the last method of authentication used in the session does not meet the requirements of the requested authentication context, AD FS 2.0 tries to authenticate the user with the configured handlers. |
true |
true |
Authentication fails, or, if the server is deployed in a server farm, the user is redirected to the parent STS if possible (for example, if home realm discovery was done earlier by the user and no further interaction is required now). |
The following example code fragment specifies forced authentication using either TLS client or user name and password.
// include this namespace for RequestedAuthenticationContext class and AuthenticationContextComparisonType enumeration.
using Microsoft.IdentityServer.Protocols.Saml;
...
// Get the identifier for the first configured RP from the DataTable exposed by the RelyingParties property.
string rpIdentity = RelyingParties.Rows[0]["Id"];
SignOnRequestParameters parameters = new SignOnRequestParameters();
// Require the user to authenticate.
parameters.ForceAuthentication = true;
// Add a reqeusted authentication context.
parameters.RequestedAuthenticationContext = new RequestedAuthenticationContext();
// Specify an exact match with one of the authentication context class URIs.
parameters.RequestedAuthenticationContext.Comparison = AuthenticationContextComparisonType.Exact;
// Specify authentication context class URIs. The order is not important.
parameters.RequestedAuthenticationContext.References.Add(new Uri("urn:oasis:names:tc:SAML:2.0:ac:classes:TLSClient"));
parameters.RequestedAuthenticationContext.References.Add(new Uri("urn:oasis:names:tc:SAML:2.0:ac:classes:Password"));
// Invoke the SignIn method to sign on to the RP with the sign-on parameters
SignIn( rpIdentity, parameters );
Assume the following scenario.
The user and the AD FS 2.0 server are members of the same Active Directory domain and the user is signed on to the domain.
A prior session exists between the user and the AD FS 2.0 server.
The AD FS 2.0 server is not a proxy server and it has the default handler configuration (Integrated, Forms, TlsClient, and Basic).
If no sign-on parameters were specified in the call to the SignIn(String, SignOnRequestParameters) method, AD FS 2.0 would authenticate the user using the session cookie. However, with the sign-on parameters specified in the example above, AD FS 2.0 presents the FormSignIn.aspx page to collect user name and password credentials from the user. This is because
The ForceAuthentication property is true (the IsPassive property is false by default), so AD FS 2.0 will ignore the existing session and authenticate the user using the configured handlers.
The RequestedAuthenticationContext.Comparison property is set to Exact, which means that the method used to authenticate the user must be either TLS client or user name and password. AD FS 2.0 evaluates the Integrated handler first (because it is specified first in web.config); however because the Integrated handler cannot perform either user name and password or TLS client authentication, it is not invoked. AD FS 2.0 then evaluates the next configured handler, which is Forms. This handler can perform user name and password authentication, so it is invoked to authenticate the user. Note that even though TLS Client is specified first in the References collection, because Forms is specified before the TLS client handler in web.config, it is the handler invoked by AD FS 2.0.
Example: Add Support for Sign-On Parameters in the Query String
The default behavior provided in the Page_Load event handler in IdpInitiatedSignOn.aspx.cs supports a single parameter in the query string, loginToRp. This parameter specifies the identity of the RP to sign on to. However, this default behavior does not provide for any of the other properties available through the SignOnRequestParameters class to be passed in the query string. The code in this example modifies the Page_Load event handler so that these properties can be specified by using additional query string parameters. With this code, the following additional query string parameters and syntax are supported.
Consent: A SAML consent identifier URI. If this parameter is omitted, the default is urn:oasis:names:tc:SAML:2.0:consent:unspecified.
IsPassive: true | false. If this parameter is omitted, the default is false.
ForcedAuthentication: true | false. If this parameter is omitted, the default is false.
RequestAuthenticationContext: One of the supported SAML authentication context class URIs. If this parameter is omitted, no authentication context class is specified during sign-on.
AuthenticationContextComparison: Better | Exact | Maximum | Minimum. If this parameter is omitted, the default is Exact. The value is case-sensitive.
Note
The query parameters are only valid if the loginToRp parameter is specified (although its value can be an empty string to specify the IdP). The AuthenticationContextComparison parameter is only valid if the RequestAuthenticationContext parameter is specified, and its value is case sensitive. Only one authentication context class URI may be passed in the RequestAuthenticationContext parameter. It does not make sense to set the ForcedAuthentication and the IsPassive parameters both to true.
By using these parameters, sign-on query strings like the following may be specified.
To sign on to the RP with no sign-on page being presented to the user (this will fail if a session does not already exist with the user): https://adfs-server.contoso.com/adfs/ls/IdpInitiatedSignon.aspx?logintorp=urn:samples:serviceprovider:myservice\&ispassive=true
To force authentication by the user even if a session already exists: https://adfs-server.contoso.com/adfs/ls/IdpInitiatedSignon.aspx?logintorp=urn:samples:serviceprovider:myservice\&ForceAuthentication=true
To specify user name-password authentication: https://adfs-server.contoso.com/adfs/ls/IdpInitiatedSignon.aspx?logintorp=urn:samples:serviceprovider:myservice\&RequestedAuthenticationContext=urn:oasis:names:tc:SAML:2.0:ac:classes:Password
To specify an authentication method that is stronger than username-password authentication (as defined by the IdP): https://adfs-server.contoso.com/adfs/ls/IdpInitiatedSignon.aspx?logintorp=urn:samples:serviceprovider:myservice\&RequestedAuthenticationContext=urn:oasis:names:tc:SAML:2.0:ac:classes:Password\&AuthenticationContextComparison=Better
To modify the default IdpInitiatedSignOn.aspx.cs code-behind to provide support for these additional query string parameters, first add a using statement for the Microsoft.IdentityServer.Protocols.Saml namespace to the top of the file.
using Microsoft.IdentityServer.Protocols.Saml;
Next add the following string constants to the code-behind class to define the query string parameters.
const string RpIdentityQueryParameter = "loginToRp";
const string IsPassiveQueryParameter = "IsPassive";
const string ForceAuthenticationQueryParameter = "ForceAuthentication";
const string AuthenticationContextComparisonQueryParameter = "AuthenticationContextComparison";
const string RequestedAuthenticationContextQueryParameter = "RequestedAuthenticationContext";
const string IdpAsRpIdentifier = "self";
Note
RpIdentityQueryParameter and IdpAsRpIdentifier are already defined in the default IdpInitiatedSignOn.aspx.cs file.
Next, replace the Page_Init method with the following code. This code extracts the sign-on parameters from the query string and uses them to create a SignOnRequestParameters object that it then passes to the SignIn method.
protected void Page_Init(object sender, EventArgs e)
{
PopulateConditionalVisibilityControls();
RelyingPartyDropDownList.DataSource = RelyingParties;
RelyingPartyDropDownList.DataBind();
UpdateText();
string rpIdentity = Context.Request.QueryString[RpIdentityQueryParameter];
//
// If the query string specified a certain relying party, sign in to that relying party.
//
if (!String.IsNullOrEmpty(rpIdentity))
{
string decodedIdentity = Server.UrlDecode(rpIdentity);
if (decodedIdentity == IdpAsRpIdentifier)
{
rpIdentity = String.Empty;
}
SignOnRequestParameters parameters = new SignOnRequestParameters();
string isPassive = Context.Request.QueryString[IsPassiveQueryParameter];
if (!String.IsNullOrEmpty(isPassive))
{
parameters.IsPassive = Boolean.Parse(isPassive);
}
string forceAuthentication = Context.Request.QueryString[ForceAuthenticationQueryParameter];
if (!String.IsNullOrEmpty(forceAuthentication))
{
parameters.ForceAuthentication = Boolean.Parse(forceAuthentication);
}
string requestedAuthentication = Context.Request.QueryString[RequestedAuthenticationContextQueryParameter];
if (!String.IsNullOrEmpty(requestedAuthentication))
{
if (parameters.RequestedAuthenticationContext == null)
{
parameters.RequestedAuthenticationContext = new RequestedAuthenticationContext();
}
parameters.RequestedAuthenticationContext.References.Add(new Uri(requestedAuthentication));
string comparison = Context.Request.QueryString[AuthenticationContextComparisonQueryParameter];
if (!String.IsNullOrEmpty(comparison))
{
parameters.RequestedAuthenticationContext.Comparison = (AuthenticationContextComparisonType)Enum.Parse(typeof(AuthenticationContextComparisonType), comparison);
}
}
SignIn(rpIdentity, parameters);
}
}
Example: Support Authentication Context Class and Comparison Rule Selection on the Sign-On Page
The default behavior provided by IdpInitiatedSignOn.aspx and IdpInitiatedSignOn.aspx.cs lets the user select an RP to sign on to from a drop-down list on the sign-in page. An optional drop-down list that lets the user choose the consent identifier when signing on to an RP can be enabled by setting the displayConsent key in the <appSettings> section of the web.config file. By default this drop-down list is disabled. For more information, see Customizing the AD FS 2.0 Sign-In Pages Using Web.config.
There is no provision made for specifying other properties available through the SignOnRequestParameters class in the default behavior. The following example provides additional drop-down lists on the sign-in page that let the user specify an authentication context class and a comparison rule when signing on to an RP.
First modify IdpInitiatedSignOn.aspx to include the new drop down lists. Add the AuthnMethodDropDownList and the ComparisonDropDownList after the ConsentDropDownList (shown for context) on the OtherRpPanel.
<div class="Indent2 GroupNormalMargin"> <asp:Label ID="ConsentLabel" runat="server" Style="vertical-align: middle; text-align: left"
Font-Bold="false" Font-Size="small" Text="<%$ Resources:CommonResources, ConsentDropDownText%>"/>
<asp:DropDownList ID="ConsentDropDownList" DataTextField="Name" DataValueField="Id" runat="server" Enabled="False">
<asp:ListItem Text="<%$ Resources:CommonResources, ConsentUnspecified%>" Value="urn:oasis:names:tc:SAML:2.0:consent:unspecified" Selected="True"/>
<asp:ListItem Text="<%$ Resources:CommonResources, ConsentObtained%>" Value="urn:oasis:names:tc:SAML:2.0:consent:obtained"/>
<asp:ListItem Text="<%$ Resources:CommonResources, ConsentPrior%>" Value="urn:oasis:names:tc:SAML:2.0:consent:prior"/>
<asp:ListItem Text="<%$ Resources:CommonResources, ConsentImplicit%>" Value="urn:oasis:names:tc:SAML:2.0:consent:current-implicit"/>
<asp:ListItem Text="<%$ Resources:CommonResources, ConsentExplicit%>" Value="urn:oasis:names:tc:SAML:2.0:consent:current-explicit"/>
<asp:ListItem Text="<%$ Resources:CommonResources, ConsentUnavailable%>" Value="urn:oasis:names:tc:SAML:2.0:consent:unavailable"/>
<asp:ListItem Text="<%$ Resources:CommonResources, ConsentInapplicable%>" Value="urn:oasis:names:tc:SAML:2.0:consent:inapplicable"/>
</asp:DropDownList>
</div>
<div class="Indent2 GroupNormalMargin"> <asp:Label ID="AuthnMethodLabel" runat="server" Style="vertical-align: middle; text-align: left"
Font-Bold="false" Font-Size="small" Text="Authentication Method:"/>
<asp:DropDownList ID="AuthnMethodDropDownList" runat="server" Enabled="False">
<asp:ListItem Text="Unspecified" Value="" Selected="True"/>
<asp:ListItem Text="Password" Value="urn:oasis:names:tc:SAML:2.0:ac:classes:Password"/>
<asp:ListItem Text="Password Protected Transport" Value="urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport"/>
<asp:ListItem Text="TLSClient" Value="urn:oasis:names:tc:SAML:2.0:ac:classes:TLSClient"/>
<asp:ListItem Text="X509 Certificate" Value="urn:oasis:names:tc:SAML:2.0:ac:classes:X509"/>
<asp:ListItem Text="Windows" Value="urn:federation:authentication:windows"/>
<asp:ListItem Text="Kerberos" Value="urn:oasis:names:tc:SAML:2.0:ac:classes:Kerberos"/>
</asp:DropDownList>
</div>
<div class="Indent2 GroupNormalMargin"> <asp:Label ID="ComparisonLabel" runat="server" Style="vertical-align: middle; text-align: left"
Font-Bold="false" Font-Size="small" Text="Comparison Type:"/>
<asp:DropDownList ID="ComparisonDropDownList" runat="server" Enabled="False">
<asp:ListItem Text="Better" Value="Better"/>
<asp:ListItem Text="Exact" Value="Exact" Selected="True"/>
<asp:ListItem Text="Minimum" Value="Minimum"/>
<asp:ListItem Text="Maximum" Value="Maximum"/>
</asp:DropDownList>
</div>
Next add a using statement for the Microsoft.IdentityServer.Protocols.Saml namespace to the top of IdpInitiatedSignOn.aspx.cs.
using Microsoft.IdentityServer.Protocols.Saml;
Add lines to enable the AuthnMethodDropDownList and the ComparisonDropDownList to the SetRpListState method.
protected void SetRpListState( object sender, EventArgs e )
{
RelyingPartyDropDownList.Enabled = OtherRpRadioButton.Checked;
ConsentDropDownList.Enabled = OtherRpRadioButton.Checked;
//Added for additional sign-on parameters support
AuthnMethodDropDownList.Enabled = OtherRpRadioButton.Checked;
ComparisonDropDownList.Enabled = OtherRpRadioButton.Checked;
}
Modify the SignInButton_Click event handler to create a RequestedAuthenticationContext object, add it to the SignOnRequestParameters, and then add the selected authentication method to the References collection and set the Comparison property according to the selected comparison rule. You can either overwrite the entire handler with the code below, or just add the indicated lines.
protected void SignInButton_Click( object sender, EventArgs e )
{
string rpIdentity = String.Empty;
SignOnRequestParameters parameters = new SignOnRequestParameters();
if ( OtherRpRadioButton.Checked )
{
rpIdentity = RelyingPartyDropDownList.SelectedItem.Value;
//
// The RequestedAuthenticationContext and IsPassive properties
// of the AuthnRequest may be customized by setting properties
// on the SignOnRequestParameters used here.
//
if ( ConsentDropDownList.Visible )
{
parameters.Consent = new Uri( ConsentDropDownList.SelectedItem.Value );
}
// Add these lines to the default handler
//
// If an authentication method has been selected, create a RequestedAuthenticationContext
// and set its values. Note: The value of Unspecified is defined as an empty string in the HTML.
if (!String.IsNullOrEmpty(AuthnMethodDropDownList.SelectedValue))
{
parameters.RequestedAuthenticationContext = new RequestedAuthenticationContext();
// Add the selected authentication method.
parameters.RequestedAuthenticationContext.References.Add(new Uri(AuthnMethodDropDownList.SelectedValue));
// Add the selected comparison rule. Note: Exact is selected in the HTML by default.
parameters.RequestedAuthenticationContext.Comparison =
(AuthenticationContextComparisonType)Enum.Parse(typeof(AuthenticationContextComparisonType), ComparisonDropDownList.SelectedItem.Value);
}
}
SignIn( rpIdentity, parameters );
}
Example: Retrieve Data from the RelyingParties Data Table
The following code shows how to retrieve data about the first compatible RP application.
string rpIdentity = RelyingParties.Rows[0]["Id"];
string rpFriendlyName = RelyingParties.Rows[0]["Name"];