AspNet Core Identity, how set options.Cookie.SameSite? - c#

In the latest templates and libraries used httpsonly flag. How can I turn it off?
This same question is outdated and it did not have full configuration sample:
AspNet Core Identity - cookie not getting set in production

In order to configure the application cookie when using Identity, you can use the ConfigureApplicationCookie method inside your Startup’s ConfigureServices:
// add identity
services.AddIdentity<ApplicationUser, IdentityRole>();
// configure the application cookie
services.ConfigureApplicationCookie(options =>
{
options.Cookie.SameSite = SameSiteMode.None;
});
Since Identity essentially adds cookie authentication under the hood, this is the configure action is the same thing you would normally pass to AddCookie() when configuring cookie authentication. It’s just that since AddIdentity() takes care of setting up authentication for you, the ConfigureApplicationCookie offers a way to adjust the cookie authentication options afterwards.

The answer by #poke did not help me set the value to SameSiteMode.None, atleast not in ASP.NET core 2.1.
Any value you set in configure application cookie is overridden by the MinimumSameSitePolicy setting of the cookie policy middleware.
To prevent the override, set MinimumSameSitePolicy for the UseCookiePolicy extension as SameSiteMode.None.
app.UseCookiePolicy(new CookiePolicyOptions
{
MinimumSameSitePolicy = SameSiteMode.None
});
Then set the actual same site value in the AddCookie extension in the ConfigureServices method
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
.AddCookie(options =>
{
options => options.Cookie.SameSite = SameSiteMode.None;
});

For my case in asp.net core 3.1 two things in combination did the trick
services.ConfigureApplicationCookie(options =>
{
options.Cookie.SameSite = SameSiteMode.Unspecified;
});
services.AddAntiforgery(opts => {
opts.Cookie.SameSite = SameSiteMode.Unspecified;
});

Related

How to increase session timeout in .net core 5

I have tried to extend the session timeout in my .net core 5.0 application but it seems the application has a default or an overriding method that enables session timeout to less than 30 minutes.
The below are where I have tried configuring the session timeout.
services.ConfigureApplicationCookie(options =>
{
// Cookie settings
options.Cookie.HttpOnly = true;
options.ExpireTimeSpan = TimeSpan.FromHours(48);
options.LoginPath = "/Account/Login";
options.LogoutPath = "/Account/Logout";
options.AccessDeniedPath = new PathString("/Administration/AccessDenied");
options.SlidingExpiration = true;
});
services.AddSession(options =>
{
options.IdleTimeout = TimeSpan.FromHours(48);
options.Cookie.IsEssential = true;
});
What is it am I doing wrong.
Kindly assist.
I test your showing codes which should be working, here is the test result: You can see from the picture, the expire time of session is working
So maybe you can try these steps to check what cause your issue:
Make sure you are adding the app.UseSession(); in the Startup.cs
Check that there are no other places in your code where the session timeout is being set as a shorter time. For example, if you have a middleware that sets the lower session timeout, it could be overriding your configuration.
Check that the session middleware is being added after the authentication middleware. The authentication middleware sets its own timeout, and if the session middleware is added before it, it will use that value instead.
Or maybe you can share more information of your project and we can check what may cause your issue.

SIgn-in error in .NET 6 web application using Microsoft Identity (aka: Azure Active Directory)

