Owin + DefaultAuthenticationTypes.ApplicationCookie + Windows Authentication - asp.net-mvc

My MVC5.1 application uses OWIN authentication based on http://www.khalidabuhakmeh.com/asp-net-mvc-5-authentication-breakdown
The user persistence in db and login validation is handled by my custom UserService class. This works perfectly fine when using individual accounts for users to login into the system.
I also need to make this work with Windows Authentication (Active Directory). So if Windows auth is turned on (on IIS & a flag in my web.config) the AD user will be validated against my DB to see if the logged in user has access to my web application and if yes log him in (set the application cookie).
I enabled Windows Auth in IIS, disabled Anonymous Auth in IIS, and removed <authentication mode="None" /> from my web.config file. This makes OWIN think the user is already authenticated even though in the startup I configure it to use ApplicationCookie
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
LoginPath = new PathString("/Account/Login")
});
Well this is fine, I could write a wrapper around AuthenticationManager.User.Identity.IsAuthenticated property and add the check to validate the user against my db. But then I am not able to add custom claims as OWIN doesnt seem to be using an Application Cookie but directly uses the WindowsClaimsIdentity.
My login function (the one that tries to add additional claims) is as follows:
_authenticationManager.SignOut(DefaultAuthenticationTypes.ApplicationCookie);
var identity = new ClaimsIdentity(
new[] {
new Claim(ClaimTypes.NameIdentifier, user.UserID.ToString()),
new Claim(ClaimTypes.Name, user.UserName),
new Claim(ClaimTypes.UserData, user.CurrentDomainID.ToString())
},
DefaultAuthenticationTypes.ApplicationCookie,
ClaimTypes.Name,
ClaimTypes.Role);
_authenticationManager.SignIn(new AuthenticationProperties() { IsPersistent = isPersistent }, identity);
Now If I add the line <authentication mode="None" /> in web.config it seems to be working, meaning OWIN only looks for claims inside its cookie and doesnt authenticate the user until the user exists in the DB.
But in both these cases, I am stuck in a redirect loop on the login page unless i remove login path from the startup. I tried setting Response.SuppressFormsAuthenticationRedirect=false in my login controller but no change.
Another problem I am facing is, the browser doesnt show me the login page until I enter a valid username/password in the basic auth popup even if i am logged in with my AD account in windows. Is there a way to hide this popup?

Related

ASP.NET MVC authentication cookie not working correctly when deployed to hostgator

I am using ASP.NET MVC 5 identity authentication cookie in my site. In my local environment the authentication is working correctly.
Also when I deployed my site to goddady shared hosting plesk everything works fine.
However, when I deploy the exact same site to hostgator shared hosting, after logging in, the user is redirected back to login page after trying to access any of the controller actions. In the request I see Asp.Authentication.Cookie being sent as part of the request header, however, I get a 302 response from the server and the user is redirected to login page (because I think the authorisation fails).
I cannot figure out why this would happen.
Below is my startup.auth:
// Enable the application to use a cookie to store information for the signed in user
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
LoginPath = new PathString("/Account/Login")
});
// Use a cookie to temporarily store information about a user logging in with a third party login provider
app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);
and the sign in method used when logging in:
AuthenticationManager.SignOut(DefaultAuthenticationTypes.ExternalCookie);
var identity = await _userManager.CreateIdentityAsync(user, DefaultAuthenticationTypes.ApplicationCookie);
AuthenticationManager.SignIn(new AuthenticationProperties() { IsPersistent = isPersistent }, identity);
This is sample request made after logging in:
The response is 302
Update
I wonder if it is IIS version issue, as godday is using v8.5 and hostgator is using v10.
Either way i moved over to bisend.com and had to do away with hostgator
I had a similar issue with a WordPress site I had hosted on Hostgator. It was a login and registration site but cookies were not recognised as being set on the frontend homepage. I thought I had managed to change the .htaccess rules for caching from my theme's functions.php file, but it turned out that the .htaccess generated by Hostgator was ignoring these and setting its own rules for optimising the speed of the site.
I commented out the affected caching lines and added
ExpiresActive On
ExpiresDefault A1
Header append Cache-Control must-revalidate
as per this site
The issues I was experiencing went away.

Owin authentication sign-out is not invalidating Identity in asp.net MVC

