WS-Federation Configuration
Support for WS-Federation is based on .net 4.5 Claims Security. Claims-based identity means an application (Relying Party, RP) uses a separate service (Security Token Service, STS / Identity Provider, IdP) for security.
See Claims Security for basics on ClaimsPrincipal and WS-Federation for architecture, tooling.
- The application trusts the STS, and accepts claim tokens from it.
- It may have no more security than the WIF configuration, and [Authorize(Roles = "Admin")]
- It can also transform the claims itself (e.g. looking up additional roles from a database).
- The STS knows the application, the users allowed for that application and their roles (and additional information).
For WCF/SOAP there's a ws2007FederationHttpBinding (message/issuerMetadata @address)
All you need may be configuration. MSDN
Config Sections
<configuration>
<configSections>
<section name="system.identityModel"
type="System.IdentityModel.Configuration.SystemIdentityModelSection,
System.IdentityModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089" />
<section name="system.identityModel.services"
type="System.IdentityModel.Services.Configuration.SystemIdentityModelServicesSection,
System.IdentityModel.Services, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089" />
</configSections>
system.web - NO authentication
<system.web>
<compilation debug="true" targetFramework="4.5" />
<httpRuntime targetFramework="4.5" requestValidationMode="4.5" />
<!-- no authentication, because the FAM/SAM modules below do it -->
<authentication mode="None"/>
<!--<authentication mode="Forms">
<forms loginUrl="~/Account/Login" />
</authentication>-->
</system.web>
But you still need to protect resources. In MVC just add the [Authorize] filter. In WebForms, add a module and hook it in the web.config:
public class MustBeAuthenticatedModule : IHttpModule
{
public void Init(HttpApplication context)
{
context.PostAuthenticateRequest += context_BeginRequest;
}
void context_BeginRequest(object sender, EventArgs e)
{
var context = HttpContext.Current;
if (context.Request.Path.StartsWith("/bundles", StringComparison.OrdinalIgnoreCase)) return;
if (context.User == null || context.User.Identity == null || !context.User.Identity.IsAuthenticated)
{
context.Response.StatusCode = 401;
context.Response.End();
}
}
Set the
requestValidationMode
attribute to 4.5<httpRuntime targetFramework="4.5" requestValidationMode="4.5" />
system.webServer - the FAM/SAM modules
<system.webServer>
<modules>
<!-- "SAM" - manages the cookie -->
<add name="SessionAuthenticationModule"
type="System.IdentityModel.Services.SessionAuthenticationModule,
System.IdentityModel.Services, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
preCondition="managedHandler" />
<!-- "FAM" - waits for the not authorized 401 and 302 redirects to the STS -->
<add name="WSFederationAuthenticationModule"
type="System.IdentityModel.Services.WSFederationAuthenticationModule,
System.IdentityModel.Services, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
preCondition="managedHandler" />
</modules>
</system.webServer>
system.identityModel - trust the STS, webfarm support
For developing (eg on EmbeddedSTS) you don't need these settings. Note that certificates expire over time!
If you're using a webfarm, the machine key bit is critical.
<system.identityModel>
<identityConfiguration>
<securityTokenHandlers>
<!-- For WebFarms: session tokens are protected by DPAPI which is machine-specific.
To spread across a webfarm, use the Machine Key -->
<remove type="System.IdentityModel.Tokens.SessionSecurityTokenHandler,
System.IdentityModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089" />
<add type="System.IdentityModel.Services.Tokens.MachineKeySessionSecurityTokenHandler,
System.IdentityModel.Services, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089">
<sessionTokenRequirement lifetime="00:30:00" />
</add>
<securityTokenHandlerConfiguration>
<!-- issuerNameRegistry and audienceUris used to be directly under identityConfiguration-->
<!-- Check this application trusts the STS.
There's only one built in issuer name registry.-->
<issuerNameRegistry
type="System.IdentityModel.Tokens.ConfigurationBasedIssuerNameRegistry,
System.IdentityModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<trustedIssuers>
<!-- Checks the token is signed with an X509 certificate with this thumbprint
Gives the claim issuer the name "LocalSTS" -->
<add thumbprint="12E..." name="LocalSTS" />
</trustedIssuers>
</issuerNameRegistry>
<!-- OPTIONAL, probably not needed. Check the signing certificate trust chain and whether it's been revoked -->
<!--<certificateValidation
certificateValidationMode="PeerOrChainTrust"
revocationMode="NoCheck" />-->
<!-- The realm name (URI of Relying Party) is embedded into the token.
To ensure the token is for this RP, use audienceUris
Otherwise client can send token from shared STS for application A to application B (re-purposing attack). -->
<audienceUris>
<clear/>
<!-- same as realm, below -->
<add value="http://ThisApplication/"/>
</audienceUris>
</securityTokenHandlerConfiguration>
</securityTokenHandlers>
</identityConfiguration>
</system.identityModel>
system.identityModel.services - link the STS
Like forms authentication, this points to the STS which could be a login page (401 becomes a 302 to the STS). ADFS can be configured with rules for transformations for each relying party (eg send group membership as claim).
Using embeddedSTS here.
<system.identityModel.services>
<federationConfiguration>
<!-- equivalent to <authentication mode="Forms"><forms loginUrl="~/Account/Login" />
NB: requireHttps="false" for development. In prod, you should use SSL.
issuer = the STS to redirect to e.g. https://xx/issue/wsfed
realm = a URI for this application (known to the STS).
Can also be where the STS redirects back to (otherwise set reply=""). -->
<wsFederation passiveRedirectEnabled="true"
issuer="http://EmbeddedSts"
realm="http://ThisApplication/"
requireHttps="false" />
<cookieHandler requireSsl="false" />
</federationConfiguration>
</system.identityModel.services>