`[Authorize (Roles="Role")]` not working, User.IsInRole("Role") always false - c#

I feel like I'm missing something. Authorize by itself works, but using roles does not. The cshtml-Code contains razor stuff, which I'm not sure I'm allowed to use in combination with roles based authorization. Furthermore, IsInRole always returns false.
In my database in the table AspNetUserRoles, the role instance is there with the correct RoleId and UserId. I added the user to the role in the Seed method of the database.
if (!userManager.IsInRole(adminUser.Id, "SystemAdministrator"))
userManager.AddToRole(adminUser.Id, "SystemAdministrator");
Do I need to add them somewhere else, like in some kind of role manager?
Here's what I think is the relevant part of the Configuration in Startup:
app.CreatePerOwinContext<RoleManager<AppRole>>((options, context) =>
new RoleManager<AppRole>(
new RoleStore<AppRole>(context.Get<MyANTon.DataContext.AntContext>())));
Maybe, after this, I have to add the user to the role?
Edit: I found a possible error source for this. My db context does not seem to include the identity tables like AspNetUserRoles or even AspNetUsers. I migrated from Forms-Authentication to Identities last week, this is probably the problem now. Do I have to change the context accordingly? It inherits from IdentityDbContext<AppUser>, which is why I can't just add the AspUserstuff (since it's already there), but when I look at the context at runtime, it's not there...
Next edit: I was missing the web.config for my role manager. After adding it, it seems like my data context idea actually feels to be true. Now, the error thrown is: 'The entity type AppUser is not part of the model for the current context.'. My context inherits from IdentityDbContext<AppUser>, why doesn't it contain AppUser then?
Context class:
public class AntContext : IdentityDbContext<AppUser>
{
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
Database.SetInitializer<AntContext>(null);
modelBuilder.Entity<AppUser>().ToTable("AppUsers");
base.OnModelCreating(modelBuilder);
}
UserManager constructor call in controller:
private UserManager<AppUser> userManager = new UserManager<AppUser>(new UserStore<AppUser>());

When you are creating your roles ... make sure there are no extra spaces before or after the Role Name when you save them into the DB. I wasted 3/4 of a day trying to chase down why this was happening.

Its looks like you have "SystemAdministrator" role and may be many others.
You should use [Authorize(Roles = "RoleName")]
ex:- [Authorize(Roles = "SystemAdministrator")]
Cross verify in your database if you have the corresponding roles.

Related

AspNet MVC get User or Identity object by username for any user (not current user)

I have been looking for a way to get a complete Userobject based on username in the default Identity model of AspNet MVC for any user. I am using asp.net Identity 2.
Through some google searches the following is the closest I came without directly querying to the database.
var user = UserManager.Users.FirstOrDefault(u => u.UserName == userName);
However UserManager requires a generic type of UserManager<TUser> and I have no clue what gereric type I am supposed to fill out here, or how I am even supposed to make this work. I'd prefer using the default asp.net functions so I don't have to query to the database myself.
I'm going to assume by default you mean the set up Visual Studio gives you when you choose
an ASP.NET Web Application with MVC and individual user accounts.
You will need the following using statement
using Microsoft.AspNet.Identity;
I believe you want the FindByName method or the FindByNameAsync method. It is a generic method so you can call it like this
var user = userManager.FindByName<ApplicationUser, string>("{the username}");
where in this case the type of the user primary key is string. But you should be able to drop the generic type parameters and just call it like this
var user = userManager.FindByName("{the username}");
If you aren't using this default set up the thing to do would be to find the type that your userManager inherits from. In visual studio you can do this by hovering over the ApplicationUserManager and pressing F12. In the default case it looks like this
public class ApplicationUserManager: UserManager<ApplicationUser>
{
//...
}
But whatever the type that the UserManager has is what you need.
ApplicationDbContext context = new ApplicationDbContext();
string CurrentUser = User.Identity.Name;
var applicationUser = await context.Users
.Where(a => a.Email.Equals(CurrentUser)).FirstOrDefaultAsync();

ASP.NET Core Identity UserManager Finds non-existant user with FindByEmailAsync

I've been trying to use ASP.NET Core Identity in order to check for existing users in my db and when I call FindByEmailAsync or other Find methods on UserManager class it finds entity with Id even though AspNetUsers DB table is empty
I've doublechecked my Startup.cs file, because I'm almost sure that has to be something with DI. But I use this EntityManager in my service class and this class is being registered as Scoped.
It doesn't matter what i type in parameter, always returns some entity:
My Startup DI configurations:
My User (derives from IdentityUser):
My service registration (where I use UserManager via DI):
I expect these methods not to find any user entities, but for some reason it always returs non-null values.
Might be the Identity caching or DI problems?
FindByEmailAsync method returns a Task, not a user. If you check the type of the userExists variable, you will see that it's of type Task<>. So, the method doesn't return a user with id 70, but a Task with id 70. If you modify this line:
var userExists = _userManager.FindByEmailAsync("rasfafasf");
by adding await:
var userExists = await _userManager.FindByEmailAsync("rasfafasf");
you will get an actual result of a Task, which is the user with that email (null in your case).

How to check current user's role in ASP.NET MVC 5

