2
votes

I have an OWIN Self-hosted Web Api and some MVC web applications all in the same domain. Web applications are calling the Web Api in server side. They use OWIN cookie authentication like this:

public void ConfigureAuth(IAppBuilder app)
{
    app.CreatePerOwinContext<MyUserManager>(MyUserManager.Create);
    app.UseCookieAuthentication(new CookieAuthenticationOptions
        {
            AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
            LoginPath = new PathString("/Account/Login"),
            Provider = new CookieAuthenticationProvider
            {
                OnValidateIdentity = 
                    SecurityStampValidator.OnValidateIdentity<MyUserManager, MyUser, Guid>(
                        validateInterval: TimeSpan.FromMinutes(30),
                        regenerateIdentityCallback: (manager, user) =>
                            user.GenerateUserIdentityAsync(manager),
                        getUserIdCallback: (id) => (new Guid(id.GetUserId())))
            }
        });
}

Being in the same domain, when user sign in one web application, the cookies are available in other web applications and the user is signed in.

I implement cookie authentication in my self-hosted web api like this:

public void Configuration(IAppBuilder appBuilder)
    {
        // Configure Web API for self-host. 
        HttpConfiguration config = new HttpConfiguration();

        config.MessageHandlers.AddRange(new List<DelegatingHandler>
        {
            new ServerContextInitializerHandler(), new LogRequestAndResponseHandler(), 
        });
        config.MessageHandlers.AddRange(ServiceLocator.Current.GetAllInstances<DelegatingHandler>());

        config.Services.Add(typeof(IExceptionLogger), new GlobalExceptionLogger());
        config.Services.Replace(typeof(IExceptionHandler), new GlobalExceptionHandler());

        config.Routes.MapHttpRoute( 
            name: "DefaultApi", 
            routeTemplate: "api/{controller}/{id}", 
            defaults: new { id = RouteParameter.Optional } 
        ); 

        appBuilder.UseCookieAuthentication(new CookieAuthenticationOptions
        {
            AuthenticationType = "ApplicationCookie",
            Provider = new CookieAuthenticationProvider(),
            AuthenticationMode = Microsoft.Owin.Security.AuthenticationMode.Active
        });

        appBuilder.UseWebApi(config);
    }

I expect to have the user in web api, as it's in the same domain and the cookies are all available in received requests. The problem is the Request.GetRequestContext().Principal is null (and other alternatives like Request.GetOwinContext().Authentication.User).

I emphasis that the Request.GetOwinContext().Request.Cookies contains all cookies that are available in the web application.

1

1 Answers

4
votes

It has passed a long time from asking the question, but there is no answer yet, but I found the reason and I'm just sharing it. Hope to be useful. As I mentioned, I implemented cookie authentication in my self-hosted web api, and the authentication cookie was available in the received request in web api. The problem is, In web applications (where the users signed in) OWIN middle-ware is encoding the ClaimsIdentity data into an Access Token and put it in the authentication cookie, and to access the authentication data in this cookie, decode it's content. This encoding and decoding on web applications is done by encryption and decryption using Machine Key of the machine on which the server is running, and in self hosted web api using another way named DPAPI. So, I had the authentication cookie on web api request, but because the OWIN middle-ware tried to do decryption using DPAPI, it wasn't able to extract the Access Token from the cookie.