ASP.NET MVC Exception 'The Role Manager feature has not been enabled' - asp.net-mvc

I'm trying to make an ASP.net MVC website. I have setup Roles in the Startup.cs file as follows:
private void CreateRolesAndUsers()
{
ApplicationDbContext context = new ApplicationDbContext();
var roleManager = new RoleManager<IdentityRole>(new RoleStore<IdentityRole>(context));
var UserManager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(context));
if (!roleManager.RoleExists("SuperAdmin"))
{
// first we create Admin role
var role = new Microsoft.AspNet.Identity.EntityFramework.IdentityRole();
role.Name = "SuperAdmin";
roleManager.Create(role);
//Here we create a Admin super user who will maintain the website
var user = new ApplicationUser();
user.UserName = "SuperAdmin";
user.Email = "SuperAdmin#SU.com";
string userPWD = "Password1";
var chkUser = UserManager.Create(user, userPWD);
//Add default User to Role Admin
if (chkUser.Succeeded)
{
var result1 = UserManager.AddToRole(user.Id, "SuperAdmin");
}
}
}
I have verified that the above code successfully adds the roles to the db and I first noticed the roles not working when I tried Roles.IsUserInRole(User.Identity.Name, "SuperAdmin")
I'm trying to controll which roles see certain content in a view and am getting an Exception:
System.Configuration.Provider.ProviderException: 'The Role Manager feature has not been enabled.'
when I try to call the following line in a .cshtml file: #Roles.GetRolesForUser();
ive looked where to enable roleManager in Web.config, but cant find it and it dosent work if i add it under the system.web section
EDIT: adding (>roleManager enabled="true"<) into the following code produces another unhandled exception whenever using IsUserInRole: "System.Web.HttpException: Unable to connect to SQL Server database."
<system.web>
<authentication mode="None"/>
<compilation debug="true" targetFramework="4.7"/>
<httpRuntime targetFramework="4.7"/>
</system.web>
i think i might be simply missing a dependancy or some initalizer but have no clue and none of the other solutions in similar quesions have worked.

You can do this by reading from the boolean property at:
System.Web.Security.Roles.Enabled
This is a direct read from the enabled attribute of the roleManager element in the web.config:
<configuration>
<system.web>
<roleManager enabled="true" />
</system.web>
</configuration>
For more information, check out this MSDN sample: https://msdn.microsoft.com/en-us/library/aa354509(v=vs.110).aspx

Related

Hangfire package in MVC on local IIS server responds with "The website declined to show this webpage" [duplicate]

