Sharing .AspNet.ApplicationCookie between two MVC projects - asp.net-mvc

I have a Web project to login our users. It signs a user in, creates the ".AspNet.ApplicationCookie" cookie and then redirects to a page "~/Views/../Redirect.cshtml" that will choose, based on some rules, what will be the Website user will be redirected to. Very simple, a "redirecting..." message and a setTimeout function.
The problem is...website 2 does not recognize cookie created by site 1 and just moves the user back to site 1.
Some information:
1 - Works running both sites locally
2 - Site 1 and 2 are in the same server running on the same domain, just different ports.
3 - Both sites share the same ApplicationUserManager.Create call since I moved this class to a Domain project.
Startup.cs is as follows:
public void ConfigureAuth(IAppBuilder app)
{
// Configure the db context, user manager and signin manager to use a single instance per request
app.CreatePerOwinContext(AccountDbContext.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, DefaultAuthenticationTypes.ApplicationCookie))
}
});
app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);
// Enables the application to temporarily store user information when they are verifying the second factor in the two-factor authentication process.
app.UseTwoFactorSignInCookie(DefaultAuthenticationTypes.TwoFactorCookie, TimeSpan.FromMinutes(5));
// Enables the application to remember the second login verification factor such as phone or email.
// Once you check this option, your second step of verification during the login process will be remembered on the device where you logged in from.
// This is similar to the RememberMe option when you log in.
app.UseTwoFactorRememberBrowserCookie(DefaultAuthenticationTypes.TwoFactorRememberBrowserCookie);
}

It turns out that the problem was the Application Pool. All sites sharing the same cookie need to run on the same Application Pool. Once I set them all to use the same, it worked just fine.

Related

Why log out sooner than ExpireTimeSpan in asp.net identity?

I am working on an asp.net mvc application that used asp.net identity.
In Startup.Auth.cs file I set ExpireTimeSpan to 20 days but when I log in to my app, sooner than 20 days my app is logged out and I have to log in agian!
Startup.Auth.cs
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
LoginPath = new PathString("/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, User>(
validateInterval: TimeSpan.FromMinutes(0),
regenerateIdentity: (manager, user) => user.GenerateUserIdentityAsync(manager))
},
ExpireTimeSpan = TimeSpan.FromDays(20),
SlidingExpiration = true
});
And in Login action:
var result = await SignInManager.PasswordSignInAsync(model.Email, model.Password, model.RememberMe, shouldLockout: true);
Update
When I log in, .AspNet.ApplicationCookie is generated and it's expire date is set to "20" days later, And when I open site next day, I am logout but the cookie is exist.
What is the cause of this problem?
Thanks in advance.
Here are the few reasons for logging out sooner than expected:
Having multiple web apps on the same domain and all of them have the same cookie name (cookie name collisions). In this case app A overwrites app B's cookies.
When validateInterval is set to zero/TimeSpan.FromMinutes(0), all calls to UpdateSecurityStamp will force the user to logout and login again immediately, including UserManager.CreateAsync, UserManager.RemovePasswordAsync, UserManager.UpdatePassword, UserManager.RemoveLoginAsync, UserManager.ChangePhoneNumberAsync/SetPhoneNumberAsync, UserManager.SetTwoFactorEnabledAsync, UserManager.SetEmailAsync. Which means if you update the user's properties, UpdateSecurityStamp will be called.
If you update the .NET framework on the server, it will overwrite the machine-key too. changing that will mark all of the issued cookies as invalid. The Machine-Key is a set of keys used to encrypt and decrypt the cookies. If you are running behind a load balancer you will want to ensure that the web farm is using a consistent machine-key.
If you are storing too many user-claims with your cookies, they will become large (larger than ~5K) and some browsers will reject them. so check out the size of the issued cookie.
Users can set their browser to delete the cookies when they close it (private browsing).

c# Asp.net mvc identity, .AspNet.ApplicationCookie invalid after ten minutes [duplicate]

I am using ASP.NET identity membership. This is the Startup.Auth.cs code:
app.CreatePerOwinContext(EFDbContext.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"),
ExpireTimeSpan = TimeSpan.FromHours(3),
CookieName = "MyLoginCookie",
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, User>(
validateInterval: TimeSpan.FromMinutes(30),
regenerateIdentity: (manager, user) => user.GenerateUserIdentityAsync(manager))
}
});
As you can see I've set expiretimespan to 3 hours, but on the production server it doesn't work; it expires in about ten minutes. When I inspect elements MyLoginCookie still exists. On localhost it works fine. Why does it have problems on the production server? Do I need to set CookieDomain?
The reason for users logging off is because of error in validation of forms-authentication data and view-state data. It could happen for different reasons including using web farm in hosting services.You should check <machineKey> in your project webconfig. Check here for details about that. If you don't have<machineKey>in your webconfig, try adding this piece of code after <system.web> in your webconfig:
<machineKey
validationKey="AutoGenerate,IsolateApps"
decryptionKey="AutoGenerate,IsolateApps"
validation="HMACSHA256"
decryption="Auto"
/>
The other option is using generated ASP.NET Machine Key inside webconfig. There are some online tools which my recommended ones are this and this.

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 + DefaultAuthenticationTypes.ApplicationCookie + Windows Authentication

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?

Resources