Owin CookieDomain IIS7 and SSL - c#

I am having a problem with setting up SSO between our apps, In the application that creates the cookie I have:
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
LoginPath = new PathString("/Account/Login"),
// LogoutPath = new PathString("/Account/Logout"),
// ExpireTimeSpan = TimeSpan.FromDays(1),
CookieName = "mycookie",
CookieDomain = ".mydomain.com",
});
When testing this locally I get the result I expect
Cookie = Name: mycookie, Domain: .mydomain.com
However when I go to our test environment I get
Cookie = Name: mycookie, Domain: oauth.mydomain.com
Since the cookie has the root of the domain it does not work in the other applications. I have done everything I can think of but it just does not seem to want to use the domain specified in the configuration.
Update: It appears this is a problem when hosting from an IIS7 environment when using SSL. When not using SSL in IIS7 or when deployed to our UAT enviroment with IIS8 it works as expected.
When using SSL it is also not redirecting correctly. I think this problem is also related.
When I hit http://site.domain.com I am redirected to
http://auth.domain.com/account/login?returnUrl=site.domain.com
as expected, however If SSL is enabled I am redirected to
https://site.domain.com/account/login?returnurl=site.domain.com

So It looks like the problem is happening within a firewall/proxy those servers sit behind.

Related

Shared cookie authentication not authenticating on server

When deploying two applications (one .net 4.6 the other .net core 2.2) that share an authentication cookie to a web farm environment, the "receiving" app does not authenticate. We have a very large web forms application that we are trying to eventually migrate to .net core, so for now we are handling the authentication in the web forms app and trying to share that authentication with the .net core app. We have upgraded the authentication in the web forms app to OWIN/Katana cookie based authentication. The apps are deployed on the same servers under the same site (server.com/app1 server.com/app2). Everything works fine locally, you sign in on one and move to the other and you are still logged in. When we deploy to our servers, which are load balanced, the .net core app receives the cookie, but isAuthenticated is false.
I have been able to manually decrypt the cookie in the .net core app and it is able to print out the claims contained within it, but the IsAuthenticated flag is still false. I've tried changing the cookie domain, cookie path, security policy, and authentication type with no success.
Web Forms app Startup.cs:
var provider = DataProtectionProvider.Create(new DirectoryInfo(System.Configuration.ConfigurationManager.AppSettings["KeyRingLocation"]),
(builder) => {
builder.SetApplicationName("sharedApp");
builder.PersistKeysToFileSystem(new DirectoryInfo(System.Configuration.ConfigurationManager.AppSettings["KeyRingLocation"]));
});
IDataProtector protector = provider.CreateProtector(
"Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationMiddleware",
"Identity.Application",
"v2");
app.UseCookieAuthentication(new Microsoft.Owin.Security.Cookies.CookieAuthenticationOptions
{
CookieName = ".AspNet.SharedCookie",
LoginPath = new PathString("/Login.aspx"),
CookiePath = "/",
AuthenticationType = "Identity.Application",
CookieSecure = Microsoft.Owin.Security.Cookies.CookieSecureOption.Always,
CookieDomain = System.Configuration.ConfigurationManager.AppSettings["CookieDomain"],
TicketDataFormat = new AspNetTicketDataFormat(new DataProtectorShim(protector)),
CookieManager = new ChunkingCookieManager()
});
.net core app Startup.cs:
services.AddDataProtection()
.SetApplicationName("sharedApp")
.PersistKeysToFileSystem(new DirectoryInfo(Configuration.GetSection("KeyRingLocation").Value));
services.AddAuthentication("Identity.Application")
.AddCookie("Identity.Application", options =>
{
options.Cookie.Name = ".AspNet.SharedCookie";
options.Cookie.Domain = Configuration.GetSection("CookieDomain").Value;
options.Cookie.Path = "/";
options.Cookie.SecurePolicy = CookieSecurePolicy.Always;
});
web forms login code:
...
var auth = Context.GetOwinContext().Authentication;
var identity = new ClaimsIdentity("Identity.Application");
identity.AddClaim(new Claim(ClaimTypes.Name, profile.UserName));
...
auth.SignIn(identity);
There are no errors being thrown so it is really hard to figure out what the issue is. I would expect it to respect the authentication cookie as it does running locally, but the user identity is null and isAuthenticated is false.

