Add User to Role ASP.NET Identity
Asked Answered
P

7

47

I know the new Membership includes a "Simple Role Provider."

I can't find any help related to creating a user and assigning a role when the user is created. I've added a user which created the tables on the DB correctly. I see the AspNetRoles, AspNetUserRoles, and AspNetUsers tables.

I am wanting to assign a role from AspNetRoles to a user in AspNetUsers which the ID of both the role/user are to be stored in AspNetUserRoles.

I'm stuck on the programming part of where and how to do this when I create the user.

I have a dropdown list to select the role, but using the Entity CF along with the new ASP.NET Identity model I'm not sure how to take the ID of the selectedvalue from the dropdown and the UserID and assign the role.

Paraformaldehyde answered 30/10, 2013 at 16:58 Comment(2)
Just wondering how you got the list of roles to put into the dropdown? Are you asking Identity or are just using a list of known roles?Enterpriser
Asp.Net Identity has upgraded since I posted this and I believe they have information on their site for this. Sorry I don't have the link.Paraformaldehyde
F
75

I found good answer here Adding Role dynamically in new VS 2013 Identity UserManager

But in case to provide an example so you can check it I am gonna share some default code.

First make sure you have Roles inserted.

enter image description here

And second test it on user register method.

[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Register(RegisterViewModel model)
{
    if (ModelState.IsValid)
    {
        var user = new ApplicationUser() { UserName = model.UserName  };

        var result = await UserManager.CreateAsync(user, model.Password);
        if (result.Succeeded)
        {
            var currentUser = UserManager.FindByName(user.UserName); 

            var roleresult = UserManager.AddToRole(currentUser.Id, "Superusers");

            await SignInAsync(user, isPersistent: false);
            return RedirectToAction("Index", "Home");
        }
        else
        {
            AddErrors(result);
        }
    }

    // If we got this far, something failed, redisplay form
    return View(model);
}

And finally you have to get "Superusers" from the Roles Dropdown List somehow.

Featherveined answered 7/1, 2014 at 12:25 Comment(7)
Best answer, would you expect anything less from a SuperMan?Tb
Can I extend this question to ask if there is a way to show the roles to the user on registration for them to select from, which is then assigned to the user in the Registration POST action.Spearing
@Spearing Would you allow somone to select Sysadmin for himself?Nostril
I suspect this is a rhetorical question however I will venture an answer for the sake of discussion and say no :-)Spearing
In my testing/experiments I found that the currentUser retrieval isn't necessary. I simply call await this.UserManager.AddToRoleAsync(user.Id, "SpecificRole"); and the user is added to the role.Extrasystole
Thank you so much! I had my head banging a lot before I managed to use your solution!Randellrandene
In asp.net core 2.2 you can use AddToRoleAsync(user,roleName) only give user model to AddToRoleAsyncBagging
E
29

I had the same challenge. This is the solution I found to add users to roles.

internal class Security
{
    ApplicationDbContext context = new ApplicationDbContext();

    internal void AddUserToRole(string userName, string roleName)
    {
        var UserManager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(context));

        try
        {
            var user = UserManager.FindByName(userName);
            UserManager.AddToRole(user.Id, roleName);
            context.SaveChanges();
        }
        catch
        {
            throw;
        }
    }
}
Elevenses answered 9/10, 2014 at 16:44 Comment(2)
In my AccountController I didn't have a database context, so I used "await UserManager.UpdateAsync(currentUser)" instead of "context.SaveChanges()".Drawer
I guess it not good to have business logic on controllers @ChuckKrutsingerSkilken
S
13

While I agree with the other answers regarding the RoleManager, I would advice to examine the possibility to implement Authorization through Claims (Expressing Roles as Claims).

Starting with the .NET Framework 4.5, Windows Identity Foundation (WIF) has been fully integrated into the .NET Framework.

In claims-aware applications, the role is expressed by a role claim type that should be available in the token. When the IsInRole() method is called, there is a check made to see if the current user has that role.

The role claim type is expressed using the following URI: "http://schemas.microsoft.com/ws/2008/06/identity/claims/role"

So instead of using the RoleManager, you can "add a user to a role" from the UserManager, doing something like this:

var um = new UserManager();
um.AddClaimAsync(1, new Claim("http://schemas.microsoft.com/ws/2008/06/identity/claims/role", "administrator"));

With the above lines you have added a role claim with the value "administrator" to the user with the id "1"...

Claims authorization, as suggested by MSFT, can simplify and increase the performance of authentication and authorization processes eliminating some back-end queries every time authorization takes place.

Using Claims you may not need the RoleStore anymore. (AspNetRoles, AspNetUserRoles)

Sabbatarian answered 3/2, 2014 at 1:29 Comment(3)
Claims authorization, as suggested by MSFT, can simplify and increase the performance of authentication and authorization processes eliminating some back-end queries every time authorization takes place Do you have a source for this claim (pun not intended :)) I would've thought roles would be cached upon creation of the token and you would need to read either a claim or a role from storage, so a ClaimsStore would just replace a RoleStore.Gerdagerdeen
After doing a lot of research over the weekend, this seems to be the direction things are going. I'd say this is the best answer for anyone doing identity in MVC5+.Bobcat
You can also use the ClaimTypes.Role instead of the URL to indicate the claim type. So you can create that role claim using: new Claim(ClaimTypes.Role, "administrator")Oralle
L
9