I am running HangFire within my MVC web app but whenever I try to navigate to http://MyApp/hangfire, it redirects me to my app's login page as though I am not logged in.
I have not explicitly configured any requirements for authorization...e.g. I had the below in the web.config, but then took it out in attempts to get this to work.
<location path="hangfire">
<system.web>
<authorization>
<allow roles="Administrator" />
<deny users="*" />
</authorization>
</system.web>
In theory, this is what I'd want, and when I log into my main web application, I will be logged in with an Administrator role so this rule should work.
But whether I have that configured in the web.config or not, whenever I try to navigate to http://MyApp/hangfire, it redirects me to my apps login page as configured in the web.config:
<authentication mode="Forms">
<forms loginUrl="~/Account/Login" timeout="960" />
</authentication>
It does NOT do this on my local machine, just when I publish to my host. Does HangFire not recognize the authentication cookie that my main app provides when I login? I thought in general, the hangfire app doesn't require authentication, so what other configuration could be thinking that it does?
UPDATE 1:
I added the authorization filters per the hangfire docs, but the same thing happens. Here is my code in Startup.cs:
using Hangfire;
using Hangfire.Logging;
using Hangfire.Dashboard;
using Hangfire.SqlServer;
using Microsoft.Owin;
using OTIS.Web.AppCode;
using OTISScheduler.AppServ;
using Owin;
using System.Web.Security;
[assembly: OwinStartup(typeof(OTIS.Web.App_Start.Startup))]
namespace OTIS.Web.App_Start
{
public class Startup
{
public void Configuration(IAppBuilder app) {
app.UseHangfire(config => {
config.UseSqlServerStorage("DefaultConnection");
config.UseServer();
//Dashboard authorization
config.UseAuthorizationFilters(new AuthorizationFilter
{
Users = "USERA", // allow only specified users (comma delimited list)
Roles = "Account Administrator, Administrator" // allow only specified roles(comma delimited list)
});
});
LogProvider.SetCurrentLogProvider(new StubLogProviderForHangfire());
GlobalJobFilters.Filters.Add(new AutomaticRetryAttribute { Attempts = 0 });
var scheduleTasksInitializer = new ScheduleTasksInitializer();
scheduleTasksInitializer.ScheduleTasks();
}
}
}
UPDATE 2:
Per the more detailed instructions showing basic authentication, I also tried this...still no luck..redirects me to my app's login page.
config.UseAuthorizationFilters(
new BasicAuthAuthorizationFilter(
new BasicAuthAuthorizationFilterOptions
{
// Require secure connection for dashboard
RequireSsl = false,
SslRedirect = false,
// Case sensitive login checking
LoginCaseSensitive = true,
// Users
Users = new[]
{
new BasicAuthAuthorizationUser
{
Login = "MyLogin",
// Password as plain text
PasswordClear = "MyPwd"
}
}
}));
With the newer versions you should use IDashboardAuthorizationFilter. With the using statements, it will look like this:
using System.Web;
using Hangfire.Annotations;
using Hangfire.Dashboard;
namespace Scheduler.Hangfire
{
public class HangFireAuthorizationFilter : IDashboardAuthorizationFilter
{
public bool Authorize([NotNull] DashboardContext context)
{
//can add some more logic here...
return HttpContext.Current.User.Identity.IsAuthenticated;
//Can use this for NetCore
return context.GetHttpContext().User.Identity.IsAuthenticated;
}
}
}
then in the configuration section:
app.UseHangfireDashboard("/jobs", new DashboardOptions()
{
Authorization = new [] {new HangFireAuthorizationFilter()}
});
Finally got it working. I created my own AuthorizationFilter class (see below).
Then I passed that to the MapHangfireDashboard method in the Startup.cs Configuration method (see below that)
public class HangFireAuthorizationFilter : IAuthorizationFilter
{
public bool Authorize(IDictionary<string, object> owinEnvironment)
{
bool boolAuthorizeCurrentUserToAccessHangFireDashboard = false;
if (HttpContext.Current.User.Identity.IsAuthenticated)
{
if(HttpContext.Current.User.IsInRole("Account Administrator"))
boolAuthorizeCurrentUserToAccessHangFireDashboard = true;
}
return boolAuthorizeCurrentUserToAccessHangFireDashboard;
}
}
To map hangfire to a custom url and specify the AuthorizationFilter to use:
public void Configuration(IAppBuilder app) {
//Get from web.config to determine to fire up hangfire scheduler or not
app.UseHangfire(config => {
config.UseSqlServerStorage("DefaultConnection");
config.UseServer();
});
//map hangfire to a url and specify the authorization filter to use to allow access
app.MapHangfireDashboard("/Admin/jobs", new[] { new HangFireAuthorizationFilter() });
}
As designed I believe.
See the docs for the dashboard.
By default Hangfire allows access to Dashboard pages only for local requests.
Strangely enough I was dealing with this the other day and one thing to be aware of is that if you are using Autofac dependency injection then you need to make sure you configure items in the correct order. Specifically Hangfire after other authentication but also, in my case, MembershipReboot before the other OAuth stuff.
Took quite a bit of trial and error.

IsAuthenticated of Request is false inside Glimpse policy, even I'm logged in

