0% found this document useful (0 votes)
319 views19 pages

A Simple Blazor User and Role Manager

The document describes how to create a simple user and role management administration page for a server-side Blazor application. It explains how to programmatically add an administrator role and assign a user to that role. It then provides code snippets to display a list of existing users, add the ability to edit users, update passwords, and add or delete users. The code demonstrates using Identity, Entity Framework Core migrations, and authorization to manage users and roles.

Uploaded by

dmusuda
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
319 views19 pages

A Simple Blazor User and Role Manager

The document describes how to create a simple user and role management administration page for a server-side Blazor application. It explains how to programmatically add an administrator role and assign a user to that role. It then provides code snippets to display a list of existing users, add the ability to edit users, update passwords, and add or delete users. The code demonstrates using Identity, Entity Framework Core migrations, and authorization to manage users and roles.

Uploaded by

dmusuda
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 19

Back

9/22/2019 Admin

A Simple Blazor User and Role Manager


You can create a simple administration page to allow you to create, update, and delete users in your server side
Blazor application by adding a single .razor page. This example also demonstrates how to update the passwords
for your users.

It does this by programmatically creating an Administrator role in the Microsoft ASP.NET Core Identity membership
and programmatically providing administrator access to a designated user (by placing them in the Administrators
role).

The Application

When you run the application for the first time, you will need to click the Register link and create an account called
[email protected].

The Entity Framework Core migrations will run (to create the database)…
…and you will then be able to log into the application with that account.

The application is coded to programmatically add that account to the Administrators role if the user navigates to the
Administration page and they are not an Administrator…

…but to have the application recognize this, you will have to log out and log back in.

When you log back in, you will be able to navigate to the Administration page and see the User Administration.
Clicking the Edit button next to an existing user allows you to update the email address of the user, their password
(the password will only update if you actually make a change), and their Role (either Users or Administrators – Note:
only users in the Administrators role can access the Administration page).

You can either press Save to update the user, or Delete to remove the user from the application.

The Add User button allows you to create a new user.

Create The Application

Using Visual Studio 2019 (or higher), create a Blazor server side application.

Change the Authentication…


… and select Individual User Accounts.

Click OK and complete the process to create the application.

When the application opens in Visual Studio, to add support for Roles, open the Startup.cs file, and change the
following code:

services.AddDefaultIdentity<IdentityUser>()
.AddEntityFrameworkStores<ApplicationDbContext>();

to:

services.AddDefaultIdentity<IdentityUser>()
.AddRoles<IdentityRole>()
.AddEntityFrameworkStores<ApplicationDbContext>();
Add a new page to the project (and a link to it in the navigation menu – see: Creating A Step-By-Step End-To-End
Database Server-Side Blazor Application for help doing this), called Administration.razor using the following code:

@page "/administration"
@using Microsoft.AspNetCore.Authorization;
@using Microsoft.AspNetCore.Identity;
@inject UserManager<IdentityUser> _UserManager
@inject RoleManager<IdentityRole> _RoleManager
@inject AuthenticationStateProvider AuthenticationStateProvider
<h3>Administration</h3>
<AuthorizeView>
<Authorized>
@if (@context.User.IsInRole(ADMINISTRATION_ROLE))
{
<p>You are in @ADMINISTRATION_ROLE </p>
}
else
{
<p>You're not signed in as a user in @ADMINISTRATION_ROLE.</p>
}
</Authorized>
<NotAuthorized>
<p>You're not loggged in.</p>
</NotAuthorized>
</AuthorizeView>
@code {
[CascadingParameter]
private Task<AuthenticationState> authenticationStateTask { get; set; }
string ADMINISTRATION_ROLE = "Administrators";
System.Security.Claims.ClaimsPrincipal CurrentUser;
protected override async Task OnInitializedAsync()
{
// ensure there is a ADMINISTRATION_ROLE
var RoleResult = await _RoleManager.FindByNameAsync(ADMINISTRATION_ROLE);
if (RoleResult == null)
{
// Create ADMINISTRATION_ROLE Role
await _RoleManager.CreateAsync(new IdentityRole(ADMINISTRATION_ROLE));
}
// Ensure a user named [email protected] is an Administrator
var user = await _UserManager.FindByNameAsync("[email protected]");
if (user != null)
{
// Is [email protected] in administrator role?
var UserResult = await _UserManager.IsInRoleAsync(user, ADMINISTRATION_ROLE);
if (!UserResult)
{
// Put admin in Administrator role
await _UserManager.AddToRoleAsync(user, ADMINISTRATION_ROLE);
}
}
// Get the current logged in user
CurrentUser = (await authenticationStateTask).User;
}
}