ASP.NET Identity 2 - logout not working when sign in on foo.com and logout on username.foo.com

I'm working on a multi tenant web application and primarily using .NET Framework 4.6 (MVC and ASP.NET Identity 2.0). Here's my implementation:
User visits foo.com to login. I am using following code in foo.com Startup.Auth.cs:
var cookieOptions = new CookieAuthenticationOptions
{
AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
LoginPath = new PathString("/account/login"),
CookieDomain = ".foo.com"
};
app.UseCookieAuthentication(cookieOptions);
And exact same machine key on both applications (foo.com as well as username.foo.com), here's my sample machine key:
<machineKey validationKey="xx" decryptionKey="xx" validation="SHA1" decryption="AES" />
To login i'm using following code:
signInManager.SignIn(user, isPersistent: false, rememberBrowser: false);
My other application username.abc.com is multi tenant, i.e. username can be anything. I'm using below code in username.abc.com Startup.Auth.cs:
var cookieOptions = new CookieAuthenticationOptions
{
ReturnUrlParameter = "redirectto",
AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
LoginPath = new PathString("/account/login")
};
app.UseCookieAuthentication(cookieOptions);
Notice, i'm not using cookies domain, because it can be anything or maybe user has started using his own domain (let's consider user is still using foo.com subdomain).
With this code, user is successfully login and redirected on his username.foo.com, but as soon as he clicks on logout on username.foo.com, page just reloads and nothing happens. Here's what i'm using in logout action:
authenticationManager.SignOut(DefaultAuthenticationTypes.ApplicationCookie);
//authenticationManager.SignOut();
We have another option to login and logout from username.foo.com too, so when user login directly from username.foo.com, he can logout successfully. Issue occurring only when user login from foo.com.
From infrastructure point, foo.com is not load balanced but username.foo.com is running through load balancer (on production). But i don't think this will be issue, because i'm running both applications on single staging environment with same issue.
I tried custom CookieAuthenticationProvider implementation also, but it has similar issue.
Please help.
You can not change a cookie for .foo.com from username.foo.com. It's in the RFC2109.
4.3.2 Rejecting Cookies
A Set-Cookie from request-host y.x.foo.com for Domain=.foo.com
would be rejected, because H is y.x and contains a dot.
You must change your workflow. you can redirect your users to foo.com with redirect_url in order to signout and after successful signout redirect them to redirect_url which is in username.foo.com.

Session cookie still authenticates after app pool recycle

My ASP.NET MVC websites are staying signed in when I don't believe they should be.
My web server is IIS 7.5 and the app pool is V4.0 Integrated with idle-timeout set to 20 mins.
When logging in, the website saves an auth cookie that expires "When the browsing session ends" (persistence set to false).
If I close the browser (Chrome or FF) and then recycle (or stop/start) the app pool on IIS on the server, then reopen the browser, then session cookie still appears to be valid.
I know that Firefox and Chrome don't delete session cookies when you close the browser (so you can start where you left off), but surely the session doesn't exist on the server anymore, since the app pool has recycled? I'm not saving session data to a database, and don't have machine id's setup in my web.config.
Why is this cookie still valid?
Edit 1 - how is the cookie set
Cookie auth options are set by ConfigureAuth (called from the Configuration method in my OWIN Startup class). Cookie options:
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
CookieName = "MyCookieName",
AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
LoginPath = new PathString("/Account/Login"),
SlidingExpiration = true,
ExpireTimeSpan = TimeSpan.FromDays(7) // this only applies if persistent is true!
});
The user is signed in using
await SignInManager.SignInAsync(user, isPersistent, rememberBrowser);
isPersistent is set from the "Remember me" check box on the login form. If this is checked then the cookie expires using the ExpireTimeSpan from the CookieAuthenticationOptions. If it's not checked, the the cookie expires "When the browsing session ends", which is where my question lies.
rememberBrowser is set to false - this is used for 2FA which is not used in my implementation.
SignInAsync is the default implementation, which calls:
AuthenticationManager.SignIn(new AuthenticationProperties()
{
IsPersistent = isPersistent
}, userIdentity);
...which is again the default implementation.
The AuthenticationManager takes care of setting the actual cookie (I believe).
Edit 2 - machineKey?
Having looked into this further, it's possible that a machine key is being stored to the cookie, allowing it to authenticate across pool recycles. I have not defined a machineKey in the web.config, so I'm not sure this is correct.
IIS identifies applications with a machine key that stays the same across app pool recycles. This is stored in the authentication cookie so that users can be authenticated across app pool recycles.

