CheckMarx Medium severity warning - HttpOnly cookie at Startup - c#

CheckMarx is flagging an error which looks like a false positive to me. Our application is written in C# and uses ASP.NET Core.
The error is:
The web application's Startup method creates a cookie Startup, at line 22 of Startup.cs, and returns it in the response. However, the application is not configured to automatically set the cookie with the "httpOnly" attribute, and the code does not explicitly add this to the cookie.
This is line 22:
public class Startup
And we do have the cookie policy set correctly:
app.UseCookiePolicy(new CookiePolicyOptions
{
HttpOnly = Microsoft.AspNetCore.CookiePolicy.HttpOnlyPolicy.Always
});
But CheckMarx is still flagging this warning. And I do not think that my Startup class creates a cookie called Startup.
I found a similar post here (unanswered) - https://github.com/Azure/azure-functions-vs-build-sdk/issues/469.
So is this a false positive? And how do I get CheckMarx to stop flagging it?

The only way to remove those warnings was to rename the Startup class to something else, for example to Startup123.
Nothing else removes the warning, and I think it is definitely a false positive.

For .NET Core 3.1, I fixed this vulnerability warning by configuring the service in Startup class and then using CookiePolicy middleware.
In ConfigureServices function:
services.Configure<CookiePolicyOptions>(options =>
{
options.Secure = CookieSecurePolicy.Always;
});
In Configure function:
app.UseCookiePolicy();
This could be also used to fix HttpOnlyPolicy vulnerability in middleware like:
services.Configure<CookiePolicyOptions>(options =>
{
options.HttpOnly = HttpOnlyPolicy.Always;
options.Secure = CookieSecurePolicy.Always;
});
Remember to use the correct order for middlewares. You could refer to ASP.NET Core Middleware Docs to read more about and get some examples.

Related

An exception was thrown while deserializing the token. Microsoft.AspNetCore.Antiforgery.AntiforgeryValidationException [duplicate]