Are you looking for something like this:

RoleManager = new RoleManager<IdentityRole>(new RoleStore<IdentityRole>(new MyDbContext()));
var str = RoleManager.Create(new IdentityRole(roleName));

Also check User Identity

Lonnylonslesaunier answered 30/10, 2013 at 17:3 Comment(1)
I saw that, which from what I understand is to create the role. I have the roles created on the table. I just don't understand how I would assign the role from the selected Dropdown value to the User when I create them. It's an in-house application and a "Super-user" will create the users. So I was hoping to allow the User to be created and have a Role assigned on the same event. My apologies if that is confusing.Paraformaldehyde
H
4

This one works for me. You can see this code on AccountController -> Register

var user = new JobUser { UserName = model.Email, Email = model.Email };
var result = await UserManager.CreateAsync(user, model.Password);
if (result.Succeeded)
{
    //add this to add role to user
     await UserManager.AddToRoleAsync(user.Id, "Name of your role");
}

but the role name must exist in your AspNetRoles table.

Heptangular answered 24/6, 2019 at 13:6 Comment(0)
F
3

Below is an alternative implementation of a 'create user' controller method using Claims based roles.

The created claims then work with the Authorize attribute e.g. [Authorize(Roles = "Admin, User.*, User.Create")]

    // POST api/User/Create
    [Route("Create")]
    public async Task<IHttpActionResult> Create([FromBody]CreateUserModel model)
    {
        if (!ModelState.IsValid)
        {
            return BadRequest(ModelState);
        }

        // Generate long password for the user
        var password = System.Web.Security.Membership.GeneratePassword(25, 5);

        // Create the user
        var user = new ApiUser() { UserName = model.UserName };
        var result = await UserManager.CreateAsync(user, password);
        if (!result.Succeeded)
        {
            return GetErrorResult(result);
        }

        // Add roles (permissions) for the user
        foreach (var perm in model.Permissions)
        {
            await UserManager.AddClaimAsync(user.Id, new Claim(ClaimTypes.Role, perm));
        }

        return Ok<object>(new { UserName = user.UserName, Password = password });
    }
Fann answered 27/5, 2016 at 7:46 Comment(0)
A
2

Check this link: Assigning Roles to Users. You can add a step to your CreateUserWIzard control and choose the roles in that step.

<asp:CreateUserWizard ID="RegisterUserWithRoles" runat="server" 
    ContinueDestinationPageUrl="~/Default.aspx" LoginCreatedUser="False" 
    onactivestepchanged="RegisterUserWithRoles_ActiveStepChanged">
    <WizardSteps>
        <asp:CreateUserWizardStep ID="CreateUserWizardStep1" runat="server">
        </asp:CreateUserWizardStep>
        <asp:WizardStep ID="SpecifyRolesStep" runat="server" AllowReturn="False" 
            StepType="Step" Title="Specify Roles">
            <h3>Choose the role.</h3>
            <asp:CheckBoxList ID="RoleList" runat="server">
            </asp:CheckBoxList>
        </asp:WizardStep>
        <asp:CompleteWizardStep ID="CompleteWizardStep1" runat="server">
        </asp:CompleteWizardStep>
    </WizardSteps>
</asp:CreateUserWizard>

And in the code-behind you will have:

protected void Page_Load(object sender, EventArgs e)
{
    if (!Page.IsPostBack)
    {
        // Reference the SpecifyRolesStep WizardStep 
        WizardStep SpecifyRolesStep = RegisterUserWithRoles.FindControl("SpecifyRolesStep") as WizardStep;

        // Reference the RoleList CheckBoxList 
        CheckBoxList RoleList = SpecifyRolesStep.FindControl("RoleList") as CheckBoxList;

        // Bind the set of roles to RoleList 
        RoleList.DataSource = Roles.GetAllRoles();
        RoleList.DataBind();
    } 
}
protected void RegisterUserWithRoles_ActiveStepChanged(object sender, EventArgs e)
{
    // Have we JUST reached the Complete step? 
    if (RegisterUserWithRoles.ActiveStep.Title == "Complete")
    {
        // Reference the SpecifyRolesStep WizardStep 
        WizardStep SpecifyRolesStep = RegisterUserWithRoles.FindControl("SpecifyRolesStep") as WizardStep;

        // Reference the RoleList CheckBoxList 
        CheckBoxList RoleList = SpecifyRolesStep.FindControl("RoleList") as CheckBoxList;

        // Add the checked roles to the just-added user 
        foreach (ListItem li in RoleList.Items)
        {
            if (li.Selected)
                Roles.AddUserToRole(RegisterUserWithRoles.UserName, li.Text);
        }
    }
}
Ashleyashli answered 3/1, 2014 at 13:43 Comment(1)
He asked how to do it with ASP .NET Identity.Featherveined

© 2022 - 2024 — McMap. All rights reserved.