Run the application.

Click the Register link and create a user named [email protected].


The Entity Framework Core migration page will show.

Click Apply Migrations.

After the migrations are applied, refresh the page in the web browser.

Click Continue.

You will now be logged in.

Navigate to the Administration page.

You will see a message that indicates your are not in the Administrators role (even though code has run, because you
navigated to that page, to add your account to that Role).

Log out and log back in again, and you will now be recognized as a user in the Administrators role.
Create another user.

No matter how many times you log in and out, that user will not be placed in the Administrators role.

List Users
The first step is to list the current users in the application.

First, let’s add some fields and variables to the @code section of the Administration.razor page that we will need
now and to support code we will add later:

// Property used to add or edit the currently selected user


IdentityUser objUser = new IdentityUser();
// Tracks the selected role for the currently selected user
string CurrentUserRole { get; set; } = "Users";
// Collection to display the existing users
List<IdentityUser> ColUsers = new List<IdentityUser>();
// Options to display in the roles dropdown when editing a user
List<string> Options = new List<string>() { "Users", "Administrators" };
// To hold any possible errors
string strError = "";
// To enable showing the Popup
bool ShowPopup = false;

Let’s also add method stubs for methods we will need later.

We add them now because markup that we will add soon, will refer to these methods, and the code will not compile if
the methods do not exist (even though at this point the methods will not actually perform the eventual functionality).

void AddNewUser()
{
}
async Task SaveUser()
{
}
async Task EditUser(IdentityUser _IdentityUser)
{
}
async Task DeleteUser()
{
}
void ClosePopup()
{
// Close the Popup
ShowPopup = false;
}

Now let us add the code to display the existing users.

Add the following method:


public void GetUsers()
{
// clear any error messages
strError = "";
// Collection to hold users
ColUsers = new List<IdentityUser>();
// get users from _UserManager
var user = _UserManager.Users.Select(x => new IdentityUser
{
Id = x.Id,
UserName = x.UserName,
Email = x.Email,
PasswordHash = "*****"
});
foreach (var item in user)
{
ColUsers.Add(item);
}
}

Also, add the following code to the end of the protected override async Task OnInitializedAsync() method so that
the getUsers() method will be invoked when the user navigates to the page:

// Get the users


GetUsers();

Finally, in the HTML markup section, at the top of the file, replace this line of code:

<p>You are in @ADMINISTRATION_ROLE </p>

With the following code:

<table class="table">
<thead>
<tr>
<th>Id</th>
<th>User Name</th>
<th>Email</th>
</tr>
</thead>
<tbody>
@foreach (var user in ColUsers)
{
<tr>
<td>@user.Id.Substring(0, 5) ...</td>
<td>@user.UserName</td>
<td>@user.Email</td>
<td>
<!-- Edit the current forecast -->
<button class="btn btn-primary"
@onclick="(() => EditUser(user))">
Edit
</button>
</td>
</tr>
}
</tbody>
</table>
When we log in with the [email protected] account and navigate to the Administration page, we
see a list of the users.

Note, the Edit button will not actually work at this point.