I'm trying to use Microsoft Identity (formerly: Azure AD) authentication in an ASP.NET web application running on .NET 6
I've used this code to configure authentication in my startup class ConfigureServices method:
services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApp(options => {
options.Instance = appSettings.UserSettings.AzIdInstance;
options.Domain = appSettings.UserSettings.AzIdDomain;
options.TenantId = appSettings.UserSettings.AzIdTenantId;
options.ClientId = appSettings.UserSettings.AzIdClientId;
options.CallbackPath = appSettings.UserSettings.AzIdCallbackPath;
options.SignedOutCallbackPath = appSettings.UserSettings.AzIdSignOutCallbackPath;
});
services.AddAuthorization();
Then in the Configure method, I've added:
app.UseAuthentication();
app.UseAuthorization();
When I try to access a controller action protected by the [Authorize] attribute, it correctly redirects me to the microsoft login page, however after I log in when the app then tries to redirect to my callback path (/signin-oidc) the connection gets reset and I get this browser error:
What am I doing wrong here? Is there a good example online on how to properly configure this?
Apparently, this error was happening because I had set the cookie's SameSite attribute to None with this code (I need it to be None for some cross-domain calls that are done to the server):
services.Configure<CookieAuthenticationOptions>(CookieAuthenticationDefaults.AuthenticationScheme, options =>
{
//In-memory cookie store, so sessions are forcibly killed when the webapp restarts
//This ensures that the user's Claims are up to date - remember to restart the service when Azure AD security group memberships are changed!
options.SessionStore = services.BuildServiceProvider().GetService<MemoryCacheTicketStore>();
//We want to disable the same-site policy, otherwise cross-domain API calls from JS won't work
options.Cookie.SameSite = SameSiteMode.None;
});
apparently this by itself causes the error. To fix it, I had to also add the following code:
services.Configure<CookiePolicyOptions>(options =>
{
options.CheckConsentNeeded = context => true;
options.HandleSameSiteCookieCompatibility(s => false);
options.MinimumSameSitePolicy = SameSiteMode.None;
});
this seems to have fixed the problem.

App.UseSession() vs App.UseAuthentication(CookieAuthenticationDefaults.AuthenticationScheme) vs App.UseCookiePolicy()

As described in https://learn.microsoft.com/en-us/aspnet/core/fundamentals/app-state?view=aspnetcore-3.1#session-state , one can add session to one's web app like so in Start.ConfigureServices
services.AddSession(options =>
{
options.IdleTimeout = TimeSpan.FromSeconds(10);
options.Cookie.HttpOnly = true;
options.Cookie.IsEssential = true;
});
and in Startup.Configure
App.UseSession()
There is also the possibility to use cookie authentication without identity via the authentication middleware, as described here https://learn.microsoft.com/en-us/aspnet/core/security/authentication/cookie?view=aspnetcore-3.1
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
.AddCookie(options =>
{
...
});
My question is, if I, in Startup.Configure, use both
App.UseSession()
App.UseAuthentication()
Which Cookie settings will be used? Will the Cookie settings in services.AddSession be completely irrelevant (because the Authentication middleware also uses Session Cookies to keep track of users, right? Or am I completely wrong about that)? Or will they just be two different sessions/services running at the same time?
I am aware that Startup.Configure (the HTTP pipeline) is order-sensitive, as described my Microsoft "Adding the middleware to the app processing pipeline is order sensitive—it only affects downstream components registered in the pipeline." My second question is thus, if I put App.UseCookiePolicy(options) before the above, would it override the settings?
App.UseCookiePolicy()
Thanks in advance for any answers!

ASP.NET core, change default redirect for unauthorized