I'm building site with ASP.NET MVC 5, and would like to secure Glimpse with existing layer of security, MVC 5 Roles. Glimpse is version 1.8.6
I wrote my implementation of IRuntimePolicy, derived from the sample code. When I run thru my code the IsAuthenticated property of request is always false. Even when I'm logged in (in the controller this property is true). Can anybody help me what I'm doing wrong? I thought setting Glimpse:DisableAsyncSupport in the app settings would help, but didn't.
This is my implementatio of IRuntimePolicy
public RuntimePolicy Execute(IRuntimePolicyContext policyContext)
{
var userManager = new UserManager(new UserStore<MyUser>(new ApplicationDbContext()));
var httpContext = HttpContext.Current;
if (httpContext.Request.IsAuthenticated) //ALWAYS FALSE, EVEN WHEN IM LOGGED IN
{
var userId = httpContext.User.Identity.GetUserId(); //User is null
if (userManager.IsInRole(userId, "Admin"))
return RuntimePolicy.On;
}
return RuntimePolicy.Off;
}
You have to add <modules runAllManagedModulesForAllRequests="true" /> or add precondition="managedHandler" for your module. See more explanation here: enter link description here There might be a performance hit in the first option.

Why is Hangfire requiring authentication to view dashboard

I am running HangFire within my MVC web app but whenever I try to navigate to http://MyApp/hangfire, it redirects me to my app's login page as though I am not logged in.
I have not explicitly configured any requirements for authorization...e.g. I had the below in the web.config, but then took it out in attempts to get this to work.
<location path="hangfire">
<system.web>
<authorization>
<allow roles="Administrator" />
<deny users="*" />
</authorization>
</system.web>
In theory, this is what I'd want, and when I log into my main web application, I will be logged in with an Administrator role so this rule should work.
But whether I have that configured in the web.config or not, whenever I try to navigate to http://MyApp/hangfire, it redirects me to my apps login page as configured in the web.config:
<authentication mode="Forms">
<forms loginUrl="~/Account/Login" timeout="960" />
</authentication>
It does NOT do this on my local machine, just when I publish to my host. Does HangFire not recognize the authentication cookie that my main app provides when I login? I thought in general, the hangfire app doesn't require authentication, so what other configuration could be thinking that it does?
UPDATE 1:
I added the authorization filters per the hangfire docs, but the same thing happens. Here is my code in Startup.cs:
using Hangfire;
using Hangfire.Logging;
using Hangfire.Dashboard;
using Hangfire.SqlServer;
using Microsoft.Owin;
using OTIS.Web.AppCode;
using OTISScheduler.AppServ;
using Owin;
using System.Web.Security;
[assembly: OwinStartup(typeof(OTIS.Web.App_Start.Startup))]
namespace OTIS.Web.App_Start
{
public class Startup
{
public void Configuration(IAppBuilder app) {
app.UseHangfire(config => {
config.UseSqlServerStorage("DefaultConnection");
config.UseServer();
//Dashboard authorization
config.UseAuthorizationFilters(new AuthorizationFilter
{
Users = "USERA", // allow only specified users (comma delimited list)
Roles = "Account Administrator, Administrator" // allow only specified roles(comma delimited list)
});
});
LogProvider.SetCurrentLogProvider(new StubLogProviderForHangfire());
GlobalJobFilters.Filters.Add(new AutomaticRetryAttribute { Attempts = 0 });
var scheduleTasksInitializer = new ScheduleTasksInitializer();
scheduleTasksInitializer.ScheduleTasks();
}
}
}
UPDATE 2:
Per the more detailed instructions showing basic authentication, I also tried this...still no luck..redirects me to my app's login page.
config.UseAuthorizationFilters(
new BasicAuthAuthorizationFilter(
new BasicAuthAuthorizationFilterOptions
{
// Require secure connection for dashboard
RequireSsl = false,
SslRedirect = false,
// Case sensitive login checking
LoginCaseSensitive = true,
// Users
Users = new[]
{
new BasicAuthAuthorizationUser
{
Login = "MyLogin",
// Password as plain text
PasswordClear = "MyPwd"
}
}
}));
With the newer versions you should use IDashboardAuthorizationFilter. With the using statements, it will look like this:
using System.Web;
using Hangfire.Annotations;
using Hangfire.Dashboard;
namespace Scheduler.Hangfire
{
public class HangFireAuthorizationFilter : IDashboardAuthorizationFilter
{
public bool Authorize([NotNull] DashboardContext context)
{
//can add some more logic here...
return HttpContext.Current.User.Identity.IsAuthenticated;
//Can use this for NetCore
return context.GetHttpContext().User.Identity.IsAuthenticated;
}
}
}
then in the configuration section:
app.UseHangfireDashboard("/jobs", new DashboardOptions()
{
Authorization = new [] {new HangFireAuthorizationFilter()}
});
Finally got it working. I created my own AuthorizationFilter class (see below).
Then I passed that to the MapHangfireDashboard method in the Startup.cs Configuration method (see below that)
public class HangFireAuthorizationFilter : IAuthorizationFilter
{
public bool Authorize(IDictionary<string, object> owinEnvironment)
{
bool boolAuthorizeCurrentUserToAccessHangFireDashboard = false;
if (HttpContext.Current.User.Identity.IsAuthenticated)
{
if(HttpContext.Current.User.IsInRole("Account Administrator"))
boolAuthorizeCurrentUserToAccessHangFireDashboard = true;
}
return boolAuthorizeCurrentUserToAccessHangFireDashboard;
}
}
To map hangfire to a custom url and specify the AuthorizationFilter to use:
public void Configuration(IAppBuilder app) {
//Get from web.config to determine to fire up hangfire scheduler or not
app.UseHangfire(config => {
config.UseSqlServerStorage("DefaultConnection");
config.UseServer();
});
//map hangfire to a url and specify the authorization filter to use to allow access
app.MapHangfireDashboard("/Admin/jobs", new[] { new HangFireAuthorizationFilter() });
}
As designed I believe.
See the docs for the dashboard.
By default Hangfire allows access to Dashboard pages only for local requests.
Strangely enough I was dealing with this the other day and one thing to be aware of is that if you are using Autofac dependency injection then you need to make sure you configure items in the correct order. Specifically Hangfire after other authentication but also, in my case, MembershipReboot before the other OAuth stuff.
Took quite a bit of trial and error.