currently dealing with an interesting problem. I am building a website with three different user roles. When logged in, the MVC partial view shows navigation options for the users. I want to show different options depending on the user's role. In previous websites, I have used the following code to determine a role:
#if (Roles.IsUserInRole("intern"))
{
<li>#Html.ActionLink("Log Time", "Index", "Time")</li>
}
Unfortunately, when I attempted this in my current code, I got the message:
The Role Manager feature has not been enabled.
So apparently in the new MVC they disable the role manager by default and have a new way of doing it. No biggie. Searching the issue suggested that I enable the feature in web.config. I followed several instructions on how to do that (I promise I can google search) but it seems to mess with my SQL Server connection string, giving me errors that indicate it's trying to log in to a local db that doesn't exist rather than my Azure SQL Server. I've played around for a while and I don't know why this is the case.
Anyway, long story short, rather than work around and re-enable a vestigial Identity feature, how are you supposed to accomplish this in the new MVC? I can get the roles fine controller side with user manager, but I can't use that in a view. Similarly a Viewbag full of roles can't work because this is navigation on every page.
I appreciate all the help in advance, thanks everyone!
Just found the answer, I'll leave this up for other people dealing with this. The correct way to do this is:
#if (User.IsInRole("intern"))
This makes sense since MVC is moving away from Role based objects and towards User based objects.
I think it's not really a good idea to ask for the user's role all the time, too many requests are made.
It would be better to ask once and save it on a variable in Razor. Then just check that variable whenever you need it.
By the way, if the roles are different, you don't even want to ask if the user is in that role rather than another one. Rather get the list of roles in a list and check if the role indicated is in the list.
Example (I'm not sure it will compile, look a the idea):
#using Microsoft.AspNetCore.Identity
#using Microsoft.AspNetCore.Mvc.Localization
#inject UserManager<ApplicationUser> UserManager
#{
ApplicationUser currentUser = await UserManager.GetUserAsync(User);
var roles = await UserManager.GetRolesAsync(currentUser);
bool isIntern = roles.Contains("intern");
bool isExtern = roles.Contains("extern");
bool isFoo = roles.Contains("foo");
...
}
then, further on
#if (isIntern)
{
<li>#Html.ActionLink("Log Time", "Index", "Time")</li>
}
else if (isExtern)
{
...
}
You can control the role of the user as many times as you want without having to make other requests and it's all much more readable.

Is a Role Provider implementation necessary?

I am struggling a little bit to completely understand what is the correct way to implement a windows authentication and role based authorization scheme into an MVC4 application. When the user accesses the (intranet) website I currently have the following method check the user name against the against a database table
List<string> permissionList =
PermissionBo.GetUserPermissionsList(PermissionBo.ParseUserName(User.Identity.Name));
Permissions permissions = new Permissions(permissionList);
Then the following if state adds a role to a user object:
if (permissions.IsAdmin)
{
if(!Roles.RoleExists("UtilitiesToolAdmin"))
{
Roles.CreateRole("UtilitiesToolAdmin");
}
if(!Roles.IsUserInRole(User.Identity.Name, "UtilitiesToolAdmin"))
{
Roles.AddUsersToRole(new string[] { User.Identity.Name }, "UtilitiesToolAdmin");
}
}
I feel like this may be an incorrect way to go about implementing this, but I am not sure where I am going wrong. Is this sufficient to begin using the authorize attribute like so:
[Authorize(Roles="UtilitiesToolAdmin")]
public static void Foo()
{
return "Bar"
}
If not what am I missing?
If all you are doing is simple role checking, a custom Role Provider might be a bit of an overkill (Role Providers also provide facilities for managing the roles themselves). What you will end up with is a class full of
throw new NotImplementedException();
Instead, consider creating a custom user principal. The IPrincipal interface defines an IsInRole method that returns a bool. This is where you would put your custom role checks. The advantage of the custom user principal is that now all of the built in ASP.NET role-checking goodies should "just work" as long as you replace the default user principal object with your custom one early enough in the lifecycle.
This SO answer has one of the best examples I've seen of using a custom user principal with an MVC application.

Deleting roles with Asp.net Identity

Can someone describe to me just how you delete roles with asp.net identity. I tried the following, but it did not work and I received a Specified Method is not supported error:
public async Task DeleteRole(string role)
{
// delete role
var roleStore = new RoleStore<IdentityRole>(new Context());
await roleStore.DeleteAsync(new IdentityRole(role));
}
Not sure if this is referring to something with my async logic, or specifically with asp.net identity itself. Nevertheless can someone demonstrate to me how to make this work correctly. There is virtually no documentation available on the new identity system for asp.net at this time.
The Identity context (IdentityDbContext) contains the role store. So you would (assuming AppDb is your context):
var role = AppDb.Roles.Where(d => d.Name == "my role name").FirstOrDefault();
AppDb.Roles.Remove(role);
AppDb.SaveChanges();
You basically treat it as a normal EntityFramework DbSet, it's inherited from the IdentityDbContext.
I know that is an old question, but I've tried a way that doesn't touch store (or DbContext) directly.
I've used it in ASP.NET Core 2.1
var role = await _roleManager.FindByNameAsync(roleName);
var result = await _roleManager.DeleteAsync(role);
needless to say that it:
delete role that assigned to user -> AspNetUserRoles
delete role's claims -> AspNetRoleClaims
delete role itself -> AspNetRoles

Categories

Resources