I am attempting to redirect to a different login url in ASP.NET MVC6
My account controller login method has a Route attribute to change the url.
[HttpGet]
[AllowAnonymous]
[Route("login")]
public IActionResult Login(string returnUrl = null)
{
this.ViewData["ReturnUrl"] = returnUrl;
return this.View();
}
When attempting to access an unathorized page, I am redirected to the invalid url, it should just be /login but instead I get
http://localhost/Account/Login?ReturnUrl=%2Fhome%2Findex
I have configured the cookie authentication path as follows:
services.Configure<CookieAuthenticationOptions>(opt =>
{
opt.LoginPath = new PathString("/login");
});
I have added a default filter, to ensure that all urls require authentication by default.
services.AddMvc(
options =>
{
options.Filters.Add(new AuthorizeFilter(new AuthorizationPolicyBuilder().RequireAuthenticatedUser().Build()));
});
I have checked that the url /login does in fact load the login page, whilst /account/login does not, as expected.
edit: I have left the routes as is, (apart from changing the default controller and action)
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Site}/{action=Site}/{id?}");
});
With asp.net core 2.0 out now, this has changed to:
services.ConfigureApplicationCookie(options => options.LoginPath = "/Account/LogIn");
More on migrating to 2.0 here. And even more information on migrating from 2.0 to 2.1.
If you check UseIdentity extension method here you will notice that it is using IdentityOptions not CookieAuthenticationOptions, so instead you must configure IdentityOptions:
services.Configure<IdentityOptions>(opt =>
{
opt.Cookies.ApplicationCookie.LoginPath = new PathString("/login");
});
Edit
For asp.net core 2.0:
Identity cookie options are no longer part of IdentityOptions. Check mxmissile's answer.
Since asp.net core 2.0 if you use cookies without Identity:
app.UseAuthentication();
// If you don't want the cookie to be automatically authenticated and assigned HttpContext.User,
// remove the CookieAuthenticationDefaults.AuthenticationScheme parameter passed to AddAuthentication.
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
.AddCookie(options =>
{
options.LoginPath = "/Account/LogIn";
options.LogoutPath = "/Account/LogOff";
});
source
You may also want to try using StatusCodePages:
app.UseStatusCodePages(async contextAccessor =>
{
var response = contextAccessor.HttpContext.Response;
if (response.StatusCode == (int)HttpStatusCode.Unauthorized ||
response.StatusCode == (int)HttpStatusCode.Forbidden)
{
response.Redirect("/Error/Unauthorized");
}
});
You'll need to configure this in startup.cs when adding the authentication service especially if you're using cookie authentication scheme.
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
.AddCookie(options =>
{
options.LoginPath = new PathString("/login");
});
This was how i solved the issue, you'll should try it out...It'll definitely work for you
UPDATE:
As of dot net core 2.1.x, Identity is scaffolded from the SDK.
To co--sign #mxmissile answer, the path can be specified. To pull off a trick path, combine with advanced routing or redirects.Scaffold Identity
I wouldn't recommend Serj Sagan solution in a real life example. This would work perfectly when developing but for a real application used by different types of user that might be misleading. Lets look at the below scenario
I am authenticated used
I know the url for a specific page
I am not authorize to access that pages
It means that I would be redirected to the login page as if I were not authenticated which is not the case. I would go more with mxmissile solution
Personnally I am using the AddMvcCore but you need to add AddRazorViewEngine if you are using razor views and AddRazorPages if you are using razor pages
services.AddMvcCore(options =>
{
var policy = new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.Build();
options.Filters.Add(new AuthorizeFilter(policy));
})
.AddRazorViewEngine()
.AddAuthorization()
.AddJsonFormatters();

How to protect all controllers by default with bearer token in ASP.NET Core?

I have added a JWT middleware to my application:
app.UseJwtBearerAuthentication(options => { options.AutomaticAuthenticate = true;} )
Ideally what I want to achieve is that all controller actions are protected by default (there were filters for that in previous ASP.NET), and I will put Anonymous on those that I want public or perhaps Authorize("SomePolicy") if I want additional policies, but I want that without a token the API cannot be accessed at all. How do I do this in the ASP.NET Core?
Starting with .Net 6 we can do this (if using minimal hosting model recommended by Microsoft):
app
.MapControllers()
.RequireAuthorization(); // This will set a default policy that says a user has to be authenticated
Starting with .Net Core 3 we can do this:
app.UseEndpoints(endpoints =>
{
endpoints
.MapControllers()
.RequireAuthorization(); // This will set a default policy that says a user has to be authenticated
});
It is possible to change default policy or add a new policy and use it as well.
P.S. Please note that even though the method name says "Authorization", by default it will only require that the user is Authenticated. It is possible to add more policies to extend the validation though.
You can still use filters as in this example:
services.AddMvc(config =>
{
var policy = new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.Build();
config.Filters.Add(new AuthorizeFilter(policy));
});
The policy in this example is very simple but there a lots of ways to configure a policy for various requirements, roles etc.
The below example worked for me when using .NET 5, the accepted answer doesn't seem to work for .NET 5
services.AddMvc(config => {
config.Filters.Add(new AuthorizeFilter());
});
There exist a lot of solutions will tell you two of them:-
//First one
builder.Services.AddControllers(opts =>
{
opts.Filters.Add(new AuthorizeFilter());
});
//Second one
builder.Services.AddAuthorization(opts =>
{
opts.FallbackPolicy = new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.Build();
});

Categories

Resources