Search code examples
cookiesasp.net-web-apicorsodataasp.net-identity

ASP.NET Identity / OData using CORS and cookie authentication missing Auth cookie


I have an ASP.NET Identity site and a ASP.NET OData site.
Both sites have CORS enabled and both site are using ASP.NET Identity CookieAuthentication.
When I execute both sites locally on my computer using IIS (not express) the AUTH cookie is being passed in the header on each request to the OData site.
But when I deploy the sites to the production IIS server then the header is missing the AUTH cookie when calling the production OData site.
Both production and my local IIS have the same domain name and CORS is setup to allow all.

The WebApiConfig has

cors = new Http.Cors.EnableCorsAttribute("*", "*", "*");
config.Enable(cors);

Before anyone asks, yes the machine key is the same between sites.

UPDATE
This seems to be a CORS issue.
When both sites are on my local machine they use the same host name and domain name but when the site are on the production server they have different host names and the same domain name.


Solution

  • I finally got this to work.
    In the ASP.NET Identity site I have the following:

    // configure OAuth for login
    app.UseCookieAuthentication(new CookieAuthenticationOptions {
            AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
            Provider = new CookieAuthenticationProvider(),
            LoginPath = new PathString("/Account/Login.aspx"),
            CookieName = ".TESTAUTH",
            CookieDomain = ".test.com",
            CookieSecure = CookieSecureOption.Always
        });
    

    It seems that the important part on the ASP.NET Identity site is that the "CookieName, CookieDomain, and the Machine Key" must match the one on the OData site.

    And then on the OData site I have the following:

    // configure OAuth for login
    app.UseCookieAuthentication(new CookieAuthenticationOptions {
            AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
            Provider = new CookieAuthenticationProvider { OnApplyRedirect = ApplyRedirect },
            LoginPath = new PathString("/Account/Login.aspx"),
            CookieName = ".TESTAUTH",
            CookieDomain = ".test.com",
            CookieSecure = CookieSecureOption.Always
        });
    
    // build the configuration for web api
    HttpConfiguration config = new HttpConfiguration();
    
    // Enable CORS (Cross-Origin Resource Sharing) for JavaScript / AJAX calls
    // NOTE: USING ALL "*" IS NOT RECOMMENDED
    var cors = new Http.Cors.EnableCorsAttribute("*", "*", "*");
    config.EnableCors(cors);
    
    // call the web api startup
    WebApiConfig.Register(config);
    app.UseWebApi(config);
    
    private void ApplyRedirect(CookieApplyRedirectContext context)
    {
        Uri absoluteUri = null;
        if (Uri.TryCreate(context.RedirectUri, UriKind.Absolute, absoluteUri)) 
        {
            var path = PathString.FromUriComponent(absoluteUri);
            if (path == context.OwinContext.Request.PathBase + context.Options.LoginPath) 
            {
                QueryString returnURI = new QueryString(context.Options.ReturnUrlParameter, context.Request.Uri.AbsoluteUri);
                context.RedirectUri = "https://www.test.com/Account/Login.aspx" + returnURI.ToString;
            }
        }
        context.Response.Redirect(context.RedirectUri);
    }
    

    The "LoginPath" is required even though it does not exist on the OData site and you can't use a full url to another site for the login path.
    I used "OnApplyRedirect" to redirect to the actual Login page.

    I'm not sure what the difference is between "config.EnableCors" and "app.UseCors" but the EnableCors seems to be working for now.