title: 401 Unauthorized when sending ajax request to web api
body: <p>I've been scratching my head at this for 2 days now.  I am using WebAPI version 2.2 and I am using CORS.  This setup works on the server side, I am allowed to get authorized content from my web client server code but getting unauthorized in my ajax calls.</p>
  
  <p>Here is my configuration:</p>
  
  <p><strong>Web API Config</strong></p>
  
  <p>WebApiConfig:</p>
  
  <pre><code>public static class WebApiConfig
  {
      public static void Register(HttpConfiguration config)
      {
  
          // Web API configuration and services
          // Configure Web API to use only bearer token authentication.
          config.SuppressDefaultHostAuthentication();
          config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType));
          config.Filters.Add(new HostAuthenticationFilter(DefaultAuthenticationTypes.ApplicationCookie));
  
          //enable cors
          config.EnableCors();
  
          // Web API routes
          config.MapHttpAttributeRoutes();
  
          config.Routes.MapHttpRoute(
              name: "DefaultApi",
              routeTemplate: "api/{controller}/{id}",
              defaults: new { id = RouteParameter.Optional }
          );
  
          config.Filters.Add(new ValidationActionFilter());
      }
  }
  </code></pre>
  
  <p>Startup.Auth.cs:</p>
  
  <pre><code>// Configure the db context and user manager to use a single instance per request
          app.CreatePerOwinContext(UserContext&lt;ApplicationUser&gt;.Create);
          app.CreatePerOwinContext&lt;ApplicationUserManager&gt;(ApplicationUserManager.Create);
  
          // Enable the application to use a cookie to store information for the signed in user
          // and to use a cookie to temporarily store information about a user logging in with a third party login provider
          app.UseCookieAuthentication(new CookieAuthenticationOptions
              {
                  AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
                  CookieHttpOnly = true,
                  CookieName = "Outpour.Api.Auth"
              }
          );
  
          //app.UseCors(CorsOptions.AllowAll);
          //app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);
  
          // Configure the application for OAuth based flow
          PublicClientId = "self";
          OAuthOptions = new OAuthAuthorizationServerOptions
          {
              TokenEndpointPath = new PathString("/Token"),
              Provider = new ApplicationOAuthProvider(PublicClientId),
              AuthorizeEndpointPath = new PathString("/api/Account/ExternalLogin"),
              AccessTokenExpireTimeSpan = TimeSpan.FromDays(14),
              AllowInsecureHttp = true
          };
  
          // Enable the application to use bearer tokens to authenticate users
          app.UseOAuthBearerTokens(OAuthOptions);
  </code></pre>
  
  <p>(I've tried every combination of app.UseCors(CorsOptions.AllowAll) and config.EnableCors())</p>
  
  <p>My Controller attribute:</p>
  
  <pre><code>[Authorize]
  [EnableCors("http://localhost:8080", "*", "*", SupportsCredentials = true)]
  [RoutePrefix("api/videos")]
  public class VideosController : ApiController...
  </code></pre>
  
  <p><strong>Web Client</strong></p>
  
  <p>Ajax Call:</p>
  
  <pre><code>$.ajaxPrefilter(function (options, originalOptions, jqXHR) {
              options.crossDomain = {
                  crossDomain: true
              };
              options.xhrFields = {
                  withCredentials: true
              };
          });
  
          function ajaxGetVideoResolutionList() {
              var request = {
                  type: "GET",
                  dataType: "json",
                  timeout: Outpour.ajaxTimeOut,
                  url: Outpour.apiRoot + "/videos/resolutions"
              };
              $.ajax(request).done(onAjaxSuccess).fail(onAjaxError);
  </code></pre>
  
  <p>Cookie Creation:</p>
  
  <pre><code>var result = await WebApiService.Instance.AuthenticateAsync&lt;SignInResult&gt;(model.Email, model.Password);
  
              FormsAuthentication.SetAuthCookie(result.AccessToken, model.RememberMe);
  
              var claims = new[]
              {
                  new Claim(ClaimTypes.Name, result.UserName), //Name is the default name claim type, and UserName is the one known also in Web API.
                  new Claim(ClaimTypes.NameIdentifier, result.UserName) //If you want to use User.Identity.GetUserId in Web API, you need a NameIdentifier claim.
              };
  
              var authTicket = new AuthenticationTicket(new ClaimsIdentity(claims, DefaultAuthenticationTypes.ApplicationCookie), new AuthenticationProperties
              {
                  ExpiresUtc = result.Expires,
                  IsPersistent = model.RememberMe,
                  IssuedUtc = result.Issued,
                  RedirectUri = redirectUrl
              });
  
              byte[] userData = DataSerializers.Ticket.Serialize(authTicket);
  
              byte[] protectedData = MachineKey.Protect(userData, new[] { "Microsoft.Owin.Security.Cookies.CookieAuthenticationMiddleware", DefaultAuthenticationTypes.ApplicationCookie, "v1" });
  
              string protectedText = TextEncodings.Base64Url.Encode(protectedData);
  
              Response.Cookies.Add(new HttpCookie("Outpour.Api.Auth")
              {
                  HttpOnly = true,
                  Expires = result.Expires.UtcDateTime,
                  Value = protectedText
              });
  </code></pre>
  
  <p>And last but not least, my headers.</p>
  
  <pre><code>Remote Address:127.0.0.1:8888
  Request URL:http://127.0.0.1/api/videos/resolutions
  Request Method:GET
  Status Code:401 Unauthorized
  
  **Request Headersview source**
  Accept:application/json, text/javascript, */*; q=0.01
  Accept-Encoding:gzip,deflate,sdch
  Accept-Language:en-US,en;q=0.8
  Cache-Control:no-cache
  Host:127.0.0.1
  Origin:http://localhost:8080
  Pragma:no-cache
  Proxy-Connection:keep-alive
  Referer:http://localhost:8080/video/upload
  User-Agent:Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.124 Safari/537.36
  
  **Response Headersview source**
  Access-Control-Allow-Credentials:true
  Access-Control-Allow-Origin:http://localhost:8080
  Cache-Control:no-cache
  Content-Length:61
  Content-Type:application/json; charset=utf-8
  Date:Wed, 08 Oct 2014 04:01:19 GMT
  Expires:-1
  Pragma:no-cache
  Server:Microsoft-IIS/8.0
  WWW-Authenticate:Bearer
  X-AspNet-Version:4.0.30319
  X-Powered-By:ASP.NET
  </code></pre>
  
  <p>Developer tools and fiddler claim there were no cookies sent with the request.</p>