OWIN Cookie authentication not working on IIS 8.5

I have developed an ASP.NET webapp with OWIN authentication, which works fine on my development machine (Windows 10/IIS 10), but when the webapp is published to my Windows 2012 server with IIS 8.5, the cookie authentication does not seem te work.
When I login (with the IsPersistent setting to true) and close the browser, I am still logged on when I start my browser again, so that's OK. But when I restart IIS and startup the browser, I have to logon again.
I have created a very simple application to test this, with the following code:
Startup.cs
public void ConfigureAuthentication(IAppBuilder app)
{
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
LoginPath = new PathString("/Login"),
CookieName = "ThisIsTheAuthCookie"
});
}
AuthenticationController.cs
public ActionResult Login(string userName, string password)
{
//For testing purposes every user/pwd is fine
var identity = new ClaimsIdentity(new [] { new Claim(ClaimTypes.Name, userName), },
DefaultAuthenticationTypes.ApplicationCookie,
ClaimTypes.Name, ClaimTypes.Role);
HttpContext.GetOwinContext().Authentication.SignIn(new AuthenticationProperties { IsPersistent = true }, identity);
return RedirectToAction("index", "home");
}
Even Chrome shows the cookie, but it looks like OWIN is not using it on IIS 8.5:
Does anybody have an idea what the problem is?
Thx,
Danny
Can you try a couple of things and share the results :-
1. Restart the IIS , keeping the User-Agent. See if you are logged in now.
2. Enable logging in Katana and check for this warning/error in the logs.
Any result on this already?
For me it looks like you have the cookie with the session ID available but the IIS server is not aware anymore on this session. Are you sure you persist the session on the IIS server? (and not 'In Process')
You can find the option under Session State in the IIS configuration. See TechNet Article IIS
The problem is solved. I had to add the MachineKey element in the web.config!

MVC client can't authenticate on IIS

I've succeeded with IdentityServer3 implementation. I created ASP.NET MVC5 client with implicit flow and this Owin startup configuration:
app.UseCookieAuthentication(new CookieAuthenticationOptions
{ AuthenticationType = "Cookies" });
app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
{
ClientId = "mvc.client",
Authority = Constants.ServerUri,
RedirectUri = Constants.MvcClientUri,
ResponseType = "id_token",
Scope = "openid profile",
UseTokenLifetime = false,
SignInAsAuthenticationType = "Cookies",
Notifications = new OpenIdConnectAuthenticationNotifications
{ SecurityTokenValidated = TokenValidatedNotification },
});
Everything works perfect running locally on IIS Express, but fails when deployed to production IIS server. Authentication is successful in both cases - id_token is returned from then same IdentityServer, but on production user is never authenticated, notification is not fired. Project references Microsoft.Owin.Host.SystemWeb assembly. I've registered exception handling OwinMiddleware as first one, but no unhandled exception was catched.
Make sure the production IIS has the website configured to use Anonymous authentication, as you are not relying on IIS's authentication infrastructure, you want the request to flow through IIS and get to the OWIN middleware responsible for authentication.

Categories