title: User.Identity fluctuates between ClaimsIdentity and WindowsIdentity
body: <p>I have an MVC site that allows logging in using both Forms login and Windows Authentication. I use a custom MembershipProvider that authenticated the users against Active Directory, the System.Web.Helpers AntiForgery class for CSRF protection, and Owin cookie authentication middle-ware.</p>
  
  <p>During login, once a user has passed authentication against Active Directory, I do the following:</p>
  
  <pre><code>IAuthenticationManager authenticationManager = HttpContext.Current.GetOwinContext().Authentication;
  authenticationManager.SignOut(StringConstants.ApplicationCookie);
  var identity = new ClaimsIdentity(StringConstants.ApplicationCookie,
      ClaimsIdentity.DefaultNameClaimType,
      ClaimsIdentity.DefaultRoleClaimType);
  if(HttpContext.Current.User.Identity is WindowsIdentity)
  {
      identity.AddClaims(((WindowsIdentity)HttpContext.Current.User.Identity).Claims);
  }
  else
  {
      identity.AddClaim(new Claim(ClaimTypes.Name, userData.Name));
  }
  identity.AddClaim(new Claim("http://schemas.microsoft.com/accesscontrolservice/2010/07/claims/identityprovider", "Active Directory"));
  identity.AddClaim(new Claim(ClaimTypes.NameIdentifier, userData.userGuid));
  authenticationManager.SignIn(new AuthenticationProperties() { IsPersistent = false }, identity);
  </code></pre>
  
  <p>My SignOut function looks like this:</p>
  
  <pre><code>IAuthenticationManager authenticationManager = HttpContext.Current.GetOwinContext().Authentication;
  authenticationManager.SignOut(StringConstants.ApplicationCookie);
  </code></pre>
  
  <p>Logging in is performed via a jQuery.ajax request. On success, the <code>Window.location</code> is updated to the site's main page.</p>
  
  <p>Logging in with both Forms and <code>IntegratedWindowsAuthentication</code> (IWA) works, but I've run into a problem when logging in with IWA. This is what happens:</p>
  
  <ol>
  <li>The user selects IWA on the login page and hits the submit button. This is sent to the regular login action via an ajax request.</li>
  <li>The site receives the request, sees the "use IWA" option and redirects to the relevant action. 302 response is sent.</li>
  <li>The browser automatically handles the 302 response and calls the redirect target.</li>
  <li>A filter sees that the request is headed to the IWA login action and that User.Identity.IsAuthenticated == false. 401 response is sent.</li>
  <li>The browser automatically handles the 401 response. If the user has not authenticated using IWA in the browser yet, they get a popup to do so (default browser behavior). Once credentials have been received, the browser performs the same request with user credentials.</li>
  <li>The site receives the authenticated request and impersonates the user to perform a check against Active Directory. If the user passes authentication, we finalize SignIn using the code above.</li>
  <li>User is forwarded to the site's main page.</li>
  <li>The site receives the request to load the main page. <strong>This is where things <em>sometimes</em> go awry</strong>.<br>
  The <code>User.Identity</code> at this point is of type <code>WindowsIdentity</code> with <code>AuthenticationType</code> set to <code>Negotiate</code>, and <em>NOT</em> as I would expect, the <code>ClaimsIdentity</code> created in the <code>SignIn</code> method above.<br>
  The site prepares the main page for the user by calling <code>@AntiForgery.GetHtml()</code> in the view. This is done to create a new AntiForgery token with the logged in user's details. The token is created with the <code>WindowsIdentity</code> </li>
  <li>As the main page loads, ajax requests made to the server arrive with <code>ClaimsIdentity</code>! The first <code>POST</code> request to arrive therefore inevitably causes an <code>AntiForgeryException</code> where the anti-forgery token it sent is "for a different user".</li>
  </ol>
  
  <p>Refreshing the page causes the main page to load with <code>ClaimsIdentity</code> and allows <code>POST</code> requests to function.</p>
  
  <p><strong>Second, related, problem</strong>: At any point after the refresh, once things are supposedly working properly, a <code>POST</code> request may arrive with <code>WindowsIdentity</code> and not with <code>ClaimsIdentity</code>, once again throwing an <code>AntiForgeryException</code>.</p>
  
  <ul>
  <li>It is <em>not</em> any specific post request,</li>
  <li>it is <em>not</em> after any specific amount of time (may be the first/second request, may be the hundredth),</li>
  <li>it is <em>not</em> necessarily the first time that specific post request got called during that session.</li>
  </ul>
  
  <p>I feel like I'm either missing something regarding the <code>User.Identity</code> or that I did something wrong in the log-in process... Any ideas?</p>
  
  <p><strong><em>Note</em></strong>: Setting <code>AntiForgeryConfig.SuppressIdentityHeuristicChecks = true;</code> allows the <code>AntiForgery.Validate</code> action to succeed whether <code>WindowsIdentity</code> or <code>ClaimsIdentity</code> are received, but as is stated on MSDN:</p>
  
  <blockquote>
    <p>Use caution when setting this value. Using it improperly can open
    security vulnerabilities in the application.</p>
  </blockquote>
  
  <p>With no more explanation than that, I don't know what security vulnerabilities are actually being opened here, and am therefore loathe to use this as a solution.</p>