Store authentication cookies in the web API using OWIN and app.UseWebApi.

I would like to use the same cookies in parts of the MVC and API of my application. I know this is not very safe, but still. Everything works, if I create a new MVC project in VS, the Web API is installed from Global.asax using GlobalConfiguration.Configure(WebApiConfig.Register) . But as soon as I try to use OWIN to configure the web API, I run into a problem where the user is always null in my API controllers.

Here is my code from Startup.cs :

 var config = new HttpConfiguration(); WebApiConfig.Register(config); app.UseWebApi(config); 

Controllers work, routes too, same WebApiConfig.cs file. However, the user is now null in my API controllers. What is missing from my HttpConfiguration instance that is present in GlobalConfiguration.Configuration ?

I need to use my own instance of HttpConfiguration instead of using GlobalConfiguration.Configuration , because I plan to use Autofac and it does not work with GlobalConfiguration , as mentioned here

EDIT:

My Startup.Auth.cs :

 // Configure the db context, user manager and signin manager to use a single instance per request app.CreatePerOwinContext(ApplicationDbContext.Create); app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create); app.CreatePerOwinContext<ApplicationSignInManager>(ApplicationSignInManager.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 // Configure the sign in cookie app.UseCookieAuthentication(new CookieAuthenticationOptions { AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie, LoginPath = new PathString("/Account/Login"), Provider = new CookieAuthenticationProvider { // Enables the application to validate the security stamp when the user logs in. // This is a security feature which is used when you change a password or add an external login to your account. OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<ApplicationUserManager, ApplicationUser>( validateInterval: TimeSpan.FromMinutes(30), regenerateIdentity: (manager, user) => user.GenerateUserIdentityAsync(manager)) } }); 
+7
asp.net-mvc owin asp.net-web-api2
source share
2 answers

What is missing from my HttpConfiguration instance that is present in GlobalConfiguration.Configuration?

GlobalConfiguration.cs Source Code from Codeplex

The main difference between when you create a new HttpConfiguration and one In GlobalConfiguration ...

 public static class GlobalConfiguration { private static Lazy<HttpConfiguration> _configuration = CreateConfiguration(); //...other code removed for brevity /// <summary> /// Gets the global <see cref="T:System.Web.Http.HttpConfiguration"/>. /// </summary> public static HttpConfiguration Configuration { get { return _configuration.Value; } } //...other code removed for brevity private static Lazy<HttpConfiguration> CreateConfiguration() { return new Lazy<HttpConfiguration>(() => { HttpConfiguration config = new HttpConfiguration(new HostedHttpRouteCollection(RouteTable.Routes)); ServicesContainer services = config.Services; Contract.Assert(services != null); services.Replace(typeof(IAssembliesResolver), new WebHostAssembliesResolver()); services.Replace(typeof(IHttpControllerTypeResolver), new WebHostHttpControllerTypeResolver()); services.Replace(typeof(IHostBufferPolicySelector), new WebHostBufferPolicySelector()); services.Replace(typeof(IExceptionHandler), new WebHostExceptionHandler(services.GetExceptionHandler())); return config; }); } //...other code removed for brevity } 

Also when considering how UseWebAPi extension in WebApiAppBuilderExtensions.cs

 public static IAppBuilder UseWebApi(this IAppBuilder builder, HttpConfiguration configuration) { if (builder == null) { throw new ArgumentNullException("builder"); } if (configuration == null) { throw new ArgumentNullException("configuration"); } HttpServer server = new HttpServer(configuration); try { HttpMessageHandlerOptions options = CreateOptions(builder, server, configuration); return UseMessageHandler(builder, options); } catch { server.Dispose(); throw; } } 

... the configuration completes with its own HttpServer , which overrides the default value used by GlobalConfiguration .

Looking through the documentation you included, I eventually came across this

For the standard IIS host, HttpConfiguration GlobalConfiguration.Configuration .

For self-hosting, the HttpConfiguration is your HttpSelfHostConfiguration instance.

For OWIN integration, the HttpConfiguration is the one you create in your application launch class and transition to the Web API middleware.

With standard IIS hosting, IIS handles authentication and user authentication, which it connects to the HttpConfiguration and the pipeline under the hood for you. When you new up HttpConfiguration yourself, you have no IIS benefits for authentication management for you, so your User remains null .

From your post, you indicate that you are using more than one HttpConfiguration instance that looks like you are trying to mix IIS and OWIN.

Looking at this question: OWIN Cookie Authentication

The answer shows that in the WebApi configuration, the next line ignores the cookie.

 // Configure Web API to use only bearer token authentication. // If you don't want the OWIN authentication to flow to your Web API then call // SuppressDefaultHostAuthentication on your HttpConfiguration. // This blocks all host level authentication at that point in the pipeline. config.SuppressDefaultHostAuthentication(); 

Commenting on this, cookie-based authentication work has been done.

UPDATE:

You specified...

Controllers work, routes too, the same WebApiConfig.cs file is used. However, User null in my API controllers is now

Take a look at ...

Combining authentication filters with host-level authentication

โ€œHost-level authenticationโ€ is the authentication performed by the host (for example, IIS) before the request reaches the framework of the web API.

Often you can enable host-level authentication for the rest of your application, but disable it for your web API controllers. For example, a typical scenario is to enable authentication at the host level, but use token-based authentication for the web API.

To disable host-level authentication inside the web API pipeline, call config.SuppressHostPrincipal() in your configuration. This calls the Web API to remove the IPrincipal from any request that is part of the Web API . In fact, it does not "authenticate" the request.

 public static class WebApiConfig { public static void Register(HttpConfiguration config) { config.SuppressHostPrincipal(); // Other configuration code not shown... } } 

If in your scenario you have the following in your web api configuration, this explains why your User always null . I suggest you comment on this or delete it all together.

+4
source share

I had exactly this problem when I switched to OWIN from a WebApi-only service. My user was also empty, although it was authenticated correctly. In my case, I skipped adding HostAuthenticationFilter after suppressing default host authentication.

 config.SuppressDefaultHostAuthentication(); config.Filters.Add(new HostAuthenticationFilter(YourAuthenticationType)); 

Make sure you do not forget your authentication filter. I did it successfully using Unity (not Autofac), but the principle is exactly the same. In my OWIN run this order:

 ConfigureAuth(app); WebApiConfig.Register(httpConfiguration); app.UseWebApi(httpConfiguration); 
+2
source share

All Articles