How to use Roles in user identity in MVC 5

I want to use asp.net useridentity in mvc 5, I do these steps:
1) create a mvc project.
2) create my own database and change the connectionstring in web.config form:
to:
3) I run the project and create a new user to add related table to my database.
4) I wanted to add a role to a user after registration a user like this code in accountControler:
public async Task<ActionResult> Register(RegisterViewModel model)
{
if (ModelState.IsValid)
{
var user = new ApplicationUser() { UserName = model.Email, Email = model.Email };
IdentityResult result = await UserManager.CreateAsync(user, model.Password);
if (result.Succeeded)
{
//******************* Add Role To User **************
if (!Roles.RoleExists("Member"))
Roles.CreateRole("Member");
Roles.AddUserToRole(model.Email, "Member");
//****************************************************
await SignInAsync(user, isPersistent: false);
// For more information on how to enable account confirmation and password reset please visit http://go.microsoft.com/fwlink/?LinkID=320771
// Send an email with this link
// string code = await UserManager.GenerateEmailConfirmationTokenAsync(user.Id);
// var callbackUrl = Url.Action("ConfirmEmail", "Account", new { userId = user.Id, code = code }, protocol: Request.Url.Scheme);
// await UserManager.SendEmailAsync(user.Id, "Confirm your account", "Please confirm your account by clicking here");
return RedirectToAction("Index", "Home");
}
else
{
AddErrors(result);
}
}
// If we got this far, something failed, redisplay form
return View(model);
}
5) I add
<roleManager enabled="true">
into:
<system.web></system.web>
when I create a new user my user register well but user not add to the role, and when I do this VS Create a new database in App_Data with name "ASPNETDB.MDF".
so I found a new article that explain about Role Provider Settings in web.config and:
6) I add
<roleManager enabled="true">
<providers>
<clear/>
<add name="AspNetSqlRoleProvider" connectionStringName="DefaultConnection" applicationName="/" type="System.Web.Security.SqlRoleProvider, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"/>
</providers>
</roleManager>
into :
<system.web></system.web>
but when I want to register new user I found this Error:
Could not find stored procedure 'dbo.aspnet_CheckSchemaVersion'.
Now I think my problem is when I do step 3 it will not completely create the user identity database and stored procedure! Am I using role true for MVC 5 ? Please help me to solve this problem!
When you write
!Roles.RoleExists("Member")
you are not using ASP.NET Identity! instead, you should use ApplicationRole so it extends the IdentityRole class
In addition, you don't need to tell the AspNetSqlRoleProvider in your config file. Asp.Net Identity is something different. In Asp.Net Identity there is a class named ApplicationRoleManager in the App_Start folder.
You should not use Asp.Net Identity as if it was the old simple membership.
Alternatively, check the beta(which means things may change) version of Identity to learn more on how to do in Identity.
Here is how to start :
Create a new project : Choose Empty template (Not MVC not WebForm)
Install the Asp.Net identity sample via nuget
PM> Install-Package Microsoft.AspNet.Identity.Samples -Pre
edit namespace to match your old project namespace
If you want to copy some folders from your old project to the new project, copy your (Controllers, Views,... ) not the config files.
Here you can create roles as follows:
var role = new IdentityRole("roleName");
var roleresult = await RoleManager.CreateAsync(role);
and to create and add a user to specific roles you will use this
var user = new ApplicationUser
{
UserName = "tresorunikin",
Email = "tresorunikin#bellashada.com",
EmailConfirmed =true
};
var userResult = await UserManager.CreateAsync(user, "123#Strong.Password");
if(userResult.Succeeded){
string[] roles =new string[]{"admin","seller","other"};
var roleResult = await UserManager.AddToRolesAsync(user.Id, roles);
if(roleResult.Succeeded){
//Here, user has been added to roles
}
}
All these are done for you by Pranav Rastogi, one of the Identity team at Microsoft.
Note that with these samples you target a new (beta) version of System.Web.Mvc that is newer than System.Web.Mvc 5.0.0.0 If I remember well the beta version is System.Web.MVC 5.0.1.2 or something like that
To Learn More about Identity click here
UPDATES
The Version in the samples is: System.Web.Mvc 5.2.1.0