I have a form:
#using (Html.BeginForm(new { ReturnUrl = ViewBag.ReturnUrl })) {
#Html.AntiForgeryToken()
#Html.ValidationSummary()...
and action:
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public ActionResult Login(LoginModel model, string returnUrl, string City)
{
}
occasionally (once a week), I get the error:
The anti-forgery token could not be decrypted. If this application is
hosted by a Web Farm or cluster, ensure that all machines are running
the same version of ASP.NET Web Pages and that the configuration
specifies explicit encryption and validation keys. AutoGenerate cannot
be used in a cluster.
i try add to webconfig:
<machineKey validationKey="AutoGenerate,IsolateApps"
decryptionKey="AutoGenerate,IsolateApps" />
but the error still appears occasionally
I noticed this error occurs, for example when a person came from one computer and then trying another computer
Or sometimes an auto value set with incorrect data type like bool to integer to the form field by any jQuery code please also check it.
I just received this error as well and, in my case, it was caused by the anti-forgery token being applied twice in the same form. The second instance was coming from a partial view so wasn't immediately obvious.
validationKey="AutoGenerate"
This tells ASP.NET to generate a new encryption key for use in encrypting things like authentication tickets and antiforgery tokens every time the application starts up. If you received a request that used a different key (prior to a restart for instance) to encrypt items of the request (e.g. authenication cookies) that this exception can occur.
If you move away from "AutoGenerate" and specify it (the encryption key) specifically, requests that depend on that key to be decrypted correctly and validation will work from app restart to restart. For example:
<machineKey
validationKey="21F090935F6E49C2C797F69BBAAD8402ABD2EE0B667A8B44EA7DD4374267A75D7
AD972A119482D15A4127461DB1DC347C1A63AE5F1CCFAACFF1B72A7F0A281B"
decryptionKey="ABAA84D7EC4BB56D75D217CECFFB9628809BDB8BF91CFCD64568A145BE59719F"
validation="SHA1"
decryption="AES"
/>
You can read to your heart's content at MSDN page: How To: Configure MachineKey in ASP.NET
Just generate <machineKey .../> tag from a link for your framework version and insert into <system.web><system.web/> in Web.config if it does not exist.
Hope this helps.
If you get here from google for your own developer machine showing this error, try to clear cookies in the browser. Clear Browser cookies worked for me.
in asp.net Core you should set Data Protection system.I test in Asp.Net Core 2.1 or higher.
there are multi way to do this and you can find more information at Configure Data Protection and Replace the ASP.NET machineKey in ASP.NET Core and key storage providers.
first way: Local file (easy implementation)
startup.cs content:
public class Startup
{
public Startup(IConfiguration configuration, IWebHostEnvironment webHostEnvironment)
{
Configuration = configuration;
WebHostEnvironment = webHostEnvironment;
}
public IConfiguration Configuration { get; }
public IWebHostEnvironment WebHostEnvironment { get; }
// This method gets called by the runtime.
// Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
// .... Add your services like :
// services.AddControllersWithViews();
// services.AddRazorPages();
// ----- finally Add this DataProtection -----
var keysFolder = Path.Combine(WebHostEnvironment.ContentRootPath, "temp-keys");
services.AddDataProtection()
.SetApplicationName("Your_Project_Name")
.PersistKeysToFileSystem(new DirectoryInfo(keysFolder))
.SetDefaultKeyLifetime(TimeSpan.FromDays(14));
}
}
second way: save to db
The Microsoft.AspNetCore.DataProtection.EntityFrameworkCore NuGet
package must be added to the project file
Add MyKeysConnection ConnectionString to your projects
ConnectionStrings in appsettings.json > ConnectionStrings >
MyKeysConnection.
Add MyKeysContext class to your project.
MyKeysContext.cs content:
public class MyKeysContext : DbContext, IDataProtectionKeyContext
{
// A recommended constructor overload when using EF Core
// with dependency injection.
public MyKeysContext(DbContextOptions<MyKeysContext> options)
: base(options) { }
// This maps to the table that stores keys.
public DbSet<DataProtectionKey> DataProtectionKeys { get; set; }
}
startup.cs content:
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime.
// Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
// ----- Add this DataProtection -----
// Add a DbContext to store your Database Keys
services.AddDbContext<MyKeysContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("MyKeysConnection")));
// using Microsoft.AspNetCore.DataProtection;
services.AddDataProtection()
.PersistKeysToDbContext<MyKeysContext>();
// .... Add your services like :
// services.AddControllersWithViews();
// services.AddRazorPages();
}
}
If you use Kubernetes and have more than one pod for your app this will most likely cause the request validation to fail because the pod that generates the RequestValidationToken is not necessarily the pod that will validate the token when POSTing back to your application. The fix should be to configure your nginx-controller or whatever ingress resource you are using and tell it to load balance so that each client uses one pod for all communication.
Update: I managed to fix it by adding the following annotations to my ingress:
https://kubernetes.github.io/ingress-nginx/examples/affinity/cookie/
Name Description Values
nginx.ingress.kubernetes.io/affinity Sets the affinity type string (in NGINX only cookie is possible
nginx.ingress.kubernetes.io/session-cookie-name Name of the cookie that will be used string (default to INGRESSCOOKIE)
nginx.ingress.kubernetes.io/session-cookie-hash Type of hash that will be used in cookie value sha1/md5/index
I ran into this issue in an area of code where I had a view calling a partial view, however, instead of returning a partial view, I was returning a view.
I changed:
return View(index);
to
return PartialView(index);
in my control and that fixed my problem.
I got this error on .NET Core 2.1. I fixed it by adding the Data Protection service in Startup:
public void ConfigureServices(IServiceCollection services)
{
services.AddDataProtection();
....
}
you are calling more than one the #Html.AntiForgeryToken() in your view
I get this error when the page is old ('stale'). A refresh of the token via a page reload resolves my problem. There seems to be some timeout period.
I found a very interesting workaround for this problem, at least in my case. My view was dynamically loading partial views with forms in a div using ajax, all within another form. the master form submits no problem, and one of the partials works but the other doesn't. The ONLY difference between the partial views was at the end of the one that was working was an empty script tag
<script type="text/javascript">
</script>
I removed it and sure enough I got the error. I added an empty script tag to the other partial view and dog gone it, it works! I know it's not the cleanest... but as far as speed and overhead goes...
I know I'm a little late to the party, but I wanted to add another possible solution to this issue. I ran into the same problem on an MVC application I had. The code did not change for the better part of a year and all of the sudden we started receiving these kinds of error messages from the application.
We didn't have multiple instances of the anti-forgery token being applied to the view twice.
We had the machine key set at the global level to Autogenerate because of STIG requirements.
It was exasperating until I got part of the answer here: https://stackoverflow.com/a/2207535/195350:
If your MachineKey is set to AutoGenerate, then your verification
tokens, etc won't survive an application restart - ASP.NET will
generate a new key when it starts up, and then won't be able to
decrypt the tokens correctly.
The issue was that the private memory limit of the application pool was being exceeded. This caused a recycle and, therefore, invalidated the keys for the tokens included in the form. Increasing the private memory limit for the application pool appears to have resolved the issue.
My fix for this was to get the cookie and token values like this:
AntiForgery.GetTokens(null, out var cookieToken, out var formToken);
For those getting this error on Google AppEngine or Google Cloud Run, you'll need to configure your ASP.NET Core website's Data Protection.
The documentation from the Google team is easy to follow and works.
https://cloud.google.com/appengine/docs/flexible/dotnet/application-security#aspnet_core_data_protection_provider
A general overview from the Microsoft docs can be found here:
https://cloud.google.com/appengine/docs/flexible/dotnet/application-security#aspnet_core_data_protection_provider
Note that you may also find you're having to login over and over, and other quirky stuff going on. This is all because Google Cloud doesn't do sticky sessions like Azure does and you're actually hitting different instances with each request.
Other errors logged, include:
Identity.Application was not authenticated. Failure message: Unprotect ticket failed

How to set session idle timeout in C#, .NET 5.0?

Final Update: It turned out that the issue was caused by authentication timeouts rather than session timeouts. These are different things and need to be set separately. Here is the fix I ended up with:
Create a timeout value in appsettings.json. This value will be used to configure session and authorization timeouts. (You can name this whatever you want.)
"IdleTimeoutMinutes": 60,
Set session timeout in Startup.cs.
services.AddSession(options =>
{
options.IdleTimeout = TimeSpan.FromMinutes(Configuration.GetValue<double>("IdleTimeoutMinutes"));
options.Cookie.HttpOnly = true;
options.Cookie.IsEssential = true;
});
Configure authentication timeout in Startup.cs.
services.AddAuthentication(NegotiateDefaults.AuthenticationScheme)
.AddNegotiate()
.AddCookie(CookieAuthenticationDefaults.AuthenticationScheme,
options =>
{
options.LoginPath = new PathString("/Account/Login/LogOn/");
options.AccessDeniedPath = new PathString("/Account/Login/AccessDenied/");
options.SlidingExpiration = true;
options.ExpireTimeSpan = TimeSpan.FromMinutes(Configuration.GetValue<double>("IdleTimeoutMinutes"));
});
Configure authentication cookie timeout in LoginController.cs.
await HttpContext.SignInAsync(
CookieAuthenticationDefaults.AuthenticationScheme, claims.Get(currentUser),
new AuthenticationProperties
{
ExpiresUtc = DateTime.UtcNow.AddMinutes(Configuration.GetValue<double>("IdleTimeoutMinutes")),
IsPersistent = true,
AllowRefresh = true
});
I found this information here: https://www.blakepell.com/blog/asp-net-core-cookie-authentication-timing-out
(Archived page: https://web.archive.org/web/20220411151611/https://www.blakepell.com/blog/asp-net-core-cookie-authentication-timing-out)
Note that the Cookie.Expiration setting described at this link no longer works. It returns a error "Cookie.Expiration is ignored, use ExpireTimeSpan instead". I left out that line and everything else worked.
Update: As a test, I changed the session IdleTimeout value from 30 minutes to 10 seconds and discovered that the session timeout is, in fact, working as expected. There is a different, unknown, timeout that is breaking things after 15 minutes, regardless of the session IdleTimeout value. Where is this 15 minute timeout coming from?
Things that break after IdleTimeout seconds:
HttpContext.Session.GetString(SessionKeySheetData) in .cs code returns a "Value cannot be null" error. This is expected. The session IdleTimeout is working correctly.
Things that break after 15 minutes idle, regardless of the session IdleTimeout value:
JavaScript Ajax calls result in an authentication popup asking for user name and password. This does not occur anywhere else in this application that uses Windows authentication and it does not accept my usual Windows login user name and password. I can work around this by adding a [AllowAnonymous] directive to the relevant code.
Context.Request.Form("<form field id>") in .cshtml code returns a "Incorrect Content-type" error.
Apparently there are two idle timeouts here. The session timeout, controlled by the IdleTimeout value, is working as expected. But there is another timeout of 15 minutes that is not related to the session timeout. Where is this other timeout coming from and how can it be changed?
Original question:
I'm a beginning C# coder and I have been tasked with maintaining an existing web application written in C# with .NET 5.0. The current session timeout seems to be 15 minutes and I would like to increase it. This question has been asked and answered many times, but before flagging this as a duplicate, understand that most of those questions and answers are for older versions of .NET and are not applicable to the current version. Also, nearly everyone has a different answer, and I have not been able to get any of them to work.
The answers I have found fall into four categories:
IIS configuration changes. For development I am using the IIS Express that comes with VS 2019. I have installed the latest IIS Manager app, but nothing I see there matches the answers I find online. I presume those answers are for older versions of IIS, and I do not see any session timeout configuration in the current version of IIS Manager. Example: https://beansoftware.com/ASP.NET-Tutorials/Session-Timeout-Expiration.aspx
Project configuration changes. I have found many, many pages suggesting to set sessionState timeout="<minutes>" in web.config. However my project does not have a web.config and it is my understanding that this is used only in older .NET versions. Example: Session timeout in ASP.NET
Create a JavaScript/Ajax function to keep the session alive by calling a dummy HTTP Handler. I haven't been able to get this to work and it seems like an ugly hack if there is a way to simply change the timeout configuration. Example: Keeping ASP.NET Session Open / Alive
Change the session timeout programmatically. I think this would be a good option if I could get it to work, but adding public TimeSpan IdleTimeout = TimeSpan.Parse("01:00:00"); to the code does not seem to have any effect. Example: https://learn.microsoft.com/en-us/dotnet/api/system.web.configuration.processmodelsection.idletimeout?view=netframework-4.8
Any help would be appreciated.
Edit: Added Startup.cs below, as requested.
using ILawProductionApp.Domain.Context;
using ILawProductionApp.Domain.Helpers.Sheets;
using ILawProductionApp.Domain.Shared.Contracts;
using ILawProductionApp.Domain.Shared.Repository;
using ILawProductionApp.Infrastructure.Contexts;
using ILawProductionApp.Infrastructure.Interfaces;
using ILawProductionApp.Infrastructure.Interfaces.Repositories;
using ILawProductionApp.UI.Areas.Account.Managers.Authorization;
using ILawProductionApp.UI.Helpers;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authentication.Negotiate;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.Authorization;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using System;
namespace ILawProductionApp.UI
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddHttpContextAccessor();
services.AddAuthentication(NegotiateDefaults.AuthenticationScheme)
.AddNegotiate()
.AddCookie(CookieAuthenticationDefaults.AuthenticationScheme,
options =>
{
options.LoginPath = new PathString("/Account/Login/LogOn/");
options.AccessDeniedPath = new PathString("/Account/Login/AccessDenied/");
});
services.AddDbContext<AppIdentityDbContext>(options => options.
UseOracle(Environment.GetEnvironmentVariable(Configuration["EnvironmentVars:DefaultConnectionString"])));
services.AddMvc(config =>
{
var policy = new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.Build();
config.Filters.Add(new AuthorizeFilter(policy));
});
services.AddSingleton<IAuthorizationPolicyProvider, LawPermissionPolicyProvider>();
services.AddScoped<IAuthorizationHandler, RolesAuthorizationHandler>();
services.AddScoped<IAuthorizationHandler, LawPermissionAuthorizationHandler>();
//services.AddScoped<IAuthorizationHandler, ProcessCalApp2AuthorizationHandler>();
//services.AddScoped<IAuthorizationHandler, ProccessGlassAppAuthorizationHandler>();
services.AddDistributedMemoryCache();
services.AddSession(options =>
{
options.IdleTimeout = TimeSpan.FromSeconds(Configuration.GetValue<double>("SessionTimeoutSeconds"));
options.Cookie.HttpOnly = true;
options.Cookie.IsEssential = true;
});
services.AddControllersWithViews().AddSessionStateTempDataProvider();
services.AddDbContext<ApplicationILawDbContext>(options => options.UseLazyLoadingProxies()
.UseOracle(Environment.GetEnvironmentVariable(Configuration["EnvironmentVars:DefaultConnectionString"])));
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
services.AddScoped<IAdminUnitOfWork, AdminUnitOfWork>();
services.AddScoped<IUnitOfWork, UnitOfWork>();
services.AddScoped<ICa2RunUtil, Ca2RunUtil>();
services.AddScoped<ILawGaRunUtil, LawGaRunUtil>();
services.AddTransient<ISheetModifier, SheetModifier>();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/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.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseSession();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "Adminstration",
pattern: "{area:exists}/{controller=Admin}/{action=Index}/{id?}");
endpoints.MapControllerRoute(
name: "Account",
pattern: "{area:exists}/{controller=Account}/{action=Index}/{id?}"
);
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
endpoints.MapRazorPages();
});
}
}
}

