ASP .NET Core Cookie Authentication expiration changes from timestamp to "Session" upon return - asp.net

I am using ASP .NET Core RC1 with Facebook-authentication and silding window cookie expiration set up like this:
app.UseIdentity();
app.UseFacebookAuthentication();
and
services.AddIdentity<ApplicationUser, IdentityRole>((options =>
{
options.Cookies.ApplicationCookie.CookieName = "myauthcookie";
options.Cookies.ApplicationCookie.ExpireTimeSpan = TimeSpan.FromDays(5);
options.Cookies.ApplicationCookie.SlidingExpiration = true;
}))
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();
This works fine when the user first logs in - the cookie expiration is set correctly. However, when the user returns to the page, the expiration of the cookie is set to "Session", so in practice the user has to re-authenticate every other visit.
Why is this happening? Have I not configured it correctly?
Update:
I have now done some testing without SlidingExpiration, and the issue remains the same. Upon returning to the page, the expiration of the cookie is changed to "Session". I am using Chrome.
Also, I am not running on https. Might this be a factor?

Short Answer
Set isPersistent: true when calling SignInManager.ExternalLoginSignInAsync.
Details
In the ASP.NET Core Web Application template, the AccountController.ExternalLoginCallback method contains this code:
_signInManager.ExternalLoginSignInAsync(
info.LoginProvider,
info.ProviderKey,
isPersistent: true); <------ set a persistent cookie.
If we set isPersistent: true when calling ExternalLoginSignInAsync , this startup configuration...
services.AddIdentity<ApplicationUser, IdentityRole>(options =>
{
options.Cookies.ApplicationCookie.CookieName = "MyApplicationCookie";
options.Cookies.ApplicationCookie.ExpireTimeSpan = TimeSpan.FromDays(5);
options.Cookies.ApplicationCookie.SlidingExpiration = true;
})
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();
...results in this application cookie...
...which persists across browser sessions.

Related

.Net Core 6 Can't get Claims after authenticated by ADFS

I recently got a problem about authenticated by ADFS
In dot net core 6, below is my scenario.
I got one Web-Api site host on IIS in server 2019, and an ADFS server
Web -Api domain like https://xxx.domain.com
ADFS one like https://ooo.domain.com
I use WS-federation in my program
both browsers can't get value, edge and chrome
setting is
services.AddAuthentication(sharedOptions =>
{
sharedOptions.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
sharedOptions.DefaultChallengeScheme = WsFederationDefaults.AuthenticationScheme;
}).AddWsFederation(options =>
{ options.MetadataAddress = "my adfs url/FederationMetadata/2007-06/FederationMetadata.xml";
options.Wreply = "https://my webpai url/checkstate";
options.CallbackPath = "/checkstate";
options.BackchannelTimeout = TimeSpan.FromMinutes(1);
options.RemoteAuthenticationTimeout = TimeSpan.FromMinutes(15);
})
.AddCookie();
web-api
signin action for auth and will redirect to adfs server login page
and auth back to the checkstate action this part are work very well.
But I can't Get the value what I want.
In my understanding use the ws-federation(Microsoft.AspNetCore.Authentication.WsFederation6.0.3)
don't need to fetch other service for parse the value.
whole workflow should like this
Users fetch the Api => auth => adfs login => success and get adfs shared value in cookies
=> back to the callback action => get value in action and do something.
When I opened the Dev tools, I can see the real flow like
Signin 302 =>adfs 200 this with a lot cookies
prefix and key is "MSISAUTH"
=> checkstate 200 but, no cookies
I already contact with the ADFS server cruise member and got response said
"We done every setting and it's look fine. "
My question is Did I miss some key-part ?
and is any misunderstanding on workflow?
[Authorize]
[HttpGet("signin")]
public IActionResult Signin()
{
return new EmptyResult();
}
[HttpPost("checkstate")]
public IActionResult CheckState()
{
var name = User.Claims.FirstOrDefault(x=>x.Type == ClaimTypes.Name)?.Value;
return Ok($"Name:{name}");
}
My question is Did I miss some key-part ?
and is any misunderstanding on workflow?
How can I get the Claims value ?

Asp.Net Core - Prevent Session cookie conflict between same domain applications

I'm using ASP.Net Core 2.2.
By default, session cookie is stored in a cookie named .AspNetCore.Session on a specific domain (e.g: mydomain.com).
In my case I have multiple .net core applications under the domain. mydomain.com/Module1, mydomain.com/Module2, etc...
With this scenario, all the applications share the same cookie for their session. The consequence is that an application try to read the session of the other and generate a warning in the logs:
Error unprotecting the session cookie.
System.Security.Cryptography.CryptographicException: The key {...} was not found in the key ring.
Although It's just a warning and session seems to working fine on each application, I wanted to know the proper way to handle this situation.
Thx.
A solution that I've found is to change the session cookie name for each application:
In Startup / Configure() :
app.UseSession(new SessionOptions() { Cookie = new CookieBuilder() {
Name = ".AspNetCore.Session.MyApp1"}});
When you have .AddAuthentication defined in Startup / ConfigureServices(), to fix this add cookie options this way. Worked for my case.
services.AddAuthentication(CookieScheme) // Sets the default scheme to cookies
.AddCookie(CookieScheme, options =>
{
options.LogoutPath = "/logout";
options.LoginPath = "/login";
options.Cookie = new CookieBuilder()
{
IsEssential = true,
SameSite = SameSiteMode.Lax,
SecurePolicy = CookieSecurePolicy.SameAsRequest,
Name = ".AspNetCore.Session.yourAppName"
};
});