I am connecting to QBO (Quickbooks Online) app using OAuth. QBO has it's own Auth Server and Auth Client.
I am using single sign-on. So after successfully connecting to QBO I am setting Cookie using following code:
var id = new ClaimsIdentity(claims, "Cookies");
Request.GetOwinContext().Authentication.SignIn(id);
My Startup.cs contains:
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = "Cookies",
AuthenticationMode = AuthenticationMode.Passive,
LoginPath = new PathString(Paths.LoginPath)
});
To signout I used :
HttpContext.GetOwinContext()
.Authentication
.SignOut(HttpContext.GetOwinContext().Authentication.GetAuthenticationTypes().
Select(o => o.AuthenticationType).ToArray());
But User.Identity remain valid after sign-out. I have tried different solutions from SO but no success.
Any idea?
When you call SignOut it would delete the cookie in order to invalidate user identity, but the User would be still authenticated during that request.
You can put [Authorize] attribute on the action that is signing the user out, so it will be redirected to login page.

MVC ASP.Net local Active Directory Login

I've written a web site that uses Owin to login using the standard Login form. This is working fine. Each customer has their own version of the site on their server with different web.config values so it behaves the way each want it to.
I've now been asked for a version that automatically logs users in by retrieving their Windows Id and then using this to get their details from the local Active Directory.
I have a script that will do this, but I'm having difficulty calling it.
I'd like to keep as much of the code I have there already so I can continue to use the User and UserManager objects.
I'm hoping it is possible to amend something in the Startup.Auth.cs script so instead of using LoginPath for the CookieAuthenticationOptions it points to my Active Directory script.
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))
}
});
Unfortunately replacing the LoginPath with the path of the Active Directory script causes an endless loop which results in the querystring being too long for the browser error.
I have set IIS with:
Anonymous Authentication: Disabled, ASP.Net Impersonation: Enabled, Forms Authentication: Disabled, Windows Authentication: Enabled
I have been stuck on this for the past 5 days so any help would be much appreciated. Thank you.
Just create your own provider which will check username and password against your AD and add it to your CookieAuthenticationOptions object in appBuilder. Your provider class should inherit CookieAuthenticationProvider and override sign in methods you need. Here you can find list of available methods
https://msdn.microsoft.com/en-us/library/microsoft.owin.security.cookies.cookieauthenticationprovider(v=vs.113).aspx

Context.User is null in self-hosted SignalR hub when called from IIS-hosted MVC app

I'm have an IIS hosted MVC 5 app that uses Asp.Net Identity and OWIN for authentication via .AspNet.ApplicationCookie. From one of its views, I make calls to long-running methods on a self-hosted SignalR hub (running on the same server) via a SignalR JS client. These calls all work as expected. I now wish to decorate my hub with [Authorize(Roles = "Administrator")]. This has proved problematic. Setting a breakpoint in a hub method reveals that the Context.User is null, even though the .AspNet.ApplicationCookie is clearly in the Context.RequestCookies.
Here is the bootstrap for the hub (self-hosted in a windows service):
app.Map("/signalr", map =>
{
map.UseCors(CorsOptions.AllowAll);
map.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie
});
var hubConfiguration = new HubConfiguration();
map.RunSignalR(hubConfiguration);
});
Here is the auth config for the web app (hosted in IIS):
// Configure the db context, user manager and signin manager to use a single instance per request
app.CreatePerOwinContext(UserAccountContext.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))
}
});
Question 1: Is the use of [Authorize] possible in the scenario described above? If so, how?
Question 2: Would it be better to just merge the self-hosted hub into the IIS hosted app? If so, are there any issues with long-running hub methods under IIS?
Update 1
I've tried adding TicketDataFormat = new TicketDataFormat(new MachineKeyDataProtector("ASP.NET Identity")) to the CookieAuthenticationOptions on my hub config, but that didn't help. Sure seems like this should be easier than it is.
I ended up moving my self-hosted hub into my ASP.Net application and it worked just fine. This seemed easier and more maintainable than implementing the workaround in this SO question, OWIN Self-Host CookieAuthentication & Legacy .NET 4.0 Application / FormsAuthenticationTicket

OWIN Authentication Login Page

I have an ASP.NET MVC5 application I am working on right now that I am integrating OWIN authentication into. I currently have my app configured in the startup class as so
// Enable the application to use a cookie to store information for the signed in user
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie, // "ApplicationCookie",
LoginPath = new PathString("/Producer/LogIn/")
});
This is working great. But I have a few areas in my code where I need to know the login path. I am not looking to directly call a method to log out the user and redirect them, I just need the value of the PathString.
I could hard code it of course as its a value that wouldn't change often, (if ever) but I hate to do that and I want a solution that I can reuse in other projects cleanly. I would prefer to be able to access this value programmatically.
TIA.

Resources