CookieAuthentication and AspNet Core 2.0 migration

I can't find a way how to migrate the application from aspnet core 1.1 to 2.0 which is using cookie authentication.
Most useful resources I already know are:
https://learn.microsoft.com/en-us/aspnet/core/migration/1x-to-2x/identity-2x#cookie-based-authentication
https://github.com/aspnet/announcements/issues/262
https://github.com/aspnet/Home/issues/2128 (my own question)
Unfortunately, I am still stuck. Here is how I do it:
In Startup.cs ConfigureServices(IServiceCollection services)I have:
services.AddSingleton<IConfigureNamedOptions<CookieAuthenticationOptions>, CookieAuthenticationOptionsSetup>();
and later:
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme).AddCookie();
The CookieAuthenticationOptionsSetup class implements IConfigureNamedOptions and sets options.Cookie.Name = "test" inside the Configure method.
I event tried to manually create and set Name property to "Cookies".
If I try to change the name of cookie with lambda expression inside Startup.cs AddCookie method, it works as expected. But if I don't, the CookieAuthenticationOptionsSetup is never used and the default cookie name (.AspNetCore.Cookies) is used.
What I am missing?
AddCookie() by default calls AuthenticationBuilder.AddScheme. From there, we can learn how the options would be ideally registered if you passed them to the AddCookie call:
Services.Configure(authenticationScheme, configureOptions);
So let’s take a look at how Services.Configure works with named options. What ultimately gets registered on the service collection are IConfigureOptions<CookieAuthenticationOptions>>.
So I would guess that is the exact type that is being looked up later when the options are resolved via DI. And in fact, that is the exact type that is being request by the OptionsFactory that is being used by the OptionsMonitor which is requested by the authentication handler.
So, tl;dr: You are registering your custom configuration as the wrong type. You should register it as an IConfigureOptions<>:
services.AddSingleton<IConfigureOptions<CookieAuthenticationOptions>, CookieAuthenticationOptionsSetup>();
Note of course that your CookieAuthenticationOptionsSetup needs to implement IConfigureNamedOptions properly and respond to a Configure call with your scheme name (CookieAuthenticationDefaults.AuthenticationScheme).
In addition to this answer, I also had to add Name property to the class which implements IConfigureNamedOptions<T> and set it in public void Configure(string name, CookieAuthenticationOptions options) method.
Few additional notes for those who will have the same problem:
To apply Authorize attribute globally, authentication scheme must be added (worked without it previously):
services.AddMvcCore(a =>
{
var policy = new AuthorizationPolicyBuilder().AddAuthenticationSchemes(CookieAuthenticationDefaults.AuthenticationScheme).RequireAuthenticatedUser().Build();
a.Filters.Add(new AuthorizeFilter(policy));
});
To use IsAuthenticated property inside middleware, app.UseAuthentication() must be called before registering the middleware.
It is not exactly clear what is the question...
But if you want just to set cookie name (or other options) and really do not need to implement IConfigureNamedOptions try something like this:
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme).AddCookie(options =>
{
options.Cookie.Name = "TestName";
}

User.IsInRole is always false when using IIS Express / Kestrel in ASP.Net 5 with Windows Authentication

I have an ASP.Net 5 application using version 1.0.0-rc1-update1 with Windows Authentication. I've implemented a custom policy in my Startup.cs file:
public void ConfigureServices(IServiceCollection services)
{
// ... other configuration code
var viewCharts = new AuthorizationPolicyBuilder()
.AddRequirements(new ViewChartsRequirement())
.Build();
collection.AddAuthorization(opts =>
{
opts.AddPolicy(Policy.ViewCharts, viewCharts);
});
collection.AddTransient<IAuthorizationHandler, ViewChartsHandler>();
// ... other configuration code
}
The ViewChartsHandler's Handle method is as follows:
protected override void Handle(
AuthorizationContext context,
T requirement)
{
var identities = _securityRepo.GetIdentitiesForPolicy(_policy);
// this returns a result when using a web listener, but
// never finds a match when using IIS Express
var matchingIdentity = identities.FirstOrDefault(role => context.User.IsInRole(role));
if (!string.IsNullOrWhiteSpace(matchingIdentity))
{
context.Succeed(requirement);
}
}
When using a web listener as shown in this answer, the code above works. However, when using IIS Express it never finds a matchingIdentity.
Things to note:
My IIS Express is configured to use Windows Authentication, and deny Anonymous Authentication. The bug related to IIS Express and this was fixed in RC1.
The username from Windows is always resolving correctly.
In the Handle code above, context.User is an instance of System.Security.Principal.WindowsPrincipal when using a web listener, but when using IIS Express it is a System.Security.Claims.ClaimsPrincipal.
I have forwardWindowsAuthToken="true" set in my web.config.
I think this is a role provider problem, but I am at a loss as to how to correct it.
I'm using the following code to successfully check for role membership on RC1, however note that it does not resolve group names (probably due to the problems referred to by #blowdart), I have to supply the group names as SIDs:
// Set up authorisation policies from the configured AD group lists.
// NOTE: Currently this only works with SIDs if hosting using Kestrel
// behind IIS, not friendly group names.
var viewerGroups = Configuration.GetSection("Groups:Viewer").Value.Split(',');
var adminGroups = Configuration.GetSection("Groups:Admin").Value.Split(',');
services.AddAuthorization(auth =>
{
auth.AddPolicy("viewer", policy =>
{
policy.RequireRole(viewerGroups);
});
auth.AddPolicy("admin", policy =>
{
policy.RequireRole(adminGroups);
});
});
I don't know if this will help you, but I thought I'd offer it up in case!
Did you add the IISPlatformHandler middleware?
app.UseIISPlatformHandler();
This needs to be ran before app.UseMvc(), app.UseStaticFiles() or any other authentication middleware.
It turns out that User.IsInRole does not function correctly in RC1. (See #blowdart's comments.) This will be fixed in RC2.
The original code will work so long as the line below returns the SIDs for each AD group, as opposed to the friendly names.
// This line must return SIDs instead of friendly names
var identities = _securityRepo.GetIdentitiesForPolicy(_policy);
Update
This was fixed in RC2. The original code works!

Using Tempdata is crashing my application

I'm very new to ASP.NET and am attempting to pass an object between two controllers in a web application I'm making in Visual Studio 2015. The web application is using an ASP.Net 5 Preview Template Web application (if it helps, I think I'm using beta code 7 and I'm not building for DNX Core 5).
The problem I'm having is whenever I try to put anything into the TempData variable, the program seems to crash. For example, in a "Create" method I have:
[HttpPost]
public ActionResult Create(Query query)
{
switch (query.QueryTypeID)
{
case 1:
TempData["Test"] = "Test";
return RedirectToAction("Index", "EventResults");
case 2:
break;
default:
break;
}
return View();
}
In that method, I attempt to add a simple test string under the key "test". When I run the application with that TempData statement in there, I receive an error message stating
An unhandled exception occurred while processing the request.
InvalidOperationException: Session has not been configured for this application >or request.
Microsoft.AspNet.Http.Internal.DefaultHttpContext.get_Session()
I have tried going to the Web.config located in the wwwroot element of the project and adding a "sessionState" object into a "system.web" element, but this had no effect on the error.
Any help would be very much so appreciated as I've been looking for solutions for this everywhere. I'm hoping it's something stupid/blindingly obvious that I somehow missed.
In order to use middleware, such as Session, Cache, etc in ASP.NET 5, you have to enable them explicitly.
Enabling session is done by adding the appropriate nuget package in your project.json file's dependencies section (make sure that the package version matches the versions of the other dependencies you have added):
"Microsoft.AspNet.Session": "1.0.0-*"
and the appropriate session (cache) storage package as well (like the example below; in memory):
"Microsoft.Extensions.Caching.Memory": "1.0.0-*"
and adding the middleware to dependency resolution in the Startup.cs Service configuration:
public void ConfigureServices(IServiceCollection services)
{
services.AddCaching();
services.AddSession(/* options go here */);
}
and adding the middleware to OWIN in the Startup.cs OWIN configuration:
public void Configure(IApplicationBuilder app)
{
app.UseSession();
//...
Make sure that the UseSession comes before the MVC configuration.
For Asp.Net Core, make sure Asp.NetCore.Session is added.
You can configure session in StartUp.cs like below.
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
services.AddSingleton<ITempDataProvider, CookieTempDataProvider>();
// Adds a default in-memory implementation of IDistributedCache.
services.AddDistributedMemoryCache();
services.AddSession(options =>
{
// Set a short timeout for easy testing.
options.IdleTimeout = TimeSpan.FromSeconds(10);
options.CookieHttpOnly = true;
});
}
public void Configure(IApplicationBuilder app)
{
app.UseSession();
app.UseMvcWithDefaultRoute();
}

Categories