Add Users
In the UI markup, under the recently added table markup, add the following code to implement the popup to add and
edit users and an Add User button to trigger it:
@if (ShowPopup)
{
<!-- This is the popup to create or edit a user -->
<div class="modal" tabindex="-1" style="display:block" role="dialog">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h3 class="modal-title">Edit User</h3>
<!-- Button to close the popup -->
<button type="button" class="close"
@onclick="ClosePopup">
<span aria-hidden="true">X</span>
</button>
</div>
<!-- Edit form for the current user -->
<div class="modal-body">
<!-- Only show Id if not a new user -->
@if (objUser.Id != "")
{
<p>@objUser.Id</p>
}
<!-- Only allow edit if a new user -->
@if (objUser.Id != "")
{
<p>@objUser.UserName</p>
}
else
{
<input class="form-control" type="text"
placeholder="UserName"
@bind="objUser.UserName" />
}
<input class="form-control" type="text"
placeholder="Email"
@bind="objUser.Email" />
<input class="form-control" type="password"
placeholder="Password"
@bind="objUser.PasswordHash" />
<select class="form-control"
@bind="@CurrentUserRole">
@foreach (var option in Options)
{
<option value="@option">
@option
</option>
}
</select>
<br /><br />
<!-- Button to save the user -->
<button class="btn btn-primary"
@onclick="SaveUser">
Save
</button>
<!-- Only show delete button if not a new record -->
@if (objUser.Id != "")
{
<!-- Button to delete the forecast -->
<button class="btn btn-danger"
@onclick="DeleteUser">
Delete
</button>
}
<br />
<span style="color:red">@strError</span>
</div>
</div>
</div>
</div>
}
<button class="btn btn-success" @onclick="AddNewUser">Add User</button>

In the procedure code, change the AddNewUser() method to the following (this is triggered when the Add User button
is clicked):
void AddNewUser()
{
// Make new user
objUser = new IdentityUser();
objUser.PasswordHash = "*****";
// Set Id to blank so we know it is a new record
objUser.Id = "";
// Open the Popup
ShowPopup = true;
}

Finally, alter the SaveUser() method to the following:

async Task SaveUser()


{
try
{
// Is this an existing user?
if (objUser.Id != "")
{
// To be implemented later...
}
else
{
// Insert new user
var NewUser =
new IdentityUser
{
UserName = objUser.UserName,
Email = objUser.Email
};
var CreateResult =
await _UserManager
.CreateAsync(NewUser, objUser.PasswordHash);
if (!CreateResult.Succeeded)
{
if (CreateResult
.Errors
.FirstOrDefault() != null)
{
strError =
CreateResult
.Errors
.FirstOrDefault()
.Description;
}
else
{
strError = "Create error";
}
// Keep the popup opened
return;
}
else
{
// Handle Roles
if (CurrentUserRole == ADMINISTRATION_ROLE)
{
// Put admin in Administrator role
await _UserManager
.AddToRoleAsync(NewUser, ADMINISTRATION_ROLE);
}
}
}
// Close the Popup
ShowPopup = false;
// Refresh Users
GetUsers();
}
catch (Exception ex)
{
strError = ex.GetBaseException().Message;
}
}
When we run the application, we can now click the Add User button to open the popup.

The popup allows us to enter the information required to create a new user.

Register Log in About rss_feed

 Home

 Downloads

 [Login]

 [Register]
We can enter information to create a new user, and receive error messages if there are any.

The new user is created and can now log in using the password we created.

Update (And Delete)


To enable the Edit button to work, alter the EditUser method to the following:

async Task EditUser(IdentityUser _IdentityUser)


{
// Set the selected user
// as the current user
objUser = _IdentityUser;
// Get the user
var user = await _UserManager.FindByIdAsync(objUser.Id);
if (user != null)
{
// Is user in administrator role?
var UserResult =
await _UserManager
.IsInRoleAsync(user, ADMINISTRATION_ROLE);
if (UserResult)
{
CurrentUserRole = ADMINISTRATION_ROLE;
}
else
{
CurrentUserRole = "Users";
}
}
// Open the Popup
ShowPopup = true;
}

Next, to enable updating to work, alter the SaveUser() method to replace the following code:

// To be implemented later...

