Establishing Trust from a WCF Relying Party Service to an STS using FedUtil
[Starting with the .NET Framework 4.5, Windows Identity Foundation (WIF) has been fully integrated into the .NET Framework. The version of WIF addressed by this topic, WIF 3.5, is deprecated and should only be used when developing against the .NET Framework 3.5 SP1 or the .NET Framework 4. For more information about WIF in the .NET Framework 4.5, also known as WIF 4.5, see the Windows Identity Foundation documentation in the .NET Framework 4.5 Development Guide.]
FedUtil.exe is provided with Windows® Identity Foundation (WIF). It helps you to establish trust from a relying party (RP) application to security token services (STSes). It provides the following capabilities:
Register an existing production STS as a trusted issuer of the RP application.
Help develop a claims-aware application by offering a local STS.
Make an existing application claims-aware.
Update federation metadata for an RP application.
Schedule automatic updates of the federation metadata for an RP application.
The following sections show you how to do each of these tasks using FedUtil. You can also do them manually by making the same changes to your RP application’s web.config file that FedUtil does.
Using FedUtil to establish trust from a WCF RP to an STS is different than establishing trust from an ASP.NET RP to an STS because you must also specify a service endpoint to configure, and you must enable encryption.
Note
Because FedUtil changes the configuration file, it might alter the existing security configuration of the application. Although FedUtil comments out any existing sections that are not needed, rather than deleting them, you should review the configuration file after running FedUtil to ensure that it has not commented out any security configuration upon which the application depends. Also note that FedUtil backs up your existing configuration file.
1. Create a local STS
In this exercise, you create a local STS for use with our claims-aware WCF service. Note that you must run FedUtil from inside Visual Studio to do this. This is useful for testing out your WCF applications with a non-production STS. Later, you’ll learn how you can switch to using a production STS.
Note
You must run Visual Studio in Elevated mode for FedUtil to work correctly.
In Visual Studio, open the File menu and select New, Web Site. Select Claims-Aware WCF Service.
Next, right-click your project in the Solution Explorer and select Add STS Reference:
This runs the FedUtil tool. You’ll see the FedUtil dialog, beginning with the Welcome to Federation Utility tool page:
This page requires you to enter two fields:
Application configuration location: Specify the path to the web.config file for your WCF service. If you run FedUtil from outside Visual Studio, or you run it from the Tools menu in Visual Studio without having a project open, this field is empty. If you run FedUtil by right-clicking on a project in Visual Studio, this field already contains the path to the web.config file for your project. The web.config file must already exist and should be in its default state (that is, as it was generated by Visual Studio). If you run FedUtil more than once on the same web.config file, FedUtil simply overwrites the content that it adds to the web.config file.
Application URI: Specify the URI for your WCF service. Note that this is a .svc file. If you run FedUtil from outside Visual Studio, or you run it from the Tools menu in Visual Studio without having a project open, this field is empty. If you run FedUtil by right-clicking on a project in Visual Studio, this field already contains two URIs for your project: one that uses localhost, and one that uses the fully qualified domain name for your computer, if available. This URI is used as the realm value while configuring the application for claims. It is also used as the first audience URI. If you want to specify additional audience URIs, you must do so manually. If the URI is not secure (that is, does not begin with “https://”), you receive a warning when you click Next.
When you have provided the information, click Next. You’ll see the Application Information page:
Select the service name and endpoint contract name that you want to configure, then click Next. If there are multiple endpoints on a service, and you want to configure claims only for certain endpoints, then select those endpoints.
In the Security Token Service page, select Create a new STS project in the current solution:
Note that if you run FedUtil from outside Visual Studio, or if you run FedUtil from the Tools menu in Visual Studio without having a project open, the Create a new STS project in the current solution option is not available.
Click Next. The Summary page appears:
The Summary page shows the information you entered in the Application Information dialog, the service and endpoint you selected, your choice to create a new STS, the claims requested by the application, and the changes that FedUtil will make to your application’s configuration.
Click Finish.
If you look at your web.config file, you’ll see that FedUtil has modified it:
The
<configuration>/<configSections>
element now contains a reference to the IdentityModel configuration section:<section name="microsoft.identityModel" type="Microsoft.IdentityModel.Configuration.MicrosoftIdentityModelSection, Microsoft.IdentityModel, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
The following application settings are added:
<appSettings> <add key="FederationMetadataLocation" value="C:\inetpub\wwwroot\ClaimsAwareService1_STS\FederationMetadata\2007-06\FederationMetadata.xml" /> </appSettings>
All users have been granted access to the federation metadata:
<location path="FederationMetadata"> <system.web> <authorization> <allow users="*" /> </authorization> </system.web> </location>
The
<system.Web>/<assemblies>
element now contains a reference to the Microsoft.IdentityModel.dll assembly:<add assembly="Microsoft.IdentityModel, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
In the
<system.serviceModel>
element, you can see that the service you selected in FedUtil now has a new endpoint:<services> <service name="Service" behaviorConfiguration="ServiceBehavior"> <endpoint address="https://localhost:54280/ClaimsAwareService1/Service.svc" binding="ws2007FederationHttpBinding" contract="ClaimsAwareService1.IService" bindingConfiguration="ClaimsAwareService1.IService_ws2007FederationHttpBinding" /> <!-- Service Endpoints --> <!--Commented out by FedUtil--> <!--<endpoint address="" binding="wsHttpBinding" contract="ClaimsAwareService1.IService"><identity><dns value="localhost" /></identity></endpoint>--> <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" /> </service> </services>
The
<system.ServiceModel>/<behaviors>/<serviceBehavior>/<behavior>
element now contains a<federatedServiceHostConfiguration />
element that refers to the service you selected in FedUtil. This is what configures the service to be claims-aware:<behaviors> <serviceBehaviors> <behavior name="ClaimsAwareService1.ServiceBehavior" > <!-- Behavior extension to make the service claims aware --> <federatedServiceHostConfiguration name="ClaimsAwareService1.Service" /> <!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment --> <serviceMetadata httpGetEnabled="true"/> <!-- To receive exception details in faults for debugging purposes, set the value below to true. Set to false before deployment to avoid disclosing exception information --> <serviceDebug includeExceptionDetailInFaults="false"/> </behavior> </serviceBehaviors> </behaviors>
The
<system.ServiceModel>/<behaviors>/<serviceBehavior>/<behavior>
element also contains a<serviceCredentials>
element that refers to a test certificate on the local computer.<serviceCredentials> <!--Certificate added by FedUtil. Subject='CN=DefaultApplicationCertificate', Issuer='CN=DefaultApplicationCertificate'.--> <serviceCertificate findValue="48BF03FCEDA703DE09E0F1F0CEFED60BB92B3DD8" storeLocation="LocalMachine" storeName="My" x509FindType="FindByThumbprint" /> </serviceCredentials>
The
<system.serviceModel>
element now contains a<bindings>
element that lists the claims that your WCF service requires:<bindings> <ws2007FederationHttpBinding> <binding name="ClaimsAwareService1.IService_ws2007FederationHttpBinding"> <security mode="Message"> <message> <issuerMetadata address="https://localhost:54908/ClaimsAwareService1_STS/Service.svc/mex" /> <claimTypeRequirements> <!--Following are the claims offered by STS 'https://localhost:54908/ClaimsAwareService1_STS/Service.svc'. Add or uncomment claims that you require by your application and then update the federation metadata of this application.--> <add claimType="https://schemas.xmlsoap.org/ws/2005/05/identity/claims/name" isOptional="true" /> <add claimType="https://schemas.microsoft.com/ws/2008/06/identity/claims/role" isOptional="true" /> </claimTypeRequirements> </message> </security> </binding> </ws2007FederationHttpBinding> </bindings>
Finally, the
<configuration>
element contains a configuration section for Microsoft.IdentityModel, which specifies the local STS as a trusted token provider:<microsoft.identityModel> <service name="ClaimsAwareService1.Service"> <audienceUris> <add value="https://localhost:54904/ClaimsAwareService1/Service.svc" /> </audienceUris> <issuerNameRegistry type="Microsoft.IdentityModel.Tokens.ConfigurationBasedIssuerNameRegistry, Microsoft.IdentityModel, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"> <trustedIssuers> <add thumbprint="0E2A9EB75F1AFC321790407FA4B130E0E4E223E2" name="CN=STSTestCert" /> </trustedIssuers> </issuerNameRegistry> </service> </microsoft.identityModel>
An
<issuerNameRegistry>/<trustedIssuers>
element is added to specify the certificate that the STS uses to sign the tokens that it issues. The STS will use a default certificate to sign the tokens it generates. This cert is named “STSTestCert” and it is added to your certificate store automatically for use by the STS. The certificate file is present in the STS project. The password for the file is “STSTest”. This should not be used in a production exercise. You can replace the default certificate with any other certificate. Please ensure that the user for your IIS process has access to the private key for any such certificate. You might also choose to create a type derived from IssuerNameRegistry to perform a programmatic validation of certificates of the trusted issuers.Security Note If you run FedUtil again to establish trust from your RP application to a different STS, FedUtil will add the certificate for the new STS, but will not remove the certificate for the old STS. If you want your RP application to no longer trust the old STS, you must edit the web.config
file and remove the certificate for the old STS.
Also, if you look at the Solution Explorer, you’ll see that FedUtil has added a new project to your solution. This project is the local STS. Note also that a federation metadata document has been added to both the relying party application and the local STS.
2. Register an existing production STS
In this exercise, you’ll use a production STS, with encryption, for our claims-aware WCF service. Note that, unlike a ASP.NET relying party application, a WCF service must use encryption.
In Visual Studio, open the File menu and select New, Web Site. Select WCF Service. Right-click your project in the Solution Explorer and select Add STS Reference. This runs the FedUtil tool. In the Welcome to the Federation Utility Tool page, make sure the Application configuration location and Application URI are correct and click Next.
In the Application Information page, select the service name and endpoint contract name that you want to configure and click Next.
In the Security Token Service page, select Use an Existing STS:
You must specify the location of the federation metadata endpoint for the production STS. You can click the Test location button to make sure the location is correct. This button makes a request to the specified endpoint and displays the response in your default Web browser. When you have specified the STS, click Next.
Note that if you specify an STS that has a certificate that is not trusted by the local certificate store, you’ll see the following warning message: “ID1025: A certificate chain processed, but terminated in a root certificate which is not trusted by the trust provider.” If you want to continue anyway, click Yes. If not, click No and select a different STS.
Another Application Information page appears, this time asking you to select No encryption or Enable encryption:
Note
You must enable encryption when you run FedUtil on a WCF service. Otherwise, you’ll receive an error message.
Select Enable encryption. Now you must select the certificate that the service uses to encrypt its communications with the STS.
Use default certificate means that if the local STS has already created a certificate for encrypting tokens, then this same certificate is used again for decryption. When registering a production STS, this isn’t very common, because the production STS will probably not use the same certificate that you used for the local STS. You should not use this option in a production solution. If you have a service certificate already, you might want to use the same certificate.
If you select an existing certificate, FedUtil displays the certificate(s) in the local certificate store. The certificate must have a private key and a subject name.
For this exercise, you can either use the default certificate or select an existing one. When you are done, click Next.
The Offered Claims page appears:
It contains a list of claims that are offered by the STS. FedUtil gets this list by downloading the metadata from the STS and parsing it. By default, FedUtil configures your claims-aware WCF service to require only the name and role claims. To see how to configure your service to require additional claims, see 3. Update Federation Metadata. If there are claims required by your service but not offered by the STS, you should contact the STS administrator and make the necessary agreements.
Click Next. The Summary page appears:
The Summary page shows the information you entered in the Application Information dialog, the service and endpoint you selected, your choice to use an existing STS, whether you chose to enable encryption, the claims requested by the application, and the changes that FedUtil will make to your application’s configuration.
If you selected a test certificate, the application information includes this note: “Selected application certificate: A new certificate with subject name 'CN=DefaultApplicationCertificate' will be added to the personal and trusted people certificate store, if not already present.” If you selected an existing certificate, you’ll see the thumbprint for that certificate.
The Summary page also includes a checkbox labeled “Schedule daily metadata updates for this application”. If you check this checkbox, FedUtil schedules a task to update the application’s metadata at midnight every night. For more information, see How to: Perform Trust Management using FedUtil.
Click Finish.
If you look at your web.config file, you’ll see that FedUtil has modified it:
The
<configuration>/<configSections>
element now contains a reference to the IdentityModel configuration section:<section name="microsoft.identityModel" type="Microsoft.IdentityModel.Configuration.MicrosoftIdentityModelSection, Microsoft.IdentityModel, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
The following application settings are added. “Specified STS” refers to the STS that you specified in FedUtil.
<appSettings> <add key="FederationMetadataLocation" value="<specified STS>" /> </appSettings>
All users have been granted access to the federation metadata:
<location path="FederationMetadata"> <system.web> <authorization> <allow users="*" /> </authorization> </system.web> </location>
The
<system.Web>/<assemblies>
element now contains a reference to the Microsoft.IdentityModel.dll assembly:<add assembly="Microsoft.IdentityModel, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
In the
<system.serviceModel>
element, you can see that the service you selected in FedUtil now has a new endpoint that uses the WS-Federation HTTP binding:<services> <service name="Service" behaviorConfiguration="ServiceBehavior"> <endpoint address="https://localhost:54280/ClaimsAwareService2/Service.svc" binding="ws2007FederationHttpBinding" contract="ClaimsAwareService2.IService" bindingConfiguration="ClaimsAwareService2.IService_ws2007FederationHttpBinding" /> <!-- Service Endpoints --> <!--Commented out by FedUtil--> <!--<endpoint address="" binding="wsHttpBinding" contract="ClaimsAwareService2.IService"><identity><dns value="localhost" /></identity></endpoint>--> <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" /> </service> </services>
The
<system.ServiceModel>/<behaviors>/<serviceBehavior>/<behavior>
element now contains a<federatedServiceHostConfiguration />
element that refers to the service you selected in FedUtil. This is what configures the service to be claims-aware:<behaviors> <serviceBehaviors> <behavior name="ClaimsAwareService2.ServiceBehavior" > <!-- Behavior extension to make the service claims aware --> <federatedServiceHostConfiguration name="ClaimsAwareService2.Service" /> <!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment --> <serviceMetadata httpGetEnabled="true"/> <!-- To receive exception details in faults for debugging purposes, set the value below to true. Set to false before deployment to avoid disclosing exception information --> <serviceDebug includeExceptionDetailInFaults="false"/> </behavior> </serviceBehaviors> </behaviors>
The
<system.ServiceModel>/<behaviors>/<serviceBehavior>/<behavior>
element also contains a<serviceCredentials>
element that refers to a test certificate on the local computer. This is the certificate you specified in FedUtil.<serviceCredentials> <!--Certificate added by FedUtil. Subject='CN=DefaultApplicationCertificate', Issuer='CN=DefaultApplicationCertificate'.--> <serviceCertificate findValue="48BF03FCEDA703DE09E0F1F0CEFED60BB92B3DD8" storeLocation="LocalMachine" storeName="My" x509FindType="FindByThumbprint" /> </serviceCredentials>
The
<system.serviceModel>
element now contains a<bindings>
element that lists the claims that your WCF service requires. “Specified STS” refers to the STS that you specified in FedUtil.<bindings> <ws2007FederationHttpBinding> <binding name="ClaimsAwareService2.IService_ws2007FederationHttpBinding"> <security mode="Message"> <message> <issuerMetadata address="https://<specified STS>/Trust/Mex" /> <claimTypeRequirements> <!--Following are the claims offered by STS '<specified STS>'. Add or uncomment claims that you require by your application and then update the federation metadata of this application.--> <add claimType="https://schemas.xmlsoap.org/ws/2005/05/identity/claims/name" isOptional="true" /> <add claimType="https://schemas.microsoft.com/ws/2008/06/identity/claims/role" isOptional="true" /> <!--<add claimType="https://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress" isOptional="true" />--> <!--<add claimType="https://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn" isOptional="true" />--> <!--<add claimType="https://schemas.xmlsoap.org/claims/CommonName" isOptional="true" />--> <!--<add claimType="https://schemas.xmlsoap.org/claims/EmailAddress" isOptional="true" />--> <!--<add claimType="https://schemas.xmlsoap.org/claims/Group" isOptional="true" />--> <!--<add claimType="https://schemas.xmlsoap.org/claims/UPN" isOptional="true" />--> <!--<add claimType="https://schemas.xmlsoap.org/ws/2005/05/identity/claims/privatepersonalidentifier" isOptional="true" />--> <!--<add claimType="https://schemas.xmlsoap.org/ws/2005/05/identity/claims/webpage" isOptional="true" />--> <!--<add claimType="https://schemas.xmlsoap.org/ws/2005/05/identity/claims/title" isOptional="true" />--> <!--<add claimType="https://schemas.xmlsoap.org/ws/2005/05/identity/claims/picture" isOptional="true" />--> <!--<add claimType="https://schemas.xmlsoap.org/ws/2005/05/identity/claims/manager" isOptional="true" />--> <!--<add claimType="https://schemas.xmlsoap.org/ws/2005/05/identity/claims/department" isOptional="true" />--> </claimTypeRequirements> </message> </security> </binding> </ws2007FederationHttpBinding> </bindings>
Note that all claims except the name and role claims are commented out. To see how to configure your service to require additional claims, see 3. Update Federation Metadata.
Finally, the
<configuration>
element contains a configuration section for Microsoft.IdentityModel, which specifies the production STS as a trusted token provider:<microsoft.identityModel> <service name="ClaimsAwareService2.Service"> <audienceUris> <add value="https://localhost:54966/ClaimsAwareService2/Service.svc" /> </audienceUris> <issuerNameRegistry type="Microsoft.IdentityModel.Tokens.ConfigurationBasedIssuerNameRegistry, Microsoft.IdentityModel, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"> <trustedIssuers> <add thumbprint="5C8885A8E3D29D6BF6C9365E00B1BEA5EB284D1E" name="CN=<specified STS>, OU=US-Federated Identity, O=Microsoft Corporation, L=Redmond, S=Washington, C=US" /> </trustedIssuers> </issuerNameRegistry> </service> </microsoft.identityModel>
Note that you can run FedUtil repeatedly to switch from a local STS to a production STS and back again. Each time you run FedUtil, it simply overwrites the configuration it created previously. However, you cannot use FedUtil to switch from using a local or production STS to using no STS.
Also note that if you run FedUtil and create a local STS, then switch to a production STS, the <issuerNameRegistry>
element in your configuration file will contain two trusted issuers. One is the local STS and the other is the production STS. Once you’re ready to deploy your application, you should remove the local STS from the issuer name registry.
3. Update Federation Metadata
By default, when you use FedUtil and specify a production STS, FedUtil configures your application to require only the name and role claims. You can see this by looking at the <claimTypeRequirements>
element in your applications web.config file:
<bindings>
<ws2007FederationHttpBinding>
<binding name="ClaimsAwareService2.IService_ws2007FederationHttpBinding">
<security mode="Message">
<message>
<issuerMetadata address="https://<specified STS>/Trust/Mex" />
<claimTypeRequirements>
<!--Following are the claims offered by STS 'http://<specified STS>/Trust'. Add or uncomment claims that you require by your application and then update the federation metadata of this application.-->
<add claimType="https://schemas.xmlsoap.org/ws/2005/05/identity/claims/name" isOptional="true" />
<add claimType="https://schemas.microsoft.com/ws/2008/06/identity/claims/role" isOptional="true" />
<!--<add claimType="https://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress" isOptional="true" />-->
<!--<add claimType="https://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn" isOptional="true" />-->
<!--<add claimType="https://schemas.xmlsoap.org/claims/CommonName" isOptional="true" />-->
<!--<add claimType="https://schemas.xmlsoap.org/claims/EmailAddress" isOptional="true" />-->
<!--<add claimType="https://schemas.xmlsoap.org/claims/Group" isOptional="true" />-->
<!--<add claimType="https://schemas.xmlsoap.org/claims/UPN" isOptional="true" />-->
<!--<add claimType="https://schemas.xmlsoap.org/ws/2005/05/identity/claims/privatepersonalidentifier" isOptional="true" />-->
<!--<add claimType="https://schemas.xmlsoap.org/ws/2005/05/identity/claims/webpage" isOptional="true" />-->
<!--<add claimType="https://schemas.xmlsoap.org/ws/2005/05/identity/claims/title" isOptional="true" />-->
<!--<add claimType="https://schemas.xmlsoap.org/ws/2005/05/identity/claims/picture" isOptional="true" />-->
<!--<add claimType="https://schemas.xmlsoap.org/ws/2005/05/identity/claims/manager" isOptional="true" />-->
<!--<add claimType="https://schemas.xmlsoap.org/ws/2005/05/identity/claims/department" isOptional="true" />-->
</claimTypeRequirements>
</message>
</security>
</binding>
</ws2007FederationHttpBinding>
</bindings>
For example, in the previous code snippet, the emailaddress claim is commented out. To configure your application to require additional claims, uncomment that claims that you want. Then, in Solution Explorer, right-click your application project and select Update federation metadata:
FedUtil updates your application’s federation metadata to reflect your changes to the list of required claims. Afterward, open your application’s FederationMetadata.xml file and look at the updated list of required claims. It should now include any additional claims that you uncommented in your application’s web.config file. Note that FedUtil also makes a backup copy of your application’s web.config file.
<fed:ClaimTypesRequested>
<auth:ClaimType Uri="https://schemas.xmlsoap.org/ws/2005/05/identity/claims/name" Optional="True" xmlns:auth="http://docs.oasis-open.org/wsfed/authorization/200706" />
<auth:ClaimType Uri="https://schemas.microsoft.com/ws/2008/06/identity/claims/role" Optional="True" xmlns:auth="http://docs.oasis-open.org/wsfed/authorization/200706" />
...
</fed:ClaimTypesRequested>
You can also add custom claim types to your application’s web.config file. You must then ask your STS administrator to update the STS policy for your application so that it issues the new claim types.