aspnetcore
aspnetcore copied to clipboard
Cookie configuration mystery using `AddCookie` and `ConfigureApplicationCookie`
I am confused how to set the cookie options, it seems some options are effective only if set using AddCookie and some others if set using ConfigureApplicationCookie. For example,
LoginPathwould be effective only if set inAddCookie:
services.AddAuthentication(options =>
{
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = CookieAuthenticationDefaults.AuthenticationScheme;
})
.AddCookie(options =>
{
options.LoginPath = "signin";
});
services.ConfigureApplicationCookie(options =>
{
options.LoginPath = "signin";
// No effect; if the setting in `AddCookie` is removed, this will fall back to the default `Account/Login` option.
});
ExpireTimeSpanwould be effective only if set inConfigureApplicationCookie:
services.AddAuthentication(options =>
{
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = CookieAuthenticationDefaults.AuthenticationScheme;
})
.AddCookie(options =>
{
options.ExpireTimeSpan = TimeSpan.FromSeconds(30);
// No effect; if the setting in `ConfigureApplicationCookie` is removed, this will fall back to the default timespan.
});
services.ConfigureApplicationCookie(options =>
{
options.ExpireTimeSpan = TimeSpan.FromSeconds(30);
});
You are mixing and matching things for generic cookie authentication (AddCookie) and things meant for asp.net identity (ConfigureApplicationCookie).
Which auth are you trying to use?
Hi @qui8t. We have added the "Needs: Author Feedback" label to this issue, which indicates that we have an open question for you before we can take further action. This issue will be closed automatically in 7 days if we do not hear back from you by then - please feel free to re-open it if you come back to this issue after that time.
I am trying to use Google authNZ with built-in asp.net identity, without leveraging any external library, so my config reads as the following
services
.AddIdentity<AppUser, IdentityRole>()
.AddEntityFrameworkStores<AccountDbContext>();
services.AddIdentityCore<AppUser>();
services
.AddAuthentication(options =>
{
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = CookieAuthenticationDefaults.AuthenticationScheme;
})
.AddJwtBearer()
.AddCookie(options =>
{
options.LoginPath = "/account/login";
options.Cookie.SameSite = SameSiteMode.Lax;
options.Cookie.SecurePolicy = CookieSecurePolicy.Always;
})
.AddGoogle(GoogleDefaults.AuthenticationScheme, options =>
{
options.ClientId = _clientId;
options.ClientSecret = _clientSecret;
options.UsePkce = true;
options.ClaimActions.MapJsonKey(GoogleProfilePictureClaim, "picture", "url");
});
services.ConfigureApplicationCookie(options =>
{
options.ExpireTimeSpan = TimeSpan.FromDays(15);
options.SlidingExpiration = true;
});
And add the following for the middleware setup.
app.UseAuthentication();
app.UseAuthorization();
app.UseCookiePolicy(
new CookiePolicyOptions
{
MinimumSameSitePolicy = SameSiteMode.Lax,
Secure = CookieSecurePolicy.Always
});
Ah got it. @HaoK how does this all hang together?
@qui8t Underneath the covers all ConfigureApplicationCookie is doing is configuring the named cookie that identity sets as the default authentication scheme. Which is the "Identity.Application" cookie scheme. Your app is specifying your own cookie to use by default. Generally if you are not using the application cookie as the default scheme, you don't even to add it.
Basically you should be calling EITHER AddIdentity, or AddIdentityCore. If you call the former, that adds all of the authentication cookies for identity as well. If you call AddIdentityCore, you are responsible for wiring up the authentication part of things, which by default does this:
services.AddAuthentication(o =>
{
o.DefaultScheme = IdentityConstants.ApplicationScheme;
o.DefaultSignInScheme = IdentityConstants.ExternalScheme;
})
.AddIdentityCookies(o => { });
Thank you @HaoK for the elaboration. I removed services.AddIdentityCore<AppUser>();. If I am understanding it correct, I can setup the cookie in ConfigureApplicationCookie, so I changed my code as the following.
services
.AddAuthentication(options =>
{
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = CookieAuthenticationDefaults.AuthenticationScheme;
})
.AddJwtBearer()
.AddCookie( /* config moved to ConfigureApplicationCookie */)
.AddGoogle(GoogleDefaults.AuthenticationScheme, options =>
{
options.ClientId = _clientId;
options.ClientSecret = _clientSecret;
options.UsePkce = true;
options.ClaimActions.MapJsonKey(GoogleProfilePictureClaim, "picture", "url");
});
services.ConfigureApplicationCookie(options =>
{
options.ExpireTimeSpan = TimeSpan.FromDays(15);
options.SlidingExpiration = true;
// moved here from AddCookie()
options.LoginPath = "/account/login";
options.Cookie.SameSite = SameSiteMode.Lax;
options.Cookie.SecurePolicy = CookieSecurePolicy.Always;
});
With this setup, at least options.LoginPath is not configured properly.
What do you mean loginpath is not configured properly? Its not /account/login as you expect? This is likely due to AddIdentity stomping on it. If you want to configure the cookies yourself, a better alternative might be to remove the call to AddIdentity and keep AddIdentityCore, and don't use any of the built in identity cookies, then you have full control over the authentication/cookies and you won't have to deal with stomping on cookie settings.
I want the user to be redirected to the "/account/login" page if the cookie has expired or they requested a protected resource while they are not authenticated yet. With the setup in my previous post, this does not happen. With the setup in my first post, this happens.
I suggest not using the identity application cookies and configuring the cookie completely yourself rather than mixing and matching your own cookies with the identity cookies
I'd love to avoid mixing, though I am trying to remark upon the fact that I can not implement the use-case I mentioned without mixing and matching them. It seems some functionality is available in one and some in the other. Please refer to my first post, and I am happy to elaborate if needed.
services
As my understanding, you should remove .AddIdentity<AppUser, IdentityRole>() and replace with .AddIdentityCore<AppUser> instead, then try your login path again.
This issue has been resolved and has not had any activity for 1 day. It will be closed for housekeeping purposes.
See our Issue Management Policies for more information.