ASP.NET Core AntiforgeryToken cookie is set to 1969 as expiration time

I have setup an authentication using simply cookies. Somehow I saw in Application tab of Chrome that antiforgery token cookie expiration time is set to 1969, 31st December.
In ConfigureServices I have:
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme).AddCookie(opts =>
{
var ts = TimeSpan.FromMinutes(30);
opts.Cookie.HttpOnly = true;
opts.Cookie.Expiration = ts;
opts.Cookie.SecurePolicy = CookieSecurePolicy.SameAsRequest;
opts.LoginPath = new PathString("/User/Authenticate");
opts.ExpireTimeSpan = ts;
opts.Cookie.MaxAge = ts;
opts.Validate();
});
and in Configure
app.UseCookiePolicy();
app.UseAuthentication();
Does it is a security concern ? Can that token be bypassed ? I didn't find any article related to antiforgery token default expiration date.
Setting the date of a cookie to a time in the past (or minimum time) is a very common technique of telling the browser to delete a cookie. You should not be concerned.

ASP.Net External Cookie with Sliding Expiration appearing as a Session cookie

I am trying to configure a sliding expiration cookie in Asp.Net. I am expecting the cookie to appear in the Google Chrome developer tools cookie manager with an expiration date 5 minutes after authentication, but it shows as "Session" and never expires until the sign-out button is clicked. It does go away if the browser is closed.
Below is the code as it currently stands. The website uses Saml based Single-Sign-On authentication with Kentor.AuthServices nuget package (now known as SustainSys.Saml2, we are behind in versions).
app.CreatePerOwinContext(ApplicationDbContext.Create);
app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
app.CreatePerOwinContext<ApplicationSignInManager>(ApplicationSignInManager.Create);
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
LoginPath = new PathString("/signin"),
CookieSecure = CookieSecureOption.SameAsRequest,
ExpireTimeSpan = TimeSpan.FromMinutes(5),
SlidingExpiration = true,
Provider = new CookieAuthenticationProvider
{
OnApplyRedirect = ctx => { },
OnResponseSignIn = context =>
{
context.Properties.AllowRefresh = true;
context.Properties.ExpiresUtc = DateTimeOffset.UtcNow.AddMinutes(5);
}
}
});
app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);
Kentor.AuthServices.Configuration.Options.GlobalEnableSha256XmlSignatures();
The OnResponseSignIn block was recently added based on this MSDN answer:
https://forums.asp.net/t/2121970.aspx?OWIN+Authentication+ExpireTimeSpan+not+working
I want the cookies to expire in a 30-minute inactive period. The above code is set to 5 for ease of testing.
The developer tools show the cookie expiration time. This is not directly related to the authentication token expiration time, which should in fact be correct for your code too.
As indicated by this comment "The expiration information is stored in the protected cookie ticket". The token expiration time should take effect properly, even if you cannot see it in the developer tools as it's encrypted inside the cookie itself.

How do I issue the corresponding Bearer and Cookie identity in ASP.NET with multiple Authorization schemes?

This documentation describes in part how to use more than one authentication scheme:
In some scenarios, such as Single Page Applications it is possible to end up with multiple authentication methods. For example, your application may use cookie-based authentication to log in and bearer authentication for JavaScript requests. In some cases you may have multiple instances of an authentication middleware. For example, two cookie middlewares where one contains a basic identity and one is created when a multi-factor authentication has triggered because the user requested an operation that requires extra security.
Example:
app.UseCookieAuthentication(new CookieAuthenticationOptions()
{
AuthenticationScheme = "Cookie",
LoginPath = new PathString("/Account/Unauthorized/"),
AccessDeniedPath = new PathString("/Account/Forbidden/"),
AutomaticAuthenticate = false
});
app.UseBearerAuthentication(options =>
{
options.AuthenticationScheme = "Bearer";
options.AutomaticAuthenticate = false;
});
However it only describes how to use Bearer or Cookie auth. What isn't clear is what other combinations are valid, or how to properly issue bearer or cookies to the client.
How can that be accomplished?
One common use case for this which large sites like Facebook, Google etc. use is to use multiple cookie authentication middleware's and set one of them to be the default using AutomaticAuthenticate
app.UseCookieAuthentication(new CookieAuthenticationOptions()
{
AuthenticationScheme = "InsecureLongLived",
LoginPath = new PathString("/Account/Unauthorized/"),
AccessDeniedPath = new PathString("/Account/Forbidden/"),
AutomaticAuthenticate = true
});
app.UseCookieAuthentication(new CookieAuthenticationOptions()
{
AuthenticationScheme = "SecureAndShortLived",
LoginPath = new PathString("/Account/Unauthorized/"),
AccessDeniedPath = new PathString("/Account/Forbidden/"),
AutomaticAuthenticate = false
});
The default one is long lived and used for non-critical auth scenarios e.g. on Facebook, this may be to view your profile page.
The more secure and short lived on is used for security critical user actions like changing your password or profile information.
This gives you the convenience of not having to login all the time with a long lived cookie but as soon as you need to do something potentially dangerous, you switch to doing auth with a much shorter lived and thus more secure cookie which requires the user to login again.

Resources