AuthorizeRole="Admin" not working in mvc3 app?

I have membership provider setup in an mvc3 application.
I ported it from the local sql express app_data/aspnetdb.mdf to a local server 2008 instance
(this is currently working fine for logins/etc, and [Authorize] SomeMethod()
I recently added 1 new aspnet_roles ("Admin") and 1 new entry in the aspnet_UsersInRoles assoc. w/my username.
Role Table:
ApplicationId RoleId RoleName LoweredRoleName Description
3F96CA96-CCB3-4780-8038-AF3CCE0BD4F2 9B5B798D-E56E-4144-A12C-7C8945FCB413 Admin admin Administrator
UsersInRoles:
UserId RoleId
58974159-E60E-4185-AD00-F8024C7C5974 9B5B798D-E56E-4144-A12C-7C8945FCB413
Q1: Why does the following code not let me into this controller action?
[Authorize]
[Authorize(Roles = "Admin")] // !!! This is keeping me out...commented out I can get in but I'm set as "Admin" and have tried lower case "admin" as well.
public ActionResult SomeMethod()
{}
Q1a: Is there another a role provider connection string that I have to setup in the web config to get this to work?
Can you please post parts of your web.config regarding membership and role providers. This sounds like your application name isn't set properly.
<roleManager enabled="true">
<providers>
<clear/>
<add name="AspNetSqlRoleProvider" type="System.Web.Security.SqlRoleProvider" connectionStringName="ApplicationServices" applicationName="Your Application Name here" />
</providers>
</roleManager>
Edit
Your application name isn't set. It needs to be set to something and it must match the application name in your database table: aspnet_Applications
If you web config has applicationName="TestApp" /> then your database table also needs to have TestApp in the aspnet_Applications table
Make sure that your ApplicationId is the same you are probably using a different applicationId, check here for more info
Try the below code in order to pin point your problem :
public ActionResult SomeMethod() {
if (!User.IsInRole("Admin"))
throw new SecurityException("User is not an admin.");
}
If you get an exception, it means that there is problem with your Membership Provider or you're not in admin role or your applicationid was configured different as suggested below.
These are some of the possibilities.

Resources