Now let's implement the authentication part. Previously, I used ASP.NET Core Web API with Blazor. Upon the user's first successful login, I stored permissions like Role and Claim in a JWT on the backend, saved the JWT in the browser's LocalStorage, and then the frontend rewrote AuthenticationStateProvider to check the JWT in LocalStorage. Then AuthenticationState was passed as a CascadingParameter down to various Components. This way, we didn't need to constantly exchange data with the backend—it was a valuable experience that gave me a deep understanding of authentication. This time, I'll try ASP.NET Core's own Identity.
First, go to NuGet and download three packages: Microsoft.AspNetCore.Identity.EntityFrameworkCore, Microsoft.AspNetCore.Identity.UI, and Microsoft.VisualStudio.Web.CodeGeneration.Design. The first one is essential for Identity. If you want to implement JWT yourself, you only need the first package plus JWT-related packages (e.g., Microsoft.AspNetCore.Authentication.JwtBearer). The latter two packages allow ASP.NET Core Identity to generate built-in Identity pages for us.
Next, go to BlazorServer.Models's AppDbContext and change the inherited DbContext to IdentityDbContext. This means the DB we use from now on is related to Identity.

Right-click the BlazorServer project, select Add, then New Scaffolded Item, switch to the Identity tab, and choose Identity.


Check Override all files and select AppDbContext as the Data context class. Note: if you didn't change the inherited class to IdentityDbContext earlier, AppDbContext won't be available. You'll have to click the + on the right to add a new IdentityDbContext.

At this point, you might encounter an error like FileUpload.OnInitializedAsync(): no suitable method found to override. This is usually a Visual Studio issue. Simply comment out that section and repeat the previous step.


Then go to Program.cs and add the authentication service. Identity stores authentication information in cookies by default.

Next, run two commands in the Package Manager Console: Add-Migration IdentitySupport to add a new Migration, and Update-Database to update the DB. Check the database, and you'll see 6 additional tables. The most commonly used ones are AspNetUsers, AspNetRoles, and AspNetUserRoles. If you handle permissions with Claim, you'll use AspNetUserClaims.

The project now has an Areas folder containing the implementation of ASP.NET Core Identity, including Login System, Account System, and Management System.

Go to NavMenu.razor and add a NavLink that leads to the Login page. In the relative path, you can omit Areas and Pages.
<div class="nav-item px-3">
<NavLink class="nav-link" href="Identity/Account/Login" Match="NavLinkMatch.All">
<span class="bi bi-file-earmark-lock2 h4 p-2 mb-0" aria-hidden="true"></span> Login
</NavLink>
</div>
After launching the website, navigate to the Login page from the left Nav. You'll see a fully functional login system including registration, login, forgot password, etc., with password rules in place. Register an account according to the rules, and the database will generate the newly registered account.

Fill in the correct email and password on the registration page, and you can view the registered user information in the AspNetUsers table:

References
- Claims-based authorization in ASP.NET Core
- Claim type and claim value in claims policy based authorization in asp net core
- ASP NET Core Identity tutorial from scratch
- Unable to resolve service for type IEmailSender while attempting to activate RegisterModel
Note: The code in this article has been refactored using .NET 6 + Visual Studio 2022. You can click the original link to compare with the refactored code. Thank you for reading and supporting the original author.