Windows® Identity Foundation (WIF) includes support for federated authentication in ASP.NET applications through the WS-Federated Authentication Module (WS-FAM). This topic is written to help you understand how federated authentication works and how to use it.
Overview of Federated Authentication
Federated authentication allows a Security Token Service (STS) in one trust domain to provide authentication information to an STS in another trust domain when there is a trust relationship between the two domains. An example of this is shown in the following illustration.
- A client in the Fabrikam trust domain sends a request to a
Relying Party (RP) application in the Contoso trust domain.
- The RP redirects the client to an STS in the Contoso trust
domain. This STS has no knowledge of the client.
- The Contoso STS redirects the client to an STS in the Fabrikam
trust domain, with which the Contoso trust domain has a trust
relationship.
- The Fabrikam STS verifies the client’s identity and issues a
security token to the Contoso STS.
- The Contoso STS uses the Fabrikam token to create its own token
that can be used by the RP and sends it to the RP.
- The RP extracts the client’s claims from the security token and
makes an authorization decision.
Using the Federated Authentication Module with ASP.NET
WSFederationAuthenticationModule (WS-FAM) is an HTTP module that lets you add federated authentication to a ASP.NET application. Federated authentication lets authentication logic be handled by the STS and lets you focus on writing business logic.
You configure the WS-FAM to specify the STS to which non-authenticated requests should be redirected. WIF lets you authenticate a user in two ways:
- Using the FederatedPassiveSignIn control. When an
unauthenticated user tries to access a protected resource, they are
redirected to a logon page in the application. This logon page has
the FederatedPassiveSignIn control embedded
in it and the control is configured with issuer (STS) information.
If you do not require application-wide protection and instead
require a logon page in the application and you expect the users to
click the control (for example, in a financial institution online
site with a login page), then this is the right approach.
- Passive redirect: When an unauthenticated user tries to access
a protected resource, and you want to simply redirect them to an
STS without requiring a login page, then this is the right
approach. The STS verifies the user’s identity, and issues a
security token that contains the appropriate claims for that user.
This option requires the WS-FAM to be added in the HTTP Modules
pipeline. For more information, see Establishing Trust from
an ASP.NET Relying Party Application to an STS using
FedUtil.
In passive redirect, all communication is performed through response/redirect from the client (typically a browser). The WS-FAM supports passive redirect in two ways:
- You can add the WS-FAM to your application’s HTTP pipeline,
where it watches for unauthenticated user requests and redirects
users to the STS you specify.
- You can instantiate the WS-FAM and use it to validate requests.
This is what the FederatedPassiveSignIn control does.
The WS-FAM also raises several events that let you customize its functionality in an ASP.NET application.
How the WS-FAM Works
The WS-FAM is implemented in the WSFederationAuthenticationModule class. Typically, you add the WS-FAM to the HTTP pipeline of your ASP.NET RP application. When an unauthenticated user tries to access a protected resource, the RP returns a “401 authorization denied” HTTP response. The WS-FAM intercepts this response instead of allowing the client to receive it, then it redirects the user to the specified STS. The STS issues a security token, which the WS-FAM again intercepts. The WS-FAM uses the token to create an instance of IClaimsPrincipal for the authenticated user, which enables regular .NET Framework authorization mechanisms to function.
Because HTTP is stateless, we need a way to avoid repeating this whole process every time that the user tries to access another protected resource. This is where the SessionAuthenticationModule comes in. When the STS issues a security token for the user, SessionAuthenticationModule also creates a session security token for the user and puts it in a cookie. On subsequent requests, the SessionAuthenticationModule intercepts this cookie and uses it to reconstruct the user’s IClaimsPrincipal.
If you want to make your RP application claims-aware,
but you do not have an STS (for example, the RP uses Forms
authentication or Windows integrated authentication), you can use
the ClaimsPrincipalHttpModule. This module sits
in your application’s HTTP pipeline and intercepts authentication
information. It generates a IClaimsPrincipal for each user based on that
user’s username, group memberships, and other authentication
information. ClaimsPrincipalHttpModule must be inserted
at the end of the <httpModules>
pipeline, which
is the first element in the <modules>
section of
<system.webServer>
on IIS 7.
The following diagram shows the overall flow of information when the user is redirected to a login page to establish credentials and then redirected to the destination page once authenticated:
The following diagram shows more detail on what happens when the user has authenticated to the STS and their security tokens are posted to the login page:
Finally, the following diagram shows more detail on what happens when the user’s security tokens have been serialized into cookies and are intercepted by the SessionAuthenticationModule:
The following diagram shows the overall flow of information in the passive redirect case. The request is automatically redirected via the STS to establish credentials without a login page:
The following diagram shows more detail on what happens when the user has authenticated to the STS and their security tokens are processed by the WSFederationAuthenticationModule:
Events
WSFederationAuthenticationModule,
SessionAuthenticationModule, and their
parent, HttpModuleBase, raise events at various
stages of processing of an HTTP request. You handle these events in
the global.asax
file of your ASP.NET application.
- HttpModuleBase raises the
Init
event when the module is initialized.
- WSFederationAuthenticationModule raises
the ServiceConfigurationCreated event when it loads the
service configuration. It only raises this event once, not
per-module. This event provides the ServiceConfiguration, which you can use
to modify the service configuration. You should catch this event in
the Application_Start method:
Copy Code void Application_Start { FA.ServiceConfigurationCreated += new ServiceConfigurationCreatedEventHandler( <your event handler signature>); }
If you want the WSFederationAuthenticationModule or SessionAuthenticationModule to have their own configurations, you must derive your own class from WSFederationAuthenticationModule or SessionAuthenticationModule, create a new ServiceConfiguration, and reassign the ServiceConfiguration reference in your derived class to the ServiceConfiguration that you have created.
- The WS-FAM raises
SecurityTokenReceived when it intercepts a security token
that has been issued by the STS.
- The WS-FAM raises
SecurityTokenValidated after it has validated the token.
- The SessionAuthenticationModule raises
SessionSecurityTokenCreated when it creates a session
security token for the user.
- The SessionAuthenticationModule raises
SessionSecurityTokenReceived when it intercepts subsequent
requests with the cookie that contains the session security
token.
- Before the WS-FAM redirects the user to the
issuer, it raises the RedirectingToIdentityProvider event
with the ‘federation request’ as a parameter. You may choose to
modify the request before sending this out to the issuer.
- The WS-FAM raises SignedIn when the
cookie is successfully written and the user is signed in.
- The WS-FAM raises SigningOut one time
per session as the session is being closed down for each user. It
is not raised if the session is closed down on the client-side (for
example, by deleting the session cookie). In an SSO environment,
the IP-STS can request each RP to sign out, too. This will also
raise this event, with IsIPInitiated set to true.
Note: |
---|
You should not call Thread.CurrentPrincipal during
any event raised by WSFederationAuthenticationModule and
SessionAuthenticationModule.
Thread.CurrentPrincipal is set after the
authentication process, while events are raised during the
authentication process. |
Scenarios Supported
The WS-FAM supports the following scenarios:
- Accessing claims in an ASP.NET RP application
that uses WS-Federation for authentication. If the RP application
uses Forms authentication or Windows Integrated authentication,
only ClaimsPrincipalHttpModule is needed. For
more information, see How to: Access Claims in
an ASP.NET Page.
- Managed card logon to an ASP.NET application.
This only requires the SessionAuthenticationModule.
Configuration of Federated Authentication
The following configuration snippet describes the
attributes that can be configured in the
<federatedAuthentication>
configuration
element:
Copy Code | |
---|---|
<federatedAuthentication> <!-- <wsFederattion> defines parameter settings for WS-FEDERATION protocol STS. This affects the settings for the WSFederationAuthenticationModule. ATTRIBUTES passiveRedirectEnabled - Boolean - default false Controls whether the module is enabled to automatically redirect unauthorized requests to an STS. issuer - String - default "" The URI of the token issuer. realm - String - default "" The URI of requesting realm. freshness - Float - default "" The value of the required freshness. reply - String - default "" The URI of address to reply to. request - String - default "" The URI of WS-FEDERATION request. requestPtr - String - default "" The URI of WS-FEDERATION request pointer. resource - String - default "" The URI of WS-FEDERATION resource value. authenticationType – String – default “” The wauth parameter that the application want to specify to STS requireHttps – Boolean – default false The Boolean flag to indicate whether to require HTTPs or not for the issuer url signInMode – String – default “Session” Either this is session based cookie or single use cookie homeRealm – String – default “” Enter a homeRealm value signInQueryString – String – default “” signOutQueryString – String – default “” signOutReply – String – default “” --> <wsFederation passiveRedirectEnabled="true|false" issuer="http://sts.com/request.aspx" realm="http://sts.com/request.aspx" freshness="10" reply="" request="" requestPtr="" resource="" /> <!-- <cookieHandler> controls the CookieHandler, which is responsible for reading and writing raw cookies at the HTTP protocol level. SessionAuthenticationModule uses the cookieHandler to read and write cookies. MODES Default (default) The same as Chunked. Chunked Uses an instance of the ChunkedCookieHandler class. This cookie handler ensures that individual cookies do not exceed a set maximum size. It accomplishes that by potentially "chunking" one logical cookie into a number of on-the-wire cookies. Custom Uses an instance of a custom CookieHandler-derived class, referenced by the <customCookieHandler> element. ATTRIBUTES domain - String - default "" The domain value for any cookies written. hideFromScript - Boolean - default true Controls whether the "HttpOnly" flag is emitted for any cookies written. Certain web browsers honor this flag by keeping client-side script from accessing the cookie value. name - String - default "FedAuth" Controls the base name for any cookies written. path - String - default is HttpRuntime.AppDomainAppVirtualPath Controls the path value for any cookies written. requireSsl - Boolean - default false Controls whether the "Secure" flag is emitted for any cookies written. If this value is set, the sign-in session cookies will only be available over HTTPS. --> <cookieHandler mode="Default|Chunked|Custom" domain=".example.com" hideFromScript="true" name="FedAuth" path="/" requireSsl="false"> <!-- <chunkedCookieHandler> may only be present if the cookieHandler/@mode is Default or Chunked. It controls the ChunkedCookieHandler. ATTRIBUTES chunkSize - Int32 - default 2000 The maximum size in characters of the HTTP cookie data for any one HTTP cookie. Care must be taken when adjusting the chunk size. Web browsers have different limits on the size of cookies and number per domain. The original Netscape specification stipulated these limits: 300 cookies total, 4096 bytes per cookie header (including metadata, not just the cookie value), and 20 cookies per domain. --> <chunkedCookieHandler chunkSize="2000" /> <!-- <customCookieHandler> may only be present if the cookieManager/@mode is Custom. It references a custom type which must be derived from CookieHandler. See the comments before the <configuration> element on custom type references. --> <customCookieHandler type="MyTypes.MyCookieHandler, MyTypes" /> </cookieHandler> </federatedAuthentication> |
Note: |
---|
If wauth is set by the application, then the application should also check it for its strength. WIF does not perform this check. |
Note: |
---|
If requiredClaims is set in the application’s configuration, the application needs to verify these claims in the ClaimsAuthenticationManager. WIF does not perform this check. |