with:
// Get the user
var user = await _UserManager.FindByIdAsync(objUser.Id);
// Update Email
user.Email = objUser.Email;
// Update the user
await _UserManager.UpdateAsync(user);
// Only update password if the current value
// is not the default value
if (objUser.PasswordHash != "*****")
{
var resetToken =
await _UserManager.GeneratePasswordResetTokenAsync(user);
var passworduser =
await _UserManager.ResetPasswordAsync(
user,
resetToken,
objUser.PasswordHash);
if (!passworduser.Succeeded)
{
if (passworduser.Errors.FirstOrDefault() != null)
{
strError =
passworduser
.Errors
.FirstOrDefault()
.Description;
}
else
{
strError = "Pasword error";
}
// Keep the popup opened
return;
}
}
// Handle Roles
// Is user in administrator role?
var UserResult =
await _UserManager
.IsInRoleAsync(user, ADMINISTRATION_ROLE);
// Is Administrator role selected
// but user is not an Administrator?
if (
(CurrentUserRole == ADMINISTRATION_ROLE)
&
(!UserResult))
{
// Put admin in Administrator role
await _UserManager
.AddToRoleAsync(user, ADMINISTRATION_ROLE);
}
else
{
// Is Administrator role not selected
// but user is an Administrator?
if ((CurrentUserRole != ADMINISTRATION_ROLE)
&
(UserResult))
{
// Remove user from Administrator role
await _UserManager
.RemoveFromRoleAsync(user, ADMINISTRATION_ROLE);
}
}

Finally, alter the DeleteUser() method to the following:


async Task DeleteUser()
{
// Close the Popup
ShowPopup = false;
// Get the user
var user = await _UserManager.FindByIdAsync(objUser.Id);
if (user != null)
{
// Delete the user
await _UserManager.DeleteAsync(user);
}
// Refresh Users
GetUsers();
}

When you run the application, you will now have the ability to update and delete users.

Links
Introduction to Identity on ASP.NET Core

Role-based authorization in ASP.NET Core

Role Based Security in an ASP.NET Core Application

Download
The project is available on the Downloads page on this site.

You must have Visual Studio 2019 (or higher) installed to run the code.
28 Comments 
1 Login

G Join the discussion…

LOG IN WITH OR SIGN UP WITH DISQUS ?

Name

 2 Share Best Newest Oldest

P
Paul Ruston − ⚑
a year ago

