Events
Power BI DataViz World Championships
Feb 14, 4 PM - Mar 31, 4 PM
With 4 chances to enter, you could win a conference package and make it to the LIVE Grand Finale in Las Vegas
Learn moreThis browser is no longer supported.
Upgrade to Microsoft Edge to take advantage of the latest features, security updates, and technical support.
ASP.NET Core Identity scaffolding adds ASP.NET Core Identity to Blazor Web Apps and Blazor Server apps. After the scaffolder adds the Identity Razor components to the app, you can customize the components to suit your app's requirements.
Although the scaffolder generates the necessary C# code to scaffold Identity into the app, you must update the project's database with an Entity Framework (EF) Core database migration to complete the process. This article explains the steps required to migrate a database.
Inspect the changes after running the Identity scaffolder. We recommend using GitHub or another source control system that shows file changes with a revert changes feature.
Services are required when using two-factor authentication (2FA), account confirmation and password recovery, and other security features with Identity. Services or service stubs aren't generated when scaffolding Identity. Services to enable these features must be added manually.
ASP.NET Core provides ASP.NET Core Identity as a Razor class library (RCL). Applications that include Identity can apply the scaffolder to selectively add the source code contained in the Identity RCL. You might want to generate source code so you can modify the code and change the behavior. For example, you could instruct the scaffolder to generate the code used in registration. Customized Identity code overrides the default implementation provided by the Identity RCL. To gain full control of the UI and not use the default RCL, see the Create full Identity UI source section.
Applications that do not include authentication can apply the scaffolder to add the RCL Identity package. You have the option of selecting Identity code to be generated.
Although the scaffolder generates most of the necessary code, you need to update your project to complete the process. This document explains the steps needed to complete an Identity scaffolding update.
We recommend using a source control system that shows file differences and allows you to back out of changes. Inspect the changes after running the Identity scaffolder.
Services are required when using Two Factor Authentication, Account confirmation and password recovery, and other security features with Identity. Services or service stubs aren't generated when scaffolding Identity. Services to enable these features must be added manually. For example, see Require Email Confirmation.
Typically, apps created with individual accounts should not create a new data context.
This section applies to Blazor Web Apps and Blazor Server apps.
Run the Identity scaffolder:
The generated Identity database code requires EF Core Migrations. The following steps explain how to create and apply a migration to the database.
Visual Studio Connected Services are used to add an EF Core migration and update the database.
In Solution Explorer, double-click Connected Services. In the SQL Server Express LocalDB area of Service Dependencies, select the ellipsis (...
) followed by Add migration.
Give the migration a Migration name, such as CreateIdentitySchema
, which is a name that describes the migration. Wait for the database context to load in the DbContext class names field, which may take a few seconds. Select Finish to create the migration.
Select the Close button after the operation finishes.
Select the ellipsis (...
) again followed by the Update database command.
The Update database with the latest migration dialog opens. Wait for the DbContext class names field to update and for prior migrations to load, which may take a few seconds. Select the Finish button.
Select the Close button after the operation finishes.
The update database command executes the Up
method migrations that haven't been applied in a migration code file created by the scaffolder. In this case, the command executes the Up
method in the Migrations/{TIME STAMP}_{MIGRATION NAME}.cs
file, which creates the Identity tables, constraints, and indexes. The {TIME STAMP}
placeholder is a time stamp, and the {MIGRATION NAME}
placeholder is the migration name.
Client-side Blazor apps (Standalone Blazor WebAssembly) use their own Identity UI approaches and can't use ASP.NET Core Identity scaffolding.
For more information, see the Blazor Security and Identity articles.
Install the Microsoft.VisualStudio.Web.CodeGeneration.Design
NuGet package.
Note
For guidance on adding packages to .NET apps, see the articles under Install and manage packages at Package consumption workflow (NuGet documentation). Confirm correct package versions at NuGet.org.
Run the Identity scaffolder:
_Layout.cshtml
), select your existing layout page to avoid overwriting your layout with incorrect markup by the scaffolder. For example, select either:
Pages/Shared/_Layout.cshtml
for Razor Pages or Blazor Server projects with existing Razor Pages infrastructure.Views/Shared/_Layout.cshtml
for MVC projects or Blazor Server projects with existing MVC infrastructure.Contoso.Data.ApplicationDbContext
for a company named "Contoso"). To create a new user class, select the + button for User class and specify the class (for example, ContosoUser
for a company named "Contoso").The generated Identity database code requires Entity Framework (EF) Core Migrations. If a migration to generate the Identity schema hasn't been created and applied to the database, create a migration and update the database.
Visual Studio Connected Services are used to add an EF Core migration and update the database.
In Solution Explorer, double-click Connected Services. In the SQL Server Express LocalDB area of Service Dependencies, select the ellipsis (...
) followed by Add migration.
Give the migration a Migration name, such as CreateIdentitySchema
, which is a name that describes the migration. Wait for the database context to load in the DbContext class names field, which may take a few seconds. Select Finish to create the migration.
Select the Close button after the operation finishes.
Select the ellipsis (...
) again followed by the Update database command.
The Update database with the latest migration dialog opens. Wait for the DbContext class names field to update and for prior migrations to load, which may take a few seconds. Select the Finish button.
Select the Close button after the operation finishes.
The update database command executes the Up
method migrations that haven't been applied in a migration code file created by the scaffolder. In this case, the command executes the Up
method in the Migrations/{TIME STAMP}_{MIGRATION NAME}.cs
file, which creates the Identity tables, constraints, and indexes. The {TIME STAMP}
placeholder is a time stamp, and the {MIGRATION NAME}
placeholder is the migration name.
If the Identity schema has already been created but not applied to the database, only the command to update the database must be executed:
In Solution Explorer, double-click Connected Services. In the SQL Server Express LocalDB area of Service Dependencies, select the ellipsis (...
) followed by the Update database command.
The Update database with the latest migration dialog opens. Wait for the DbContext class names field to update and for prior migrations to load, which may take a few seconds. Select the Finish button.
Select the Close button after the operation finishes.
You can confirm the application of an Identity schema with the following command. The output of the command includes an "applied
" column to show which migrations are applied to the database.
In the Visual Studio Package Manager Console, execute Get-Migration
:
Get-Migration
If more than one database context exists, specify the context with the -Context
parameter.
Optional: Add the login partial (_LoginPartial
) to the layout file:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>@ViewData["Title"] - WebRPnoAuth2Auth</title>
<link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.css" />
<link rel="stylesheet" href="~/css/site.css" asp-append-version="true" />
<link rel="stylesheet" href="~/WebRPnoAuth2Auth.styles.css" asp-append-version="true" />
</head>
<body>
<header>
<nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light bg-white border-bottom box-shadow mb-3">
<div class="container">
<a class="navbar-brand" asp-area="" asp-page="/Index">WebRPnoAuth2Auth</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target=".navbar-collapse" aria-controls="navbarSupportedContent"
aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="navbar-collapse collapse d-sm-inline-flex justify-content-between">
<ul class="navbar-nav flex-grow-1">
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-page="/Index">Home</a>
</li>
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-page="/Privacy">Privacy</a>
</li>
</ul>
<partial name="_LoginPartial" />
</div>
</div>
</nav>
</header>
<div class="container">
<main role="main" class="pb-3">
@RenderBody()
</main>
</div>
<footer class="border-top footer text-muted">
<div class="container">
© 2021 - WebRPnoAuth2Auth - <a asp-area="" asp-page="/Privacy">Privacy</a>
</div>
</footer>
<script src="~/lib/jquery/dist/jquery.js"></script>
<script src="~/lib/bootstrap/dist/js/bootstrap.bundle.js"></script>
<script src="~/js/site.js" asp-append-version="true"></script>
@await RenderSectionAsync("Scripts", required: false)
</body>
</html>
Install the Microsoft.VisualStudio.Web.CodeGeneration.Design
NuGet package.
Note
For guidance on adding packages to .NET apps, see the articles under Install and manage packages at Package consumption workflow (NuGet documentation). Confirm correct package versions at NuGet.org.
Run the Identity scaffolder:
_Layout.cshtml
), select your existing layout page to avoid overwriting your layout with incorrect markup by the scaffolder. For example, select either:
Pages/Shared/_Layout.cshtml
for Razor Pages or Blazor Server projects with existing Razor Pages infrastructure.Views/Shared/_Layout.cshtml
for MVC projects or Blazor Server projects with existing MVC infrastructure.Contoso.Data.ApplicationDbContext
for a company named "Contoso"). To create a new user class, select the + button for User class and specify the class (for example, ContosoUser
for a company named "Contoso").Install the Microsoft.VisualStudio.Web.CodeGeneration.Design
NuGet package.
Note
For guidance on adding packages to .NET apps, see the articles under Install and manage packages at Package consumption workflow (NuGet documentation). Confirm correct package versions at NuGet.org.
Run the Identity scaffolder:
_Layout.cshtml
), select your existing layout page to avoid overwriting your layout with incorrect markup by the scaffolder. For example, select either:
Pages/Shared/_Layout.cshtml
for Razor Pages or Blazor Server projects with existing Razor Pages infrastructure.Views/Shared/_Layout.cshtml
for MVC projects or Blazor Server projects with existing MVC infrastructure.Contoso.Data.ApplicationDbContext
for a company named "Contoso"). To create a new user class, select the + button for User class and specify the class (for example, ContosoUser
for a company named "Contoso").Optional: Add the login partial (_LoginPartial
) to the Views/Shared/_Layout.cshtml
file:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>@ViewData["Title"] - WebRPnoAuth2Auth</title>
<link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.css" />
<link rel="stylesheet" href="~/css/site.css" asp-append-version="true" />
<link rel="stylesheet" href="~/WebRPnoAuth2Auth.styles.css" asp-append-version="true" />
</head>
<body>
<header>
<nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light bg-white border-bottom box-shadow mb-3">
<div class="container">
<a class="navbar-brand" asp-area="" asp-page="/Index">WebRPnoAuth2Auth</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target=".navbar-collapse" aria-controls="navbarSupportedContent"
aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="navbar-collapse collapse d-sm-inline-flex justify-content-between">
<ul class="navbar-nav flex-grow-1">
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-page="/Index">Home</a>
</li>
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-page="/Privacy">Privacy</a>
</li>
</ul>
<partial name="_LoginPartial" />
</div>
</div>
</nav>
</header>
<div class="container">
<main role="main" class="pb-3">
@RenderBody()
</main>
</div>
<footer class="border-top footer text-muted">
<div class="container">
© 2021 - WebRPnoAuth2Auth - <a asp-area="" asp-page="/Privacy">Privacy</a>
</div>
</footer>
<script src="~/lib/jquery/dist/jquery.js"></script>
<script src="~/lib/bootstrap/dist/js/bootstrap.bundle.js"></script>
<script src="~/js/site.js" asp-append-version="true"></script>
@await RenderSectionAsync("Scripts", required: false)
</body>
</html>
The generated Identity database code requires Entity Framework (EF) Core Migrations. If a migration to generate the Identity schema hasn't been created and applied to the database, create a migration and update the database.
Visual Studio Connected Services are used to add an EF Core migration and update the database.
In Solution Explorer, double-click Connected Services. In the SQL Server Express LocalDB area of Service Dependencies, select the ellipsis (...
) followed by Add migration.
Give the migration a Migration name, such as CreateIdentitySchema
, which is a name that describes the migration. Wait for the database context to load in the DbContext class names field, which may take a few seconds. Select Finish to create the migration.
Select the Close button after the operation finishes.
Select the ellipsis (...
) again followed by the Update database command.
The Update database with the latest migration dialog opens. Wait for the DbContext class names field to update and for prior migrations to load, which may take a few seconds. Select the Finish button.
Select the Close button after the operation finishes.
The update database command executes the Up
method migrations that haven't been applied in a migration code file created by the scaffolder. In this case, the command executes the Up
method in the Migrations/{TIME STAMP}_{MIGRATION NAME}.cs
file, which creates the Identity tables, constraints, and indexes. The {TIME STAMP}
placeholder is a time stamp, and the {MIGRATION NAME}
placeholder is the migration name.
If the Identity schema has already been created but not applied to the database, only the command to update the database must be executed:
In Solution Explorer, double-click Connected Services. In the SQL Server Express LocalDB area of Service Dependencies, select the ellipsis (...
) followed by the Update database command.
The Update database with the latest migration dialog opens. Wait for the DbContext class names field to update and for prior migrations to load, which may take a few seconds. Select the Finish button.
Select the Close button after the operation finishes.
You can confirm the application of an Identity schema with the following command. The output of the command includes an "applied
" column to show which migrations are applied to the database.
In the Visual Studio Package Manager Console, execute Get-Migration
:
Get-Migration
If more than one database context exists, specify the context with the -Context
parameter.
Add MapRazorPages
to Program.cs
as shown in the following highlighted code:
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using WebMVCauth.Data;
var builder = WebApplication.CreateBuilder(args);
var connectionString = builder.Configuration.GetConnectionString("DefaultConnection");
builder.Services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(connectionString));
builder.Services.AddDatabaseDeveloperPageExceptionFilter();
builder.Services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)
.AddEntityFrameworkStores<ApplicationDbContext>();
builder.Services.AddControllersWithViews();
var app = builder.Build();
if (app.Environment.IsDevelopment())
{
app.UseMigrationsEndPoint();
}
else
{
app.UseExceptionHandler("/Home/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
app.MapRazorPages();
app.Run();
Install the Microsoft.VisualStudio.Web.CodeGeneration.Design
NuGet package.
Note
For guidance on adding packages to .NET apps, see the articles under Install and manage packages at Package consumption workflow (NuGet documentation). Confirm correct package versions at NuGet.org.
Run the Identity scaffolder:
_Layout.cshtml
), select your existing layout page to avoid overwriting your layout with incorrect markup by the scaffolder. For example, select either:
Pages/Shared/_Layout.cshtml
for Razor Pages or Blazor Server projects with existing Razor Pages infrastructure.Views/Shared/_Layout.cshtml
for MVC projects or Blazor Server projects with existing MVC infrastructure.Contoso.Data.ApplicationDbContext
for a company named "Contoso"). To create a new user class, select the + button for User class and specify the class (for example, ContosoUser
for a company named "Contoso").To maintain full control of the Identity UI, run the Identity scaffolder and select Override all files.
If PasswordOptions are configured in Startup.ConfigureServices
, [StringLength]
attribute configuration might be required for the Password
property in scaffolded Identity pages. InputModel
Password
properties are found in the following files:
Areas/Identity/Pages/Account/Register.cshtml.cs
Areas/Identity/Pages/Account/ResetPassword.cshtml.cs
This section shows how to disable the register page but the approach can be used to disable any page.
To disable user registration:
Scaffold Identity. Include Account.Register, Account.Login, and Account.RegisterConfirmation. For example:
dotnet aspnet-codegenerator identity -dc RPauth.Data.ApplicationDbContext --files "Account.Register;Account.Login;Account.RegisterConfirmation"
Update Areas/Identity/Pages/Account/Register.cshtml.cs
so users can't register from this endpoint:
public class RegisterModel : PageModel
{
public IActionResult OnGet()
{
return RedirectToPage("Login");
}
public IActionResult OnPost()
{
return RedirectToPage("Login");
}
}
Update Areas/Identity/Pages/Account/Register.cshtml
to be consistent with the preceding changes:
@page
@model RegisterModel
@{
ViewData["Title"] = "Go to Login";
}
<h1>@ViewData["Title"]</h1>
<li class="nav-item">
<a class="nav-link text-dark" asp-area="Identity" asp-page="/Account/Login">Login</a>
</li>
Comment out or remove the registration link from Areas/Identity/Pages/Account/Login.cshtml
@*
<p>
<a asp-page="./Register" asp-route-returnUrl="@Model.ReturnUrl">Register as a new user</a>
</p>
*@
Update the Areas/Identity/Pages/Account/RegisterConfirmation
page.
PageModel
:[AllowAnonymous]
public class RegisterConfirmationModel : PageModel
{
public IActionResult OnGet()
{
return Page();
}
}
Provide a mechanism to add users outside the web app. Options to add users include:
The following code outlines one approach to adding users:
public class Program
{
public static void Main(string[] args)
{
var host = CreateHostBuilder(args).Build();
using (var scope = host.Services.CreateScope())
{
var services = scope.ServiceProvider;
try
{
var context = services.GetRequiredService<AppDbCntx>();
context.Database.Migrate();
var config = host.Services.GetRequiredService<IConfiguration>();
var userList = config.GetSection("userList").Get<List<string>>();
SeedData.Initialize(services, userList).Wait();
}
catch (Exception ex)
{
var logger = services.GetRequiredService<ILogger<Program>>();
logger.LogError(ex, "An error occurred adding users.");
}
}
host.Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
The following code outlines adding a user:
public static async Task Initialize(IServiceProvider serviceProvider,
List<string> userList)
{
var userManager = serviceProvider.GetService<UserManager<IdentityUser>>();
foreach (var userName in userList)
{
var userPassword = GenerateSecurePassword();
var userId = await EnsureUser(userManager, userName, userPassword);
NotifyUser(userName, userPassword);
}
}
private static async Task<string> EnsureUser(UserManager<IdentityUser> userManager,
string userName, string userPassword)
{
var user = await userManager.FindByNameAsync(userName);
if (user == null)
{
user = new IdentityUser(userName)
{
EmailConfirmed = true
};
await userManager.CreateAsync(user, userPassword);
}
return user.Id;
}
A similar approach can be followed for production scenarios.
To prevent publishing static Identity assets to the web root, see Introduction to Identity on ASP.NET Core.
ASP.NET Core provides ASP.NET Core Identity as a Razor class library (RCL). Applications that include Identity can apply the scaffolder to selectively add the source code contained in the Identity RCL. You might want to generate source code so you can modify the code and change the behavior. For example, you could instruct the scaffolder to generate the code used in registration. Generated code takes precedence over the same code in the Identity RCL. To gain full control of the UI and not use the default RCL, see the section Create full Identity UI source.
Applications that do not include authentication can apply the scaffolder to add the RCL Identity package. You have the option of selecting Identity code to be generated.
Although the scaffolder generates most of the necessary code, you need to update your project to complete the process. This document explains the steps needed to complete an Identity scaffolding update.
We recommend using a source control system that shows file differences and allows you to back out of changes. Inspect the changes after running the Identity scaffolder.
Services are required when using Two Factor Authentication, Account confirmation and password recovery, and other security features with Identity. Services or service stubs aren't generated when scaffolding Identity. Services to enable these features must be added manually. For example, see Require Email Confirmation.
Typically, apps created with individual accounts should not create a new data context.
Install the Microsoft.VisualStudio.Web.CodeGeneration.Design
NuGet package.
Note
For guidance on adding packages to .NET apps, see the articles under Install and manage packages at Package consumption workflow (NuGet documentation). Confirm correct package versions at NuGet.org.
Run the Identity scaffolder:
_Layout.cshtml
), select your existing layout page to avoid overwriting your layout with incorrect markup by the scaffolder. For example, select either:
Pages/Shared/_Layout.cshtml
for Razor Pages or Blazor Server projects with existing Razor Pages infrastructure.Views/Shared/_Layout.cshtml
for MVC projects or Blazor Server projects with existing MVC infrastructure.Contoso.Data.ApplicationDbContext
for a company named "Contoso"). To create a new user class, select the + button for User class and specify the class (for example, ContosoUser
for a company named "Contoso").The generated Identity database code requires Entity Framework (EF) Core Migrations. If a migration to generate the Identity schema hasn't been created and applied to the database, create a migration and update the database.
Visual Studio Connected Services are used to add an EF Core migration and update the database.
In Solution Explorer, double-click Connected Services. In the SQL Server Express LocalDB area of Service Dependencies, select the ellipsis (...
) followed by Add migration.
Give the migration a Migration name, such as CreateIdentitySchema
, which is a name that describes the migration. Wait for the database context to load in the DbContext class names field, which may take a few seconds. Select Finish to create the migration.
Select the Close button after the operation finishes.
Select the ellipsis (...
) again followed by the Update database command.
The Update database with the latest migration dialog opens. Wait for the DbContext class names field to update and for prior migrations to load, which may take a few seconds. Select the Finish button.
Select the Close button after the operation finishes.
The update database command executes the Up
method migrations that haven't been applied in a migration code file created by the scaffolder. In this case, the command executes the Up
method in the Migrations/{TIME STAMP}_{MIGRATION NAME}.cs
file, which creates the Identity tables, constraints, and indexes. The {TIME STAMP}
placeholder is a time stamp, and the {MIGRATION NAME}
placeholder is the migration name.
If the Identity schema has already been created but not applied to the database, only the command to update the database must be executed:
In Solution Explorer, double-click Connected Services. In the SQL Server Express LocalDB area of Service Dependencies, select the ellipsis (...
) followed by the Update database command.
The Update database with the latest migration dialog opens. Wait for the DbContext class names field to update and for prior migrations to load, which may take a few seconds. Select the Finish button.
Select the Close button after the operation finishes.
You can confirm the application of an Identity schema with the following command. The output of the command includes an "applied
" column to show which migrations are applied to the database.
In the Visual Studio Package Manager Console, execute Get-Migration
:
Get-Migration
If more than one database context exists, specify the context with the -Context
parameter.
Optional: Add the login partial (_LoginPartial
) to the layout file:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>@ViewData["Title"] - WebRPnoAuth2Auth</title>
<link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.css" />
<link rel="stylesheet" href="~/css/site.css" asp-append-version="true" />
<link rel="stylesheet" href="~/WebRPnoAuth2Auth.styles.css" asp-append-version="true" />
</head>
<body>
<header>
<nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light bg-white border-bottom box-shadow mb-3">
<div class="container">
<a class="navbar-brand" asp-area="" asp-page="/Index">WebRPnoAuth2Auth</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target=".navbar-collapse" aria-controls="navbarSupportedContent"
aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="navbar-collapse collapse d-sm-inline-flex justify-content-between">
<ul class="navbar-nav flex-grow-1">
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-page="/Index">Home</a>
</li>
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-page="/Privacy">Privacy</a>
</li>
</ul>
<partial name="_LoginPartial" />
</div>
</div>
</nav>
</header>
<div class="container">
<main role="main" class="pb-3">
@RenderBody()
</main>
</div>
<footer class="border-top footer text-muted">
<div class="container">
© 2021 - WebRPnoAuth2Auth - <a asp-area="" asp-page="/Privacy">Privacy</a>
</div>
</footer>
<script src="~/lib/jquery/dist/jquery.js"></script>
<script src="~/lib/bootstrap/dist/js/bootstrap.bundle.js"></script>
<script src="~/js/site.js" asp-append-version="true"></script>
@await RenderSectionAsync("Scripts", required: false)
</body>
</html>
Install the Microsoft.VisualStudio.Web.CodeGeneration.Design
NuGet package.
Note
For guidance on adding packages to .NET apps, see the articles under Install and manage packages at Package consumption workflow (NuGet documentation). Confirm correct package versions at NuGet.org.
Run the Identity scaffolder:
_Layout.cshtml
), select your existing layout page to avoid overwriting your layout with incorrect markup by the scaffolder. For example, select either:
Pages/Shared/_Layout.cshtml
for Razor Pages or Blazor Server projects with existing Razor Pages infrastructure.Views/Shared/_Layout.cshtml
for MVC projects or Blazor Server projects with existing MVC infrastructure.Contoso.Data.ApplicationDbContext
for a company named "Contoso"). To create a new user class, select the + button for User class and specify the class (for example, ContosoUser
for a company named "Contoso").Install the Microsoft.VisualStudio.Web.CodeGeneration.Design
NuGet package.
Note
For guidance on adding packages to .NET apps, see the articles under Install and manage packages at Package consumption workflow (NuGet documentation). Confirm correct package versions at NuGet.org.
Run the Identity scaffolder:
_Layout.cshtml
), select your existing layout page to avoid overwriting your layout with incorrect markup by the scaffolder. For example, select either:
Pages/Shared/_Layout.cshtml
for Razor Pages or Blazor Server projects with existing Razor Pages infrastructure.Views/Shared/_Layout.cshtml
for MVC projects or Blazor Server projects with existing MVC infrastructure.Contoso.Data.ApplicationDbContext
for a company named "Contoso"). To create a new user class, select the + button for User class and specify the class (for example, ContosoUser
for a company named "Contoso").Optional: Add the login partial (_LoginPartial
) to the Views/Shared/_Layout.cshtml
file:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>@ViewData["Title"] - WebRPnoAuth2Auth</title>
<link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.css" />
<link rel="stylesheet" href="~/css/site.css" asp-append-version="true" />
<link rel="stylesheet" href="~/WebRPnoAuth2Auth.styles.css" asp-append-version="true" />
</head>
<body>
<header>
<nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light bg-white border-bottom box-shadow mb-3">
<div class="container">
<a class="navbar-brand" asp-area="" asp-page="/Index">WebRPnoAuth2Auth</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target=".navbar-collapse" aria-controls="navbarSupportedContent"
aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="navbar-collapse collapse d-sm-inline-flex justify-content-between">
<ul class="navbar-nav flex-grow-1">
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-page="/Index">Home</a>
</li>
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-page="/Privacy">Privacy</a>
</li>
</ul>
<partial name="_LoginPartial" />
</div>
</div>
</nav>
</header>
<div class="container">
<main role="main" class="pb-3">
@RenderBody()
</main>
</div>
<footer class="border-top footer text-muted">
<div class="container">
© 2021 - WebRPnoAuth2Auth - <a asp-area="" asp-page="/Privacy">Privacy</a>
</div>
</footer>
<script src="~/lib/jquery/dist/jquery.js"></script>
<script src="~/lib/bootstrap/dist/js/bootstrap.bundle.js"></script>
<script src="~/js/site.js" asp-append-version="true"></script>
@await RenderSectionAsync("Scripts", required: false)
</body>
</html>
The generated Identity database code requires Entity Framework (EF) Core Migrations. If a migration to generate the Identity schema hasn't been created and applied to the database, create a migration and update the database.
Visual Studio Connected Services are used to add an EF Core migration and update the database.
In Solution Explorer, double-click Connected Services. In the SQL Server Express LocalDB area of Service Dependencies, select the ellipsis (...
) followed by Add migration.
Give the migration a Migration name, such as CreateIdentitySchema
, which is a name that describes the migration. Wait for the database context to load in the DbContext class names field, which may take a few seconds. Select Finish to create the migration.
Select the Close button after the operation finishes.
Select the ellipsis (...
) again followed by the Update database command.
The Update database with the latest migration dialog opens. Wait for the DbContext class names field to update and for prior migrations to load, which may take a few seconds. Select the Finish button.
Select the Close button after the operation finishes.
The update database command executes the Up
method migrations that haven't been applied in a migration code file created by the scaffolder. In this case, the command executes the Up
method in the Migrations/{TIME STAMP}_{MIGRATION NAME}.cs
file, which creates the Identity tables, constraints, and indexes. The {TIME STAMP}
placeholder is a time stamp, and the {MIGRATION NAME}
placeholder is the migration name.
If the Identity schema has already been created but not applied to the database, only the command to update the database must be executed:
In Solution Explorer, double-click Connected Services. In the SQL Server Express LocalDB area of Service Dependencies, select the ellipsis (...
) followed by the Update database command.
The Update database with the latest migration dialog opens. Wait for the DbContext class names field to update and for prior migrations to load, which may take a few seconds. Select the Finish button.
Select the Close button after the operation finishes.
You can confirm the application of an Identity schema with the following command. The output of the command includes an "applied
" column to show which migrations are applied to the database.
In the Visual Studio Package Manager Console, execute Get-Migration
:
Get-Migration
If more than one database context exists, specify the context with the -Context
parameter.
Add MapRazorPages
to Program.cs
as shown in the following highlighted code:
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using WebMVCauth.Data;
var builder = WebApplication.CreateBuilder(args);
var connectionString = builder.Configuration.GetConnectionString("DefaultConnection");
builder.Services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(connectionString));
builder.Services.AddDatabaseDeveloperPageExceptionFilter();
builder.Services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)
.AddEntityFrameworkStores<ApplicationDbContext>();
builder.Services.AddControllersWithViews();
var app = builder.Build();
if (app.Environment.IsDevelopment())
{
app.UseMigrationsEndPoint();
}
else
{
app.UseExceptionHandler("/Home/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
app.MapRazorPages();
app.Run();
Install the Microsoft.VisualStudio.Web.CodeGeneration.Design
NuGet package.
Note
For guidance on adding packages to .NET apps, see the articles under Install and manage packages at Package consumption workflow (NuGet documentation). Confirm correct package versions at NuGet.org.
Run the Identity scaffolder:
_Layout.cshtml
), select your existing layout page to avoid overwriting your layout with incorrect markup by the scaffolder. For example, select either:
Pages/Shared/_Layout.cshtml
for Razor Pages or Blazor Server projects with existing Razor Pages infrastructure.Views/Shared/_Layout.cshtml
for MVC projects or Blazor Server projects with existing MVC infrastructure.Contoso.Data.ApplicationDbContext
for a company named "Contoso"). To create a new user class, select the + button for User class and specify the class (for example, ContosoUser
for a company named "Contoso").Install the Microsoft.VisualStudio.Web.CodeGeneration.Design
NuGet package.
Note
For guidance on adding packages to .NET apps, see the articles under Install and manage packages at Package consumption workflow (NuGet documentation). Confirm correct package versions at NuGet.org.
Run the Identity scaffolder:
_Layout.cshtml
), select your existing layout page to avoid overwriting your layout with incorrect markup by the scaffolder. For example, select either:
Pages/Shared/_Layout.cshtml
for Razor Pages or Blazor Server projects with existing Razor Pages infrastructure.Views/Shared/_Layout.cshtml
for MVC projects or Blazor Server projects with existing MVC infrastructure.Contoso.Data.ApplicationDbContext
for a company named "Contoso"). To create a new user class, select the + button for User class and specify the class (for example, ContosoUser
for a company named "Contoso").The generated Identity database code requires Entity Framework (EF) Core Migrations. If a migration to generate the Identity schema hasn't been created and applied to the database, create a migration and update the database.
Visual Studio Connected Services are used to add an EF Core migration and update the database.
In Solution Explorer, double-click Connected Services. In the SQL Server Express LocalDB area of Service Dependencies, select the ellipsis (...
) followed by Add migration.
Give the migration a Migration name, such as CreateIdentitySchema
, which is a name that describes the migration. Wait for the database context to load in the DbContext class names field, which may take a few seconds. Select Finish to create the migration.
Select the Close button after the operation finishes.
Select the ellipsis (...
) again followed by the Update database command.
The Update database with the latest migration dialog opens. Wait for the DbContext class names field to update and for prior migrations to load, which may take a few seconds. Select the Finish button.
Select the Close button after the operation finishes.
The update database command executes the Up
method migrations that haven't been applied in a migration code file created by the scaffolder. In this case, the command executes the Up
method in the Migrations/{TIME STAMP}_{MIGRATION NAME}.cs
file, which creates the Identity tables, constraints, and indexes. The {TIME STAMP}
placeholder is a time stamp, and the {MIGRATION NAME}
placeholder is the migration name.
If the Identity schema has already been created but not applied to the database, only the command to update the database must be executed:
In Solution Explorer, double-click Connected Services. In the SQL Server Express LocalDB area of Service Dependencies, select the ellipsis (...
) followed by the Update database command.
The Update database with the latest migration dialog opens. Wait for the DbContext class names field to update and for prior migrations to load, which may take a few seconds. Select the Finish button.
Select the Close button after the operation finishes.
You can confirm the application of an Identity schema with the following command. The output of the command includes an "applied
" column to show which migrations are applied to the database.
In the Visual Studio Package Manager Console, execute Get-Migration
:
Get-Migration
If more than one database context exists, specify the context with the -Context
parameter.
Because server-side Blazor apps use Razor Pages Identity pages, the styling of the UI changes when a visitor navigates between Identity pages and components. You have two options to address the incongruous styles:
ASP.NET Core Identity is designed to work in the context of HTTP request and response communication, which isn't the primary client-server communication model in Blazor apps. ASP.NET Core apps that use ASP.NET Core Identity for user management should use Razor Pages instead of Razor components for Identity-related UI, such as user registration, login, logout, and other user management tasks.
Because SignInManager<TUser> and UserManager<TUser> aren't supported in Razor components, we recommend using web API to manage Identity actions from Razor components via a server-side Identity-enabled ASP.NET Core app. For guidance on creating web APIs for Blazor apps, see Call a web API from an ASP.NET Core Blazor app.
An approach to using Razor components for Identity instead of Razor pages is to build your own custom Identity Razor components, but Microsoft doesn't recommend or support the approach. For additional context, explore the following discussions. In the following discussions, code examples in issue comments and code examples cross-linked in non-Microsoft GitHub repositories aren't supported by Microsoft but might be helpful to some developers:
SigninManager<T>
not being supported in Razor Components (dotnet/aspnetcore #34095)For additional assistance when seeking to build custom Identity Razor components or searching for third-party Razor components, we recommend the following resources:
blazor
) (Public support forum)The Identity pages layout and styles can be modified to produce pages that use styles similar to the default Blazor theme. This approach isn't covered by the documentation.
Client-side Blazor apps use their own Identity UI approaches and can't use ASP.NET Core Identity scaffolding. Server-side ASP.NET Core apps of hosted Blazor solutions can follow the Razor Pages/MVC guidance in this article and are configured just like any other type of ASP.NET Core app that supports Identity.
The Blazor framework doesn't include Razor component versions of Identity UI pages. Identity UI Razor components can be custom built or obtained from unsupported third-party sources.
For more information, see the Blazor Security and Identity articles.
To maintain full control of the Identity UI, run the Identity scaffolder and select Override all files.
If PasswordOptions are configured in Startup.ConfigureServices
, [StringLength]
attribute configuration might be required for the Password
property in scaffolded Identity pages. InputModel
Password
properties are found in the following files:
Areas/Identity/Pages/Account/Register.cshtml.cs
Areas/Identity/Pages/Account/ResetPassword.cshtml.cs
This section shows how to disable the register page but the approach can be used to disable any page.
To disable user registration:
Scaffold Identity. Include Account.Register, Account.Login, and Account.RegisterConfirmation. For example:
dotnet aspnet-codegenerator identity -dc RPauth.Data.ApplicationDbContext --files "Account.Register;Account.Login;Account.RegisterConfirmation"
Update Areas/Identity/Pages/Account/Register.cshtml.cs
so users can't register from this endpoint:
public class RegisterModel : PageModel
{
public IActionResult OnGet()
{
return RedirectToPage("Login");
}
public IActionResult OnPost()
{
return RedirectToPage("Login");
}
}
Update Areas/Identity/Pages/Account/Register.cshtml
to be consistent with the preceding changes:
@page
@model RegisterModel
@{
ViewData["Title"] = "Go to Login";
}
<h1>@ViewData["Title"]</h1>
<li class="nav-item">
<a class="nav-link text-dark" asp-area="Identity" asp-page="/Account/Login">Login</a>
</li>
Comment out or remove the registration link from Areas/Identity/Pages/Account/Login.cshtml
@*
<p>
<a asp-page="./Register" asp-route-returnUrl="@Model.ReturnUrl">Register as a new user</a>
</p>
*@
Update the Areas/Identity/Pages/Account/RegisterConfirmation
page.
PageModel
:[AllowAnonymous]
public class RegisterConfirmationModel : PageModel
{
public IActionResult OnGet()
{
return Page();
}
}
Provide a mechanism to add users outside the web app. Options to add users include:
The following code outlines one approach to adding users:
public class Program
{
public static void Main(string[] args)
{
var host = CreateHostBuilder(args).Build();
using (var scope = host.Services.CreateScope())
{
var services = scope.ServiceProvider;
try
{
var context = services.GetRequiredService<AppDbCntx>();
context.Database.Migrate();
var config = host.Services.GetRequiredService<IConfiguration>();
var userList = config.GetSection("userList").Get<List<string>>();
SeedData.Initialize(services, userList).Wait();
}
catch (Exception ex)
{
var logger = services.GetRequiredService<ILogger<Program>>();
logger.LogError(ex, "An error occurred adding users.");
}
}
host.Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
The following code outlines adding a user:
public static async Task Initialize(IServiceProvider serviceProvider,
List<string> userList)
{
var userManager = serviceProvider.GetService<UserManager<IdentityUser>>();
foreach (var userName in userList)
{
var userPassword = GenerateSecurePassword();
var userId = await EnsureUser(userManager, userName, userPassword);
NotifyUser(userName, userPassword);
}
}
private static async Task<string> EnsureUser(UserManager<IdentityUser> userManager,
string userName, string userPassword)
{
var user = await userManager.FindByNameAsync(userName);
if (user == null)
{
user = new IdentityUser(userName)
{
EmailConfirmed = true
};
await userManager.CreateAsync(user, userPassword);
}
return user.Id;
}
A similar approach can be followed for production scenarios.
To prevent publishing static Identity assets to the web root, see Introduction to Identity on ASP.NET Core.
ASP.NET Core provides ASP.NET Core Identity as a Razor class library (RCL). Applications that include Identity can apply the scaffolder to selectively add the source code contained in the Identity RCL. You might want to generate source code so you can modify the code and change the behavior. For example, you could instruct the scaffolder to generate the code used in registration. Generated code takes precedence over the same code in the Identity RCL. To gain full control of the UI and not use the default RCL, see the section Create full Identity UI source.
Applications that do not include authentication can apply the scaffolder to add the RCL Identity package. You have the option of selecting Identity code to be generated.
Although the scaffolder generates most of the necessary code, you need to update your project to complete the process. This document explains the steps needed to complete an Identity scaffolding update.
We recommend using a source control system that shows file differences and allows you to back out of changes. Inspect the changes after running the Identity scaffolder.
Services are required when using Two Factor Authentication, Account confirmation and password recovery, and other security features with Identity. Services or service stubs aren't generated when scaffolding Identity. Services to enable these features must be added manually. For example, see Require Email Confirmation.
When scaffolding Identity with a new data context into a project with existing individual accounts, open Startup.ConfigureServices
and remove the calls to:
AddDbContext
AddDefaultIdentity
For example, AddDbContext
and AddDefaultIdentity
are commented out in the following code:
public void ConfigureServices(IServiceCollection services)
{
//services.AddDbContext<ApplicationDbContext>(options =>
// options.UseSqlServer(
// Configuration.GetConnectionString("DefaultConnection")));
//services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)
// .AddEntityFrameworkStores<ApplicationDbContext>();
services.AddControllersWithViews();
services.AddRazorPages();
}
The preceding code comments out the code that is duplicated in Areas/Identity/IdentityHostingStartup.cs
Typically, apps created with individual accounts should not create a new data context.
Run the Identity scaffolder:
_Layout.cshtml
), select your existing layout page to avoid overwriting your layout with incorrect markup by the scaffolder. For example, select either:
Pages/Shared/_Layout.cshtml
for Razor Pages or Blazor Server projects with existing Razor Pages infrastructure.Views/Shared/_Layout.cshtml
for MVC projects or Blazor Server projects with existing MVC infrastructure.Contoso.Data.ApplicationDbContext
for a company named "Contoso"). To create a new user class, select the + button for User class and specify the class (for example, ContosoUser
for a company named "Contoso").Update the Startup
class with code similar to the following:
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews();
services.AddRazorPages();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseDatabaseErrorPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
endpoints.MapRazorPages();
});
}
}
UseHsts
is recommended but not required. For more information, see HTTP Strict Transport Security Protocol.
The generated Identity database code requires Entity Framework (EF) Core Migrations. If a migration to generate the Identity schema hasn't been created and applied to the database, create a migration and update the database.
Visual Studio Connected Services are used to add an EF Core migration and update the database.
In Solution Explorer, double-click Connected Services. In the SQL Server Express LocalDB area of Service Dependencies, select the ellipsis (...
) followed by Add migration.
Give the migration a Migration name, such as CreateIdentitySchema
, which is a name that describes the migration. Wait for the database context to load in the DbContext class names field, which may take a few seconds. Select Finish to create the migration.
Select the Close button after the operation finishes.
Select the ellipsis (...
) again followed by the Update database command.
The Update database with the latest migration dialog opens. Wait for the DbContext class names field to update and for prior migrations to load, which may take a few seconds. Select the Finish button.
Select the Close button after the operation finishes.
The update database command executes the Up
method migrations that haven't been applied in a migration code file created by the scaffolder. In this case, the command executes the Up
method in the Migrations/{TIME STAMP}_{MIGRATION NAME}.cs
file, which creates the Identity tables, constraints, and indexes. The {TIME STAMP}
placeholder is a time stamp, and the {MIGRATION NAME}
placeholder is the migration name.
If the Identity schema has already been created but not applied to the database, only the command to update the database must be executed:
In Solution Explorer, double-click Connected Services. In the SQL Server Express LocalDB area of Service Dependencies, select the ellipsis (...
) followed by the Update database command.
The Update database with the latest migration dialog opens. Wait for the DbContext class names field to update and for prior migrations to load, which may take a few seconds. Select the Finish button.
Select the Close button after the operation finishes.
You can confirm the application of an Identity schema with the following command. The output of the command includes an "applied
" column to show which migrations are applied to the database.
In the Visual Studio Package Manager Console, execute Get-Migration
:
Get-Migration
If more than one database context exists, specify the context with the -Context
parameter.
Run the Identity scaffolder:
_Layout.cshtml
), select your existing layout page to avoid overwriting your layout with incorrect markup by the scaffolder. For example, select either:
Pages/Shared/_Layout.cshtml
for Razor Pages or Blazor Server projects with existing Razor Pages infrastructure.Views/Shared/_Layout.cshtml
for MVC projects or Blazor Server projects with existing MVC infrastructure.Contoso.Data.ApplicationDbContext
for a company named "Contoso"). To create a new user class, select the + button for User class and specify the class (for example, ContosoUser
for a company named "Contoso").Identity is configured in Areas/Identity/IdentityHostingStartup.cs
. For more information, see IHostingStartup
.
The generated Identity database code requires Entity Framework (EF) Core Migrations. If a migration to generate the Identity schema hasn't been created and applied to the database, create a migration and update the database.
Visual Studio Connected Services are used to add an EF Core migration and update the database.
In Solution Explorer, double-click Connected Services. In the SQL Server Express LocalDB area of Service Dependencies, select the ellipsis (...
) followed by Add migration.
Give the migration a Migration name, such as CreateIdentitySchema
, which is a name that describes the migration. Wait for the database context to load in the DbContext class names field, which may take a few seconds. Select Finish to create the migration.
Select the Close button after the operation finishes.
Select the ellipsis (...
) again followed by the Update database command.
The Update database with the latest migration dialog opens. Wait for the DbContext class names field to update and for prior migrations to load, which may take a few seconds. Select the Finish button.
Select the Close button after the operation finishes.
The update database command executes the Up
method migrations that haven't been applied in a migration code file created by the scaffolder. In this case, the command executes the Up
method in the Migrations/{TIME STAMP}_{MIGRATION NAME}.cs
file, which creates the Identity tables, constraints, and indexes. The {TIME STAMP}
placeholder is a time stamp, and the {MIGRATION NAME}
placeholder is the migration name.
If the Identity schema has already been created but not applied to the database, only the command to update the database must be executed:
In Solution Explorer, double-click Connected Services. In the SQL Server Express LocalDB area of Service Dependencies, select the ellipsis (...
) followed by the Update database command.
The Update database with the latest migration dialog opens. Wait for the DbContext class names field to update and for prior migrations to load, which may take a few seconds. Select the Finish button.
Select the Close button after the operation finishes.
You can confirm the application of an Identity schema with the following command. The output of the command includes an "applied
" column to show which migrations are applied to the database.
In the Visual Studio Package Manager Console, execute Get-Migration
:
Get-Migration
If more than one database context exists, specify the context with the -Context
parameter.
Update the Startup
class with code similar to the following:
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
services.AddRazorPages();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseDatabaseErrorPage();
}
else
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapRazorPages();
});
}
}
UseHsts
is recommended but not required. For more information, see HTTP Strict Transport Security Protocol.
Optional: Add the login partial (_LoginPartial
) to the layout file:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>@ViewData["Title"] - WebRP</title>
<link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.css" />
<link rel="stylesheet" href="~/css/site.css" />
</head>
<body>
<header>
<nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light bg-white border-bottom box-shadow mb-3">
<div class="container">
<a class="navbar-brand" asp-area="" asp-page="/Index">WebRP</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target=".navbar-collapse" aria-controls="navbarSupportedContent"
aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="navbar-collapse collapse d-sm-inline-flex flex-sm-row-reverse">
<partial name="_LoginPartial" />
<ul class="navbar-nav flex-grow-1">
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-page="/Index">Home</a>
</li>
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-page="/Privacy">Privacy</a>
</li>
</ul>
</div>
</div>
</nav>
</header>
<div class="container">
<main role="main" class="pb-3">
@RenderBody()
</main>
</div>
<footer class="border-top footer text-muted">
<div class="container">
© 2019 - WebRP - <a asp-area="" asp-page="/Privacy">Privacy</a>
</div>
</footer>
<script src="~/lib/jquery/dist/jquery.js"></script>
<script src="~/lib/bootstrap/dist/js/bootstrap.bundle.js"></script>
<script src="~/js/site.js" asp-append-version="true"></script>
@RenderSection("Scripts", required: false)
</body>
</html>
Run the Identity scaffolder:
_Layout.cshtml
), select your existing layout page to avoid overwriting your layout with incorrect markup by the scaffolder. For example, select either:
Pages/Shared/_Layout.cshtml
for Razor Pages or Blazor Server projects with existing Razor Pages infrastructure.Views/Shared/_Layout.cshtml
for MVC projects or Blazor Server projects with existing MVC infrastructure.Contoso.Data.ApplicationDbContext
for a company named "Contoso"). To create a new user class, select the + button for User class and specify the class (for example, ContosoUser
for a company named "Contoso").Some Identity options are configured in Areas/Identity/IdentityHostingStartup.cs
. For more information, see IHostingStartup
.
Run the Identity scaffolder:
_Layout.cshtml
), select your existing layout page to avoid overwriting your layout with incorrect markup by the scaffolder. For example, select either:
Pages/Shared/_Layout.cshtml
for Razor Pages or Blazor Server projects with existing Razor Pages infrastructure.Views/Shared/_Layout.cshtml
for MVC projects or Blazor Server projects with existing MVC infrastructure.Contoso.Data.ApplicationDbContext
for a company named "Contoso"). To create a new user class, select the + button for User class and specify the class (for example, ContosoUser
for a company named "Contoso").Optional: Add the login partial (_LoginPartial
) to the Views/Shared/_Layout.cshtml
file:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>@ViewData["Title"] - WebRP</title>
<link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.css" />
<link rel="stylesheet" href="~/css/site.css" />
</head>
<body>
<header>
<nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light bg-white border-bottom box-shadow mb-3">
<div class="container">
<a class="navbar-brand" asp-area="" asp-page="/Index">WebRP</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target=".navbar-collapse" aria-controls="navbarSupportedContent"
aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="navbar-collapse collapse d-sm-inline-flex flex-sm-row-reverse">
<partial name="_LoginPartial" />
<ul class="navbar-nav flex-grow-1">
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-page="/Index">Home</a>
</li>
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-page="/Privacy">Privacy</a>
</li>
</ul>
</div>
</div>
</nav>
</header>
<div class="container">
<main role="main" class="pb-3">
@RenderBody()
</main>
</div>
<footer class="border-top footer text-muted">
<div class="container">
© 2019 - WebRP - <a asp-area="" asp-page="/Privacy">Privacy</a>
</div>
</footer>
<script src="~/lib/jquery/dist/jquery.js"></script>
<script src="~/lib/bootstrap/dist/js/bootstrap.bundle.js"></script>
<script src="~/js/site.js" asp-append-version="true"></script>
@RenderSection("Scripts", required: false)
</body>
</html>
Move the Pages/Shared/_LoginPartial.cshtml
file to Views/Shared/_LoginPartial.cshtml
.
Identity is configured in Areas/Identity/IdentityHostingStartup.cs
. For more information, see IHostingStartup
.
The generated Identity database code requires Entity Framework (EF) Core Migrations. If a migration to generate the Identity schema hasn't been created and applied to the database, create a migration and update the database.
Visual Studio Connected Services are used to add an EF Core migration and update the database.
In Solution Explorer, double-click Connected Services. In the SQL Server Express LocalDB area of Service Dependencies, select the ellipsis (...
) followed by Add migration.
Give the migration a Migration name, such as CreateIdentitySchema
, which is a name that describes the migration. Wait for the database context to load in the DbContext class names field, which may take a few seconds. Select Finish to create the migration.
Select the Close button after the operation finishes.
Select the ellipsis (...
) again followed by the Update database command.
The Update database with the latest migration dialog opens. Wait for the DbContext class names field to update and for prior migrations to load, which may take a few seconds. Select the Finish button.
Select the Close button after the operation finishes.
The update database command executes the Up
method migrations that haven't been applied in a migration code file created by the scaffolder. In this case, the command executes the Up
method in the Migrations/{TIME STAMP}_{MIGRATION NAME}.cs
file, which creates the Identity tables, constraints, and indexes. The {TIME STAMP}
placeholder is a time stamp, and the {MIGRATION NAME}
placeholder is the migration name.
If the Identity schema has already been created but not applied to the database, only the command to update the database must be executed:
In Solution Explorer, double-click Connected Services. In the SQL Server Express LocalDB area of Service Dependencies, select the ellipsis (...
) followed by the Update database command.
The Update database with the latest migration dialog opens. Wait for the DbContext class names field to update and for prior migrations to load, which may take a few seconds. Select the Finish button.
Select the Close button after the operation finishes.
You can confirm the application of an Identity schema with the following command. The output of the command includes an "applied
" column to show which migrations are applied to the database.
In the Visual Studio Package Manager Console, execute Get-Migration
:
Get-Migration
If more than one database context exists, specify the context with the -Context
parameter.
Update the Startup
class with code similar to the following:
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews();
services.AddRazorPages();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseDatabaseErrorPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
endpoints.MapRazorPages();
});
}
}
UseHsts
is recommended but not required. For more information, see HTTP Strict Transport Security Protocol.
Run the Identity scaffolder:
_Layout.cshtml
), select your existing layout page to avoid overwriting your layout with incorrect markup by the scaffolder. For example, select either:
Pages/Shared/_Layout.cshtml
for Razor Pages or Blazor Server projects with existing Razor Pages infrastructure.Views/Shared/_Layout.cshtml
for MVC projects or Blazor Server projects with existing MVC infrastructure.Contoso.Data.ApplicationDbContext
for a company named "Contoso"). To create a new user class, select the + button for User class and specify the class (for example, ContosoUser
for a company named "Contoso").Run the Identity scaffolder:
_Layout.cshtml
), select your existing layout page to avoid overwriting your layout with incorrect markup by the scaffolder. For example, select either:
Pages/Shared/_Layout.cshtml
for Razor Pages or Blazor Server projects with existing Razor Pages infrastructure.Views/Shared/_Layout.cshtml
for MVC projects or Blazor Server projects with existing MVC infrastructure.Contoso.Data.ApplicationDbContext
for a company named "Contoso"). To create a new user class, select the + button for User class and specify the class (for example, ContosoUser
for a company named "Contoso").Identity is configured in Areas/Identity/IdentityHostingStartup.cs
. For more information, see IHostingStartup
.
The generated Identity database code requires Entity Framework (EF) Core Migrations. If a migration to generate the Identity schema hasn't been created and applied to the database, create a migration and update the database.
Visual Studio Connected Services are used to add an EF Core migration and update the database.
In Solution Explorer, double-click Connected Services. In the SQL Server Express LocalDB area of Service Dependencies, select the ellipsis (...
) followed by Add migration.
Give the migration a Migration name, such as CreateIdentitySchema
, which is a name that describes the migration. Wait for the database context to load in the DbContext class names field, which may take a few seconds. Select Finish to create the migration.
Select the Close button after the operation finishes.
Select the ellipsis (...
) again followed by the Update database command.
The Update database with the latest migration dialog opens. Wait for the DbContext class names field to update and for prior migrations to load, which may take a few seconds. Select the Finish button.
Select the Close button after the operation finishes.
The update database command executes the Up
method migrations that haven't been applied in a migration code file created by the scaffolder. In this case, the command executes the Up
method in the Migrations/{TIME STAMP}_{MIGRATION NAME}.cs
file, which creates the Identity tables, constraints, and indexes. The {TIME STAMP}
placeholder is a time stamp, and the {MIGRATION NAME}
placeholder is the migration name.
If the Identity schema has already been created but not applied to the database, only the command to update the database must be executed:
In Solution Explorer, double-click Connected Services. In the SQL Server Express LocalDB area of Service Dependencies, select the ellipsis (...
) followed by the Update database command.
The Update database with the latest migration dialog opens. Wait for the DbContext class names field to update and for prior migrations to load, which may take a few seconds. Select the Finish button.
Select the Close button after the operation finishes.
You can confirm the application of an Identity schema with the following command. The output of the command includes an "applied
" column to show which migrations are applied to the database.
In the Visual Studio Package Manager Console, execute Get-Migration
:
Get-Migration
If more than one database context exists, specify the context with the -Context
parameter.
Because server-side Blazor apps use Razor Pages Identity pages, the styling of the UI changes when a visitor navigates between Identity pages and components. You have two options to address the incongruous styles:
An approach to using components for Identity instead of pages is to build Identity components. Because SignInManager
and UserManager
aren't supported in Razor components, use web API endpoints in the Blazor app to process user account actions.
The Identity pages layout and styles can be modified to produce pages that use styles similar to the default Blazor theme. This approach isn't covered by the documentation.
Run the Identity scaffolder:
_Layout.cshtml
), select your existing layout page to avoid overwriting your layout with incorrect markup by the scaffolder. For example, select either:
Pages/Shared/_Layout.cshtml
for Razor Pages or Blazor Server projects with existing Razor Pages infrastructure.Views/Shared/_Layout.cshtml
for MVC projects or Blazor Server projects with existing MVC infrastructure.Contoso.Data.ApplicationDbContext
for a company named "Contoso"). To create a new user class, select the + button for User class and specify the class (for example, ContosoUser
for a company named "Contoso").Some Identity options are configured in Areas/Identity/IdentityHostingStartup.cs
. For more information, see IHostingStartup
.
Client-side Blazor apps use their own Identity UI approaches and can't use ASP.NET Core Identity scaffolding. Server-side ASP.NET Core apps of hosted Blazor solutions can follow the Razor Pages/MVC guidance in this article and are configured just like any other type of ASP.NET Core app that supports Identity.
The Blazor framework doesn't include Razor component versions of Identity UI pages. Identity UI Razor components can be custom built or obtained from unsupported third-party sources.
For more information, see the Blazor Security and Identity articles.
To maintain full control of the Identity UI, run the Identity scaffolder and select Override all files.
The following highlighted code shows the changes to replace the default Identity UI with Identity in an ASP.NET Core 2.1 web app. You might want to do this to have full control of the Identity UI.
public void ConfigureServices(IServiceCollection services)
{
services.Configure<CookiePolicyOptions>(options =>
{
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.None;
});
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(
Configuration.GetConnectionString("DefaultConnection")));
services.AddIdentity<IdentityUser, IdentityRole>()
// services.AddDefaultIdentity<IdentityUser>()
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();
services.AddMvc()
.AddRazorPagesOptions(options =>
{
options.Conventions.AuthorizeAreaFolder("Identity", "/Account/Manage");
options.Conventions.AuthorizeAreaPage("Identity", "/Account/Logout");
});
services.ConfigureApplicationCookie(options =>
{
options.LoginPath = $"/Identity/Account/Login";
options.LogoutPath = $"/Identity/Account/Logout";
options.AccessDeniedPath = $"/Identity/Account/AccessDenied";
});
// using Microsoft.AspNetCore.Identity.UI.Services;
services.AddSingleton<IEmailSender, EmailSender>();
}
The default Identity is replaced in the following code:
services.AddIdentity<IdentityUser, IdentityRole>()
// services.AddDefaultIdentity<IdentityUser>()
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();
The following code sets the LoginPath, LogoutPath, and AccessDeniedPath):
services.ConfigureApplicationCookie(options =>
{
options.LoginPath = $"/Identity/Account/Login";
options.LogoutPath = $"/Identity/Account/Logout";
options.AccessDeniedPath = $"/Identity/Account/AccessDenied";
});
Register an IEmailSender
implementation, for example:
// using Microsoft.AspNetCore.Identity.UI.Services;
services.AddSingleton<IEmailSender, EmailSender>();
public class EmailSender : IEmailSender
{
public Task SendEmailAsync(string email, string subject, string message)
{
return Task.CompletedTask;
}
}
If PasswordOptions are configured in Startup.ConfigureServices
, [StringLength]
attribute configuration might be required for the Password
property in scaffolded Identity pages. InputModel
Password
properties are found in the following files:
Areas/Identity/Pages/Account/Register.cshtml.cs
Areas/Identity/Pages/Account/ResetPassword.cshtml.cs
This section shows how to disable the register page but the approach can be used to disable any page.
To disable user registration:
Scaffold Identity. Include Account.Register, Account.Login, and Account.RegisterConfirmation. For example:
dotnet aspnet-codegenerator identity -dc RPauth.Data.ApplicationDbContext --files "Account.Register;Account.Login;Account.RegisterConfirmation"
Update Areas/Identity/Pages/Account/Register.cshtml.cs
so users can't register from this endpoint:
public class RegisterModel : PageModel
{
public IActionResult OnGet()
{
return RedirectToPage("Login");
}
public IActionResult OnPost()
{
return RedirectToPage("Login");
}
}
Update Areas/Identity/Pages/Account/Register.cshtml
to be consistent with the preceding changes:
@page
@model RegisterModel
@{
ViewData["Title"] = "Go to Login";
}
<h1>@ViewData["Title"]</h1>
<li class="nav-item">
<a class="nav-link text-dark" asp-area="Identity" asp-page="/Account/Login">Login</a>
</li>
Comment out or remove the registration link from Areas/Identity/Pages/Account/Login.cshtml
@*
<p>
<a asp-page="./Register" asp-route-returnUrl="@Model.ReturnUrl">Register as a new user</a>
</p>
*@
Update the Areas/Identity/Pages/Account/RegisterConfirmation
page.
PageModel
:[AllowAnonymous]
public class RegisterConfirmationModel : PageModel
{
public IActionResult OnGet()
{
return Page();
}
}
Provide a mechanism to add users outside the web app. Options to add users include:
The following code outlines one approach to adding users:
public class Program
{
public static void Main(string[] args)
{
var host = CreateHostBuilder(args).Build();
using (var scope = host.Services.CreateScope())
{
var services = scope.ServiceProvider;
try
{
var context = services.GetRequiredService<AppDbCntx>();
context.Database.Migrate();
var config = host.Services.GetRequiredService<IConfiguration>();
var userList = config.GetSection("userList").Get<List<string>>();
SeedData.Initialize(services, userList).Wait();
}
catch (Exception ex)
{
var logger = services.GetRequiredService<ILogger<Program>>();
logger.LogError(ex, "An error occurred adding users.");
}
}
host.Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
The following code outlines adding a user:
public static async Task Initialize(IServiceProvider serviceProvider,
List<string> userList)
{
var userManager = serviceProvider.GetService<UserManager<IdentityUser>>();
foreach (var userName in userList)
{
var userPassword = GenerateSecurePassword();
var userId = await EnsureUser(userManager, userName, userPassword);
NotifyUser(userName, userPassword);
}
}
private static async Task<string> EnsureUser(UserManager<IdentityUser> userManager,
string userName, string userPassword)
{
var user = await userManager.FindByNameAsync(userName);
if (user == null)
{
user = new IdentityUser(userName)
{
EmailConfirmed = true
};
await userManager.CreateAsync(user, userPassword);
}
return user.Id;
}
A similar approach can be followed for production scenarios.
To prevent publishing static Identity assets to the web root, see Introduction to Identity on ASP.NET Core.
Changes to authentication code to ASP.NET Core 2.1 and later
ASP.NET Core feedback
ASP.NET Core is an open source project. Select a link to provide feedback:
Events
Power BI DataViz World Championships
Feb 14, 4 PM - Mar 31, 4 PM
With 4 chances to enter, you could win a conference package and make it to the LIVE Grand Finale in Las Vegas
Learn moreTraining
Module
Secure a .NET web app with the ASP.NET Core Identity framework - Training
Learn how to add authentication and authorization to a .NET web app using the ASP.NET Core Identity framework.
Certification
Microsoft Certified: Identity and Access Administrator Associate - Certifications
Demonstrate the features of Microsoft Entra ID to modernize identity solutions, implement hybrid solutions, and implement identity governance.