Monday 5 May 2014

Generating Federation Metadata for ADFS WCF Services with FedUtil

Fedutil is probably one of the worst tools ever produced by Microsoft, it is used to generate Federation Metadata for claim authenticated Web services.

I say it's one of the worst tools because it fails rather a lot, which is fine, but sometimes it's tricky to work out why it's failing.

At any rate, Fedutil comes with the WIF SDK and MUST be run with elevated permissions.

The first thing to note is that the certificate in the behaviours section of your web.config, see below, must be installed, with private key in the machine you are running Fedutil from.

Another interesting tidbit is that the Endpoint address needs to be populated and finally, if you are encrypting your appSettings section decrypt it first.

If you have done all the above then it's just a simple case of running:
 fedutil /u <pathtoconfigfile>
This will generate your federation metadata file.

Sample configuration file below
<?xml version="1.0"?>
<configuration>
  <configSections>
    <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net, Version=1.2.10.0, Culture=neutral, PublicKeyToken=1b44e1d426115821"/>
    <section name="microsoft.identityModel" type="Microsoft.IdentityModel.Configuration.MicrosoftIdentityModelSection, Microsoft.IdentityModel, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
  </configSections>
  <log4net>
    <appender name="RollingLogFileAppender" type="log4net.Appender.RollingFileAppender">
      <param name="File" value="WorkingHours.log"/>
      <param name="AppendToFile" value="true"/>
      <param name="MaxSizeRollBackups" value="5"/>
      <param name="MaximumFileSize" value="5MB"/>
      <param name="ImmediateFlush" value="true"/>
      <param name="RollingStyle" value="Size"/>
      <param name="StaticLogFileName" value="true"/>
      <layout type="log4net.Layout.PatternLayout">
        <param name="ConversionPattern" value="%d{dd/MM HH:mm:ss:fff}|%-5p|%m%n"/>
      </layout>
    </appender>
    <appender name="TraceAppender" type="log4net.Appender.TraceAppender">
      <layout type="log4net.Layout.PatternLayout">
        <conversionPattern value="%date [%thread] %-5level %logger [%property{NDC}] - %message%newline"/>
        <conversionPattern value="%date %-5level - %message%newline"/>
      </layout>
    </appender>
    <root>
      <!-- The "priority" element specifies the level of information reported that will be logged -->
      <priority value="ALL"/>
      <appender-ref ref="RollingLogFileAppender"/>
      <appender-ref ref="TraceAppender"/>
    </root>
  </log4net>
  <appSettings>
    <add key="ProvisionCacheTimeMilliseconds" value="86400000"/>
    <add key="FederationMetadataLocation" value="https://adfs.dev.local/FederationMetadata/2007-06/FederationMetadata.xml"/>
    <add key="Organisation" value="c4wsandpit"/>
  </appSettings>
  <location path="FederationMetadata">
    <system.web>
      <authorization>
        <allow users="*"/>
      </authorization>
    </system.web>
  </location>
  <system.web>
    <compilation debug="true" targetFramework="4.0">
      <assemblies>
        <add assembly="Microsoft.IdentityModel, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
      </assemblies>
    </compilation>
  </system.web>
  <system.serviceModel>
    <serviceHostingEnvironment multipleSiteBindingsEnabled="true"/>
    <bindings>
      <customBinding>
        <binding name="customBinding0">
          <security authenticationMode="IssuedTokenOverTransport" messageSecurityVersion="WSSecurity11WSTrust13WSSecureConversation13WSSecurityPolicy12BasicSecurityProfile10">
            <issuedTokenParameters keyType="SymmetricKey"/>
          </security>
          <binaryMessageEncoding/>
          <httpsTransport/>
        </binding>
      </customBinding>
    </bindings>
    <services>
      <service behaviorConfiguration="Service.Service1Behavior" name="Service.WorkingHours">
        <endpoint address="https://crm.dev.local/Services/WorkingHours.svc" binding="customBinding" contract="Service.IWorkingHours" bindingConfiguration="customBinding0"/>
        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior name="Service.Service1Behavior">
          <federatedServiceHostConfiguration name="Service.WorkingHours"/>
          <serviceMetadata httpGetEnabled="true"/>
          <serviceDebug includeExceptionDetailInFaults="true"/>
          <serviceCredentials>
            <serviceCertificate findValue="AC123A8A913584818F789E3BB3B09D40E12A50BA" storeLocation="LocalMachine" storeName="My" x509FindType="FindByThumbprint"/>
          </serviceCredentials>
        </behavior>
        <behavior name="">
          <serviceMetadata httpGetEnabled="true"/>
          <serviceDebug includeExceptionDetailInFaults="false"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <extensions>
      <behaviorExtensions>
        <add name="federatedServiceHostConfiguration" type="Microsoft.IdentityModel.Configuration.ConfigureServiceHostBehaviorExtensionElement, Microsoft.IdentityModel, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
      </behaviorExtensions>
    </extensions>
  </system.serviceModel>
  <microsoft.identityModel>
    <service name="Service.WorkingHours">
      <audienceUris>
        <add value="https://crm.dev.local/Services/WorkingHours.svc"/>
      </audienceUris>
      <issuerNameRegistry type="Microsoft.IdentityModel.Tokens.ConfigurationBasedIssuerNameRegistry, Microsoft.IdentityModel, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35">
        <trustedIssuers>
          <add thumbprint="AC123A84E5A209F3FEE5190B44B1797414F68A77B" name="http://adfs.dev.local/adfs/services/trust"/>
        </trustedIssuers>
      </issuerNameRegistry>
      <certificateValidation certificateValidationMode="None"/>
    </service>
  </microsoft.identityModel>
</configuration>


No comments:

Post a Comment