Hi Michael. Looking for a user management system for an existing Blazor system in
development, and Google gave me this. I was with you through the Lightswitch years and
always trusted your tutorials and judgement. This article is from three years ago and all I want
to know is, before I invest any time (I've been burnt by Silverlight and Lightswitch), is this still a
valid way to administer users for a Blazor app? Stay well, my friend.

1 0 Reply • Share ›

Michael Washington Mod > Paul Ruston


− ⚑
a year ago

The best example I have for user management, that does not use Azure B2C (and I
*do* recommend that you use Azure B2C), is the code that runs this Blog. It is located
at: https://github.com/ADefWebs...

0 0 Reply • Share ›

P
Paul Ruston
a year ago
> Michael Washington
− ⚑

Many thanks, I'll take a look.

0 0 Reply • Share ›

Emin
a year ago
− ⚑

Great tutorial. Would you consider highlighting your code with HighlightJS? It's all automatic.

1 0 Reply • Share ›

Michael Washington Mod


a year ago
> Emin
− ⚑

I fixed the code formatting.

1 0 Reply • Share ›

Y
Yang Hon-Jang
2 years ago
− ⚑

Great tutorial. Thanks a lot.


Documentation of Microsoft about Blazor is hard to follow for me with no previous experience
of AspNet MVC, Identity, Authentication, Authorization.
This tutorial DO help me a lot as a newbie of Blazor Server.
Very thanks again!

1 0 Reply • Share ›

Michael Washington Mod


2 years ago
> Yang Hon-Jang
− ⚑

Thank you for the kind words.

0 0 Reply • Share ›

Allie Pollie
2 years ago
− ⚑

great walk-through ! works very well. This is also helpful for any other grid/edit page. Thanks a
lot

1 0 Reply • Share ›

Sayabis Tga Davao


2 years ago
− ⚑

Thank you. 🙏
1 0 Reply • Share ›

Shannon Slaton − ⚑
10 months ago

Is there a way to have different users logged in to different tabs/browser sessions?

0 0 Reply • Share ›

Michael Washington Mod > Shannon Slaton


− ⚑
10 months ago

When a user is logged into this application, they are logged into **all** tabs of the
application. The **sessions** for all users are always **their own** (not shared with
anyone else)

0 0 Reply • Share ›

Shannon Slaton > Michael Washington


− ⚑
10 months ago

Yes. But I am trying to figure out how to have a different user logged in on
different tabs.

0 0 Reply • Share ›

Michael Washington Mod > Shannon Slaton


− ⚑
10 months ago

Let's say I have an Administrator Tab, I only want people who are
Administrators to see the Tab. When a user logs in, if they are an
Administrator, I show them the Administrator Tab (otherwise they
cannot see it). You can see how I do that here:
https://blazorhelpwebsite.c...

0 0 Reply • Share ›

Shannon Slaton > Michael Washington


− ⚑
10 months ago

Yes. I see that. But that is not what I am asking. I want Steve logged
into one browser tab and Dave logged into another browser tab.
Currently, both tabs are Steve.

0 0 Reply • Share ›

Michael Washington Mod > Shannon Slaton


− ⚑
10 months ago

The only way I can think of to achieve that is to have one tab, called
"Steve" that only users in the "Steve role" can see. The same with
the "Dave" tab.

0 0 Reply • Share ›

C
Curt T − ⚑
a year ago edited

I downloaded the source, and am unable to log in with the new user credentials when creating a
user from the admin tool. The UserManager.CreateAsync succeeds, and creates a user in the
AspNetUsers table. However, I cannot login with the new user credentials. Can anyone else
create a new user with the admin screen? I am able to create an account with the default
"register" screen.

0 0 Reply • Share ›

Michael Washington Mod > Curt T


− ⚑
a year ago

This code is outdated. It defiantly worked but was never tested with the latest .Net
Core. There are no plans to update it because the recommended method is to use
Azure B2C (see: Blazor Azure B2C User And Group Management)

0 0 Reply • Share ›

C
Curt T
a year ago
> Michael Washington
− ⚑

I figured it out, the default identity configuration requires email confirmation


to log in. For the new IdentityUser, I added "EmailConfirmed = true" and it
works as expected. Thanks for the sample code, it was very helpful.

1 0 Reply • Share ›

A
Aarin − ⚑
a year ago

Love this. How would one go about grabbing the roles for the current logged in user and
displaying them in one of the columns, and also save the assigned role from the save user
module?

0 0 Reply • Share ›

Michael Washington Mod > Aarin


− ⚑
a year ago

Sorry I don't have an example.

0 0 Reply • Share ›

ShockWave − ⚑
2 years ago edited

Save function is now working for me

async Task SaveUser()


{
try
{
if (objUser.Id != "")
{
var user = await _UserManager.FindByIdAsync(objUser.Id);
user.Email = objUser.Email;
await _UserManager.UpdateAsync(user);
if (objUser.PasswordHash != "*****")
{
var resetToken =
await _UserManager.GeneratePasswordResetTokenAsync(user);
var passworduser =
await _UserManager.ResetPasswordAsync(

see more

0 0 Reply • Share ›

ShockWave > ShockWave


− ⚑
2 years ago

Nevermind i had bad typo in onclick

1 0 Reply • Share ›

Okily Dokily − ⚑
2 years ago

How are you able to inject the usermanager and use usermanager.create(). I thought that you
couldn't do that in blazor??? I understand how you can use the razor pages class to create
users because that uses razor pages instead of blazor. I have not been able to successfully use
the usermanager so this walk through is different from what i've experienced and read about
blazor.

0 0 Reply • Share ›

Michael Washington Mod > Okily Dokily


− ⚑
2 years ago

This is Blazor Server so that may be the difference.

0 0 Reply • Share ›

Okily Dokily > Michael Washington


− ⚑
2 years ago

No I'm using blazor server. I was able to access the user manager, after I
changed services.addidentity to services.adddefaultidentity or at least that
was what enabled my oath login to work again. (so maybe that was a
separate issue) If that is why then this note is misleading
https://docs.microsoft.com/.... I was not able to access the getuserlogininfo
method? Maybe that is something that can only be done in the razor pages
scaffolding?

0 0 Reply • Share ›

You might also like