title: Sometimes ADFS exception: ID1032 "At least one 'audienceUri' must be specified..."
body: <p>I have a project which uses ADFS authentication in some cases. The configuration is read from a database and the URLs are different from customer to customer, so there are many configuration options which I can't hard-code in my <code>Web.config</code>.</p>
  
  <p>The problem is that I get the following error:</p>
  
  <blockquote>
    <p>ID1032: At least one 'audienceUri' must be specified in the SamlSecurityTokenRequirement when the AudienceUriMode is set to 'Always' or 'BearerKeyOnly'</p>
  </blockquote>
  
  <p>But I don't get it always, and I can't reproduce it. This is pretty annoying since I can't really debug it as long as I can't reproduce it. And I'm not sure whether I did everything correct. Maybe some ADFS expert can have a look at it.</p>
  
  <p>(Trusts between my relying parties and their corresponding ADFS servers have been established, of course.)</p>
  
  <p>Here is my code (only interesting parts of it), please ask if anything is missing or unclear.</p>
  
  <p>Some snippets from my <code>Web.config</code>:</p>
  
  <pre class="lang-xml prettyprint-override"><code>&lt;system.webServer&gt;
    &lt;modules&gt;
      &lt;add name="WSFederationAuthenticationModule" type="Microsoft.IdentityModel.Web.WSFederationAuthenticationModule, Microsoft.IdentityModel, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" preCondition="managedHandler" /&gt;
      &lt;add name="SessionAuthenticationModule" type="Microsoft.IdentityModel.Web.SessionAuthenticationModule, Microsoft.IdentityModel, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" preCondition="managedHandler" /&gt;
      &lt;add name="ClaimsPrincipalHttpModule" type="Microsoft.IdentityModel.Web.ClaimsPrincipalHttpModule, Microsoft.IdentityModel, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" preCondition="managedHandler" /&gt;
      &lt;!-- ... --&gt;
    &lt;/modules&gt;
    &lt;!-- ... --&gt;
  &lt;/system.webServer&gt;
  </code></pre>
  
  <pre class="lang-xml prettyprint-override"><code>&lt;microsoft.identityModel&gt;
    &lt;service&gt;
      &lt;securityTokenHandlers&gt;
        &lt;remove type="Microsoft.IdentityModel.Tokens.SessionSecurityTokenHandler" /&gt;
        &lt;add type="MyProject.MachineKeySessionSecurityTokenHandler" /&gt;
      &lt;/securityTokenHandlers&gt;
      &lt;federatedAuthentication&gt;
        &lt;wsFederation passiveRedirectEnabled="false"
                      issuer="https://fail/IssuerEndpoint"
                      realm="https://fail/FederationResult"
                      homeRealm="https://fail"
                      requireHttps="true" /&gt;
      &lt;/federatedAuthentication&gt;
    &lt;/service&gt;
  &lt;/microsoft.identityModel&gt;
  </code></pre>
  
  <p>Those <em>fail</em> values will be overridden per request (see my <code>Login()</code> method below), but I have to specify something in my <code>Web.config</code>, so I chose to specify a valid URI at least. The default <code>SessionSecurityTokenHandler</code> had to be replaced because my service runs on multiple machines with DNS Round-Robin (sharing the same machine key).</p>
  
  <p>Then I have a class I called <code>AdfsTrustFilter</code> which implements <code>IAuthorizationFilter</code>. I know it's bit of overhead, but due to the project structure, this filter is used as a global filter on every request (order is the least value in the whole project). In the <code>OnAuthorization</code> method, I complete the configuration as follows:</p>
  
  <pre class="lang-c# prettyprint-override"><code>public sealed class AdfsTrustFilter : IAuthorizationFilter
      public void OnAuthorization(AuthorizationContext filterContext)
          // ...
  
          var fam = FederatedAuthentication.WSFederationAuthenticationModule;
  
          fam.ServiceConfiguration = new ServiceConfiguration
          {
              AudienceRestriction = new AudienceRestriction(AudienceUriMode.Always),
              CertificateValidationMode = X509CertificateValidationMode.PeerOrChainTrust,
              // MyIssuerNameRegistry checks whether a fingerprint is known and some other stuff
              IssuerNameRegistry = new MyIssuerNameRegistry()
          };
  
          // config.OwnPath contains something like "https://my.app.com/AppRoot/"
          fam.ServiceConfiguration.AudienceRestriction.AllowedAudienceUris.Add(new Uri(config.OwnPath));
      }
  }
  </code></pre>
  
  <p>This is the code that starts the authentication:</p>
  
  <pre class="lang-c# prettyprint-override"><code>public ActionResult Login()
  {
      // ...
  
      // again something like "https://my.app.com/AppRoot/"
      string baseUrl = Config.OwnPath.TrimEnd('/') + "/";
  
      // adfs endpoint for this customer: i.e. "https://identity.provider.net/adfs/ls/"
      string endpoint = Config.AdfsConfig.IdentityProvider.Endpoint;
  
      // the code behind FederationResult is shown below
      var signIn = new SignInRequestMessage(new Uri(endpoint), baseUrl + "/Adfs/FederationResult")
                          {
                              Context = baseUrl
                          };
  
      var url = signIn.WriteQueryString();
  
      return Redirect(url);
  }
  </code></pre>
  
  <p>And finally the <code>FederationResult</code> callback:</p>
  
  <pre class="lang-c# prettyprint-override"><code>public ActionResult FederationResult()
  {
      WSFederationAuthenticationModule fam = FederatedAuthentication.WSFederationAuthenticationModule;
      HttpRequest request = System.Web.HttpContext.Current.Request;
  
      if (fam.CanReadSignInResponse(request, true))
      {
          var id = (IClaimsIdentity) User.Identity;
  
          // do something
      }
  
      // ...
  }
  </code></pre>
  
  <p>P.S.: The ADFS server was recently upgraded from 2008 R2 to 2012, but this didn't change anything. ADFS version was always 2.0.</p>