I'd like to keep using same cookies in MVC and API parts of my app. I know this isn't very secure but still.
Everything works if I create a new MVC project in VS, Web API is set up from Global.asax using GlobalConfiguration.Configure(WebApiConfig.Register)
.
But as soon as I'm trying to use OWIN to configure Web API I run into a problem where User is always null in my API controllers.
Here's my code from Startup.cs
:
var config = new HttpConfiguration();
WebApiConfig.Register(config);
app.UseWebApi(config);
Controllers work, routes too, same WebApiConfig.cs file is used. However the User is null in my API controllers now. What's missing from my instance of HttpConfiguration
that is present in GlobalConfiguration.Configuration
?
I need to use my own instance of HttpConfiguration
instead of using GlobalConfiguration.Configuration
because I'm planning to use Autofac and it doesn't 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))
}
});
OWIN (Open Web Interface for . NET) is a standard for an interface between . NET Web applications and Web servers. It is a community-owned open-source project. The OAuth authorization framework enables a third-party application to obtain limited access to a HTTP service.
That’s not the case. You can do authentication and authorization in a Web Api using cookies the same way you would for a normal web application, and doing so has the added advantage that cookies are easier to setup than for example JWT tokens. There are just a few things you need to be aware.
There’s this frequent notion that you need to use tokens to secure a web api and you can’t use cookies. That’s not the case. You can do authentication and authorization in a Web Api using cookies the same way you would for a normal web application, and doing so has the added advantage that cookies are easier to setup than for example JWT tokens.
Cookies in Web API. To add a cookie to an HTTP response, create a CookieHeaderValue instance that represents the cookie. Then call the AddCookies extension method, which is defined in the System.Net.Http.
What you need to do server-side is to configure ASP.NET’s cookie authentication middleware and also setup CORS so that your Web Api “declares” it accepts requests from the domain where your client is hosted. To setup the cookie middleware you have to setup the authentication middleware in your Startup.cs ‘ ConfigurateServices method:
What's missing from my instance of HttpConfiguration that is present in GlobalConfiguration.Configuration?
GlobalConfiguration.cs Source code from Codeplex
The main difference between when you create a new HttpConfiguration
and the 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 looking at how the 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 is wrapped in its own HttpServer
which overrides the default one used by GlobalConfiguration
.
Looking through the documentation you included, I eventually came across this
For standard IIS hosting, the
HttpConfiguration
isGlobalConfiguration.Configuration
.For self hosting, the
HttpConfiguration
is yourHttpSelfHostConfiguration
instance.For OWIN integration, the
HttpConfiguration
is the one you create in your app startup class and pass to the Web API middleware.
With standard IIS hosting, IIS handles user Authentication and Identification which it plugs into the HttpConfiguration
and pipeline under the hood for you. When you new
up HttpConfiguration
your self you don't have the benefits of IIS to manage Authentication for you so your User
remains null
.
From your post you indicate that you are using more than one instance of HttpConfiguration
which looks like you are trying to mix IIS and OWIN.
Looking at this question : OWIN Cookie Authentication
The answer shows that in the WebApi Config the following line was ignoring 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 it out made the cookie based Authentication work.
UPDATE:
You indicated...
Controllers work, routes too, same
WebApiConfig.cs
file is used. However theUser
isnull
in my API controllers now
Take a look at...
Combining Authentication Filters with Host-Level Authentication
“Host-level authentication” is authentication performed by the host (such as IIS), before the request reaches the Web API framework.
Often, you may want to to 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 Forms Authentication at the host level, but use token-based authentication for Web API.
To disable host-level authentication inside the Web API pipeline, call
config.SuppressHostPrincipal()
in your configuration. This causes Web API to remove theIPrincipal
from any request that enters the Web API pipeline. Effectively, it "un-authenticates" 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, it would explain why your User
is always null
. I suggest you comment it out or remove it all together.
I had exactly this problem when I transferred to OWIN from a WebApi only service. My user was also null even though it was correctly authenticated. In my case I had missed adding the HostAuthenticationFilter in after suppressing the Default Host Authentication.
config.SuppressDefaultHostAuthentication();
config.Filters.Add(new HostAuthenticationFilter(YourAuthenticationType));
Check that you have not forgotten your authentication filter here. I've done this successfully using Unity (rather than Autofac) but the principal is exactly the same. In my OWIN startup this order:
ConfigureAuth(app);
WebApiConfig.Register(httpConfiguration);
app.UseWebApi(httpConfiguration);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With