I'm working on a project whose back-end is built in .NET 3.1 and Angular 11 for the front-end. I'm trying to set the HttpOnly attribute on true for cookies via the Startup method, which is extended by various APIs and Managers through the entire application: so far the current configuration is as follows.
public void ConfigureServices(IServiceCollection services)
{
...
services.Configure<CookiePolicyOptions>(options =>{
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.None;
options.HttpOnly = HttpOnlyPolicy.Always;
options.Secure = CookieSecurePolicy.Always;
});
...
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILoggerFactory loggerFactory)
{
...
app.UseCookiePolicy();
...
}
Anyways, when checking via the Network tab in Chrome/Firefox the HttpOnly flag is not set, what am I missing?
Thanks for any help!
It seems like you need to pass in the cookie policy options you created.
Using this line
services.Configure<CookiePolicyOptions>(options ...
makes the cookie policy available later on but doesn't configure it in your startup.
According to https://learn.microsoft.com/en-us/aspnet/core/security/authentication/cookie?view=aspnetcore-3.1#cookie-policy-middleware-1 you'll need to create a cookie policy and then pass that in to
app.UseCookiePolicy();
Otherwise, it uses the default cookie policy which doesn't have them set to what you would prefer.
Related
I am new is asp.net core
I am trying to create web application using asp.net core 3.1 as per the instruction on link
i created login page which is working, application login is working. so after login 1st user in application i copied the cookies of 1st user to other browser and open localhost site and i saw user got loggedin without authentication.
is this right implementation how to create safe login and authorization module in asp.net core webapp
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(
Configuration.GetConnectionString("DefaultConnection")));
// Add Distributed Redis Cache for Session
services.AddDistributedRedisCache(options =>
{
options.Configuration = "localhost";
options.InstanceName = "Session_";
});
services.AddSession(options =>
{
// 20 minutes later from last access your session will be removed.
options.IdleTimeout = TimeSpan.FromMinutes(20);
options.Cookie.HttpOnly = true;
options.Cookie.IsEssential = true;
});
services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)
.AddEntityFrameworkStores<ApplicationDbContext>();
services.AddRazorPages();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseDatabaseErrorPage();
}
else
{
app.UseExceptionHandler("/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
// Adds session middleware to pipeline
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseSession();
app.UseEndpoints(endpoints =>
{
endpoints.MapRazorPages();
});
}
sample code from link
Let's summarize a few things here:
First of all, if your web application is configured correctly it is not possible to steal someone else's cookie. Unless you're on the same physical machine (which I assume is what you did with when you copied the cookie) of course.
So your site should always be served over HTTPS, that's configured correctly: app.UseHttpsRedirection();. And cookies should be HttpOnly (meaning not accessible by javascript): options.Cookie.HttpOnly = true; (but that's for the session cookie). The cookie that is created by the Identity template is marked as HttpOnly and Secure by default so that's also fine. So basically the answer to your question is 'Yes, the Identity template is safe to use'
As a final comment I would recommend to add app.UseHsts(); to add HSTS headers for more security.
I'm trying to use HttpContext.Session in my asp.net core web application but I'm having trouble. Accessing the session results in InvalidOperationException, with the message "Session has not been configured for this application or request".
I've search around and there some code you have to add to start up i.e adding session and uses it. (I've also added Nuget package AspNetCore.Session).
Now when I try to access Session (HttpContext.Session) in my PageModel code-behind. It throws exception with the message as specified in paragraph above. I can't find any more details aside from you gotta set up in startup code which I've done. My startup code is below:
public void ConfigureServices(IServiceCollection services)
{
services.Configure<CookiePolicyOptions>(options =>
{
// This lambda determines whether user consent for non-essential cookies is needed for a given request.
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.None;
});
services.AddHttpClient();
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
services.AddDistributedMemoryCache();
services.AddSession();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseCookiePolicy();
app.UseSession();
app.UseMvc();
}
Page model on post is how i'm trying to access it:
public async void OnPostAsync()
{
//Some async stuff here.
//Session throws exception
HttpContext.Session.SetString("something", "something");
}
You can't seem to access the static Session via HttpContext, what you need to do is in ConfigurationServices method add services.AddHttpContextAccessor(); This will let you inject IHttpContextAccessor into your page model constructor, this will have session that you setup instead.
Makre sure you set the Session as a member variable in the constructor, as accessing it via HttpSession in the Post method would result in the same problem.
So I followed the guide here (excluding some of the application specific items like Application Insights).
Startup.cs was modified in these two areas:
public void ConfigureServices(IServiceCollection services)
{
services.AddResponseCompression(options =>
{
options.Providers.Add<GzipCompressionProvider>();
options.MimeTypes = ResponseCompressionDefaults.MimeTypes.Concat(new[] { "image/svg+xml" });
});
// Add framework services.
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("DatabaseConnection")));
services.AddDbContext<DatabaseContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("DatabaseConnection")));
services.AddIdentity<ApplicationUser, IdentityRole>()
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();
services.AddResponseCaching();
services.AddMvc();
// Add application services.
services.AddTransient<IEmailSender, AuthMessageSender>();
services.AddTransient<ISmsSender, AuthMessageSender>();
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
app.UseResponseCompression();
app.UseResponseCaching();
loggerFactory.AddConsole(Configuration.GetSection("Logging"));
loggerFactory.AddDebug();
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseDatabaseErrorPage();
app.UseBrowserLink();
}
else
{
app.UseExceptionHandler("/Home/Error");
}
app.UseStaticFiles();
app.UseIdentity();
// Add external authentication middleware below. To configure them please see https://go.microsoft.com/fwlink/?LinkID=532715
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
}
And on various Controllers for pages, I call ResponseCache like this (set it to 2 minutes, not sure if this is what people traditionallly set it to):
[ResponseCache(Duration = 120)]
public IActionResult Index()
{
return View();
}
After deploying to Azure, I can repeatedly hit F5 and still see 200 in network traffic. The goal is to cache CSS, JS, and pages (well, pages that aren't part of [Authorize] managed controllers).
update (of sorts): the unfortunate thing is that I have reviewed quite a few guides on this and it seems they all inherently say the same things (main difference is not relying on the Response Caching Nuget package and going with a hard coded version, same non-results though), but for some reason this doesn't work. In a Web Forms application (2.0 upgraded to 4.0), I was able to achieve this with minimal effort.
When you hit F5, you will always get a new response, bypassing the cache. If instead you try to navigate to a link (...), you will see that the response is indeed cached.
I'm adding Auth0 to simple project and trying to understand how middlewares work.
In my Startup.cs I have this code
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory, IOptions<AuthSettings> auth0Settings)
{
loggerFactory.AddConsole(Configuration.GetSection("Logging"));
loggerFactory.AddDebug();
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseStaticFiles();
// Add the cookie middleware
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AutomaticAuthenticate = true,
AutomaticChallenge = true
});
// Add the OIDC middleware
var options = new OpenIdConnectOptions("Auth0")
{
// here there are some configurations
// .....................
};
options.Scope.Clear();
options.Scope.Add("openid");
options.Scope.Add("name");
options.Scope.Add("email");
options.Scope.Add("picture");
app.UseOpenIdConnectAuthentication(options);
app.UseMvc(routeBuilder =>
{
routeBuilder.MapRoute("Default", "{controller=Home}/{action=Index}");
});
}
If I understand correctly the idea of middleware in ASP.NET Core in our example, if there is a cookie present and authentication can be done by it
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AutomaticAuthenticate = true,
AutomaticChallenge = true
});
OpenId middleware will not be executed.
app.UseOpenIdConnectAuthentication(options);
Could somebody explain me how does OpenId middleware knows that it should not be executed?
At the bottom we have
app.UseMvc(routeBuilder =>
{
routeBuilder.MapRoute("Default", "{controller=Home}/{action=Index}");
});
How does it knows that it should always be executed but in case where we request some static file we do not use mvc.
Every single middleware in the pipeline can choose to call the next middleware. The reason you get static files instead of it hitting an MVC controller is because the static file middleware finds the file requested, and chooses not to call the next middleware in the chain. It simply returns the file as a response.
AutomaticAuthenticate in authentication middleware always means "Inspect the incoming request. If you find something that interests you, create a ClaimsPrincipal from it." In this case cookie authentication automatically creates a principal for the signed-in user when their sign-in cookie is in the request, before passing the request to the next middleware.
The OpenId Connect middleware executes actually, but it doesn't do anything because it won't find anything interesting in the request even if it had AutomaticAuthenticate = true. It is looking for requests to its callback path, which by default is set as CallbackPath = new PathString("/signin-oidc"); in the constructor.
The two authentication middleware are setup like this so that the cookie middleware runs always, but OpenId Connect only redirects to the identity provider when requested (e.g. by returning a ChallengeResult from your MVC controller).
I would like to know how I can add Access-Control-Allow-Origin:* to my headers.
I've tried this unsuccessfully:
app.Use((context, next) =>
{
context.Response.Headers.Add("Access-Control-Allow-Origin", new[] { "*" });
return next.Invoke();
});
Using app.use(...) and mutating context.Response.Headers from within Startup.Configure is correct, but it's important to do it at the right point in the chain. ASP.NET Core middleware components can "short-circuit" (see the ASP.NET Core Middleware docs), preventing further middleware from being called, and by experimenting with it I've inferred that UseMvc() does so. In an MVC application, then, this means you have to put your app.use(...) call before app.UseMvc().
In other words, starting from the template ASP.NET Core 2.0 application that Visual Studio generates for you, you want to modify Startup.Configure in Startup.cs to look something like this:
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
// Add header:
app.Use((context, next) =>
{
context.Response.Headers["Access-Control-Allow-Origin"] = "*";
return next.Invoke();
});
app.UseMvc();
}
I tried your code, and it worked beautifully... Placement is key: I'm pretty sure it needs to be early in the chain.
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
loggerFactory.AddConsole(Configuration.GetSection("Logging"));
loggerFactory.AddDebug();
//app.UseCors(builder => builder.AllowAnyHeader().AllowAnyMethod().AllowAnyOrigin());
app.Use((context, next) => {
context.Response.Headers.Add("Access-Control-Allow-Origin", new[] { "*" });
return next.Invoke();
});
app.UseMvc();
app.UseWebSockets();
app.UseSignalR();
}
You can also try to use the in built CORS Middleware in the asp.net core framework rather than creating your own Middleware.
In Configure method of the Startup class add the following code.
// Add CORS for YourAnotherSite
app.UseCors(builder =>
builder.WithOrigins("http://YourAnotherSite.com"));
OR
Use Named Policies
In Configure method of the Startup class
options.AddPolicy("AllowMyOrigin",
builder => builder.WithOrigins("http://YourAnotherSite.com"));
and then in the ConfigureServices method of the startup class.
app.UseCors("AllowMyOrigin");
Alternatively, the Policy can be applied at each Controller or Action methods.
We've found the ApplicationBuilder methods inconsistent too - it's not clear when the handler is handing back to the chain (for instance UseStaticFiles()) and when it's not (UseMvc()).
You don't say what environment you're running under, but if you're intending on using IIS then don't give up on web.config yet! The url rewrite module works perfectly well, and allows you to set outbound rules on all request.
There's a good answer here: https://stackoverflow.com/a/26545975/548664