Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions aspnetcore/blazor/security/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,14 @@ For a client-side app, authorization is *only* used to determine which UI option

:::moniker-end

:::moniker range="< aspnetcore-8.0"

ASP.NET Core Identity is designed to work in the context of HTTP request and response communication, which generally isn't the Blazor app client-server communication model. 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. Building Razor components that directly handle Identity tasks is possible for several scenarios but isn't recommended or supported by Microsoft.

ASP.NET Core abstractions, such as <xref:Microsoft.AspNetCore.Identity.SignInManager%601> and <xref:Microsoft.AspNetCore.Identity.UserManager%601>, aren't supported in Razor components. For more information on using ASP.NET Core Identity with Blazor, see [Scaffold ASP.NET Core Identity into a server-side Blazor app](xref:security/authentication/scaffold-identity#scaffold-identity-into-a-server-side-blazor-app).

:::moniker-end

> [!NOTE]
> The code examples in this article adopt [nullable reference types (NRTs) and .NET compiler null-state static analysis](xref:migration/50-to-60#nullable-reference-types-nrts-and-net-compiler-null-state-static-analysis), which are supported in ASP.NET Core 6.0 or later. When targeting ASP.NET Core 5.0 or earlier, remove the null type designation (`?`) from examples in this article.

Expand Down
68 changes: 60 additions & 8 deletions aspnetcore/blazor/security/server/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,22 @@ Create a new server-side Blazor app by following the guidance in <xref:blazor/to

After choosing the server-side app template and configuring the project, select the app's authentication under **Authentication type**:

<!-- UPDATE 8.0 Check this at RC2 -->
:::moniker range=">= aspnetcore-8.0"

* **None** (default): No authentication.
* **Individual Accounts**: User accounts are stored within the app using ASP.NET Core [Identity](xref:security/authentication/identity).

:::moniker-end

:::moniker range="< aspnetcore-8.0"

* **None** (default): No authentication.
* **Individual Accounts**: User accounts are stored within the app using ASP.NET Core [Identity](xref:security/authentication/identity).
* **Microsoft identity platform**: For more information, see <xref:blazor/security/index#additional-resources>.
* **Windows**: Use Windows Authentication.

:::moniker-end

# [Visual Studio Code](#tab/visual-studio-code)

When issuing the .NET CLI command to create and configure the server-side Blazor app, indicate the authentication mechanism with the `-au|--auth` option:
Expand All @@ -57,6 +67,17 @@ When issuing the .NET CLI command to create and configure the server-side Blazor

Permissible authentication values for the `{AUTHENTICATION}` placeholder are shown in the following table.

:::moniker range=">= aspnetcore-8.0"

| Authentication mechanism | Description |
| ------------------------ | ----------- |
| `None` (default) | No authentication |
| `Individual` | Users stored in the app with ASP.NET Core Identity |

:::moniker-end

:::moniker range="< aspnetcore-8.0"

| Authentication mechanism | Description |
| ------------------------ | ----------- |
| `None` (default) | No authentication |
Expand All @@ -66,6 +87,8 @@ Permissible authentication values for the `{AUTHENTICATION}` placeholder are sho
| `MultiOrg` | Organizational authentication for multiple tenants |
| `Windows` | Windows Authentication |

:::moniker-end

For more information, see the [`dotnet new`](/dotnet/core/tools/dotnet-new) command in the .NET Core Guide.

# [.NET Core CLI](#tab/netcore-cli/)
Expand All @@ -81,6 +104,17 @@ When issuing the .NET CLI command to create and configure the server-side Blazor

Permissible authentication values for the `{AUTHENTICATION}` placeholder are shown in the following table.

:::moniker range=">= aspnetcore-8.0"

| Authentication mechanism | Description |
| ------------------------ | ----------- |
| `None` (default) | No authentication |
| `Individual` | Users stored in the app with ASP.NET Core Identity |

:::moniker-end

:::moniker range="< aspnetcore-8.0"

| Authentication mechanism | Description |
| ------------------------ | ----------- |
| `None` (default) | No authentication |
Expand All @@ -90,6 +124,8 @@ Permissible authentication values for the `{AUTHENTICATION}` placeholder are sho
| `MultiOrg` | Organizational authentication for multiple tenants |
| `Windows` | Windows Authentication |

:::moniker-end

For more information:

* See the [`dotnet new`](/dotnet/core/tools/dotnet-new) command in the .NET Core Guide.
Expand All @@ -109,25 +145,41 @@ For more information:

Blazor supports generating a full Blazor-based Identity UI when you choose the authentication option for *Individual Accounts*.

In Visual Studio, the Blazor Web App template scaffolds Identity code for a SQL Server database. The command line version uses SQLite by default and includes a SQLite database for Identity.
The Blazor Web App template scaffolds Identity code for a SQL Server database. The command line version uses SQLite by default and includes a SQLite database for Identity.

The template handles the following:

* Adds Identity Razor components and related logic for routine authentication tasks, such as signing users in and out.
* The Identity components also support advanced Identity features, such as [account confirmation and password recovery](xref:security/authentication/accconfirm) and [multifactor authentication](xref:security/authentication/mfa) using a third-party app.
* Interactive server and interactive client rendering scenarios are supported.
* Adds the Identity-related packages and dependencies.
* References the Identity packages in `_Imports.razor`.
* Creates a custom Identity class called `ApplicationUser'.
* Creates and registers an EFCore DbContext.
* Adds and routes the built-in Identity endpoints.
* Adds all Identity UI components and related logic.
* Creates a custom user Identity class (`ApplicationUser`).
* Creates and registers an EF Core database context (`ApplicationDbContext`).
* Configures routing for the built-in Identity endpoints.
* Includes Identity validation and business logic.

The UI components also support advanced Identity concepts, such as multifactor authentication using a third-party app and email confirmations.
<!-- UPDATE 8.0 Cross-link API -->

When you choose the WebAssembly or Auto interactivity types, the server handles all authentication and authorization requests, and the Identity components remain on the server in the Blazor Web App's main project. The project template includes a `PersistentAuthenticationStateProvider` class in the `.Client` project to synchronize the user's authentication state between the server and the browser. The class is a custom implementation of <xref:Microsoft.AspNetCore.Components.Authorization.AuthenticationStateProvider>. The provider uses the <xref:Microsoft.AspNetCore.Components.PersistentComponentState> class to prerender the authentication state and persist it to the page.

In the main project of a Blazor Web App, the authentication state provider is named either `IdentityRevalidatingAuthenticationStateProvider` (Server interactivity solutions only) or `PersistingRevalidatingAuthenticationStateProvider` (WebAssembly or Auto interactivity solutions).

For more information on persisting prerendered state, see <xref:blazor/components/prerender#persist-prerendered-state>.

<!-- UPDATE 9.0 Remove blog post cross-link -->

For more information on the Blazor Identity UI and guidance on integrating external logins through social websites, see [What's new with identity in .NET 8](https://devblogs.microsoft.com/dotnet/whats-new-with-identity-in-dotnet-8/#the-blazor-identity-ui).

:::moniker-end

:::moniker range="< aspnetcore-8.0"

## Scaffold Identity

:::moniker range=">= aspnetcore-6.0"
:::moniker-end

:::moniker range=">= aspnetcore-6.0 < aspnetcore-8.0"

For more information on scaffolding Identity into a server-side Blazor app, see <xref:security/authentication/scaffold-identity#scaffold-identity-into-a-server-side-blazor-app>.

Expand Down
237 changes: 236 additions & 1 deletion aspnetcore/security/authentication/scaffold-identity.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,242 @@ By [Rick Anderson](https://twitter.com/RickAndMSFT)

<!-- VS add Microsoft.EntityFrameworkCore.Design -->

:::moniker range=">= aspnetcore-6.0"
:::moniker range=">= aspnetcore-8.0"

ASP.NET Core provides [ASP.NET Core Identity](xref:security/authentication/identity) as a [Razor Class Library](xref:razor-pages/ui-class). Applications that include Identity can apply the scaffolder to selectively add the source code contained in the Identity Razor Class Library (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](#full).

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](xref:security/authentication/identity-enable-qrcodes), [Account confirmation and password recovery](xref:security/authentication/accconfirm), 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](xref:security/authentication/accconfirm#require-email-confirmation).

Typically, apps that were created with individual accounts should ***not*** create a new data context.

<a name="RPNA"></a>

## Scaffold Identity into a Razor project without existing authorization

<!-- Updated for 3.0
set projNam=RPnoAuth
set projType=webapp

dotnet new %projType% -o %projNam%
cd %projNam%
dotnet add package Microsoft.VisualStudio.Web.CodeGeneration.Design
dotnet add package Microsoft.EntityFrameworkCore.Design
dotnet add package Microsoft.AspNetCore.Identity.EntityFrameworkCore
dotnet add package Microsoft.AspNetCore.Identity.UI
dotnet add package Microsoft.EntityFrameworkCore.SqlServer
dotnet add package Microsoft.EntityFrameworkCore.Tools
dotnet aspnet-codegenerator identity --useDefaultUI
dotnet ef database drop
dotnet ef migrations add CreateIdentitySchema0
dotnet ef database update
-->

<!-- ERROR
There is already an object named 'AspNetRoles' in the database.

Fixed via dotnet ef database drop
before dotnet ef database update
-->

[!INCLUDE[](~/includes/scaffold-identity/install-pkg.md)]

[!INCLUDE[](~/includes/scaffold-identity/id-scaffold-dlg.md)]

<a name="efm"></a>

### Migrations, UseAuthentication, and layout

[!INCLUDE[](~/includes/scaffold-identity/migrations.md)]

<a name="useauthentication"></a>

<!--
### Enable authentication

Update the `Startup` class with code similar to the following:

[!code-csharp[](scaffold-identity/3.1sample/StartupRP.cs?name=snippet)]

[!INCLUDE[](~/includes/scaffold-identity/hsts.md)] -->

### Layout changes

Optional: Add the login partial (`_LoginPartial`) to the layout file:

[!code-cshtml[](scaffold-identity/6.0sample/_Layout.cshtml?highlight=29)]

## Scaffold Identity into a Razor project with authorization

[!INCLUDE[](~/includes/scaffold-identity/install-pkg.md)]

<!--
Use >=2.1: dotnet new webapp -au Individual -o RPauth
Use = 2.0: dotnet new razor -au Individual -o RPauth
uld option: Use Local DB, not SQLite

dotnet new webapp -au Individual -uld -o RPauth
cd RPauth
dotnet add package Microsoft.VisualStudio.Web.CodeGeneration.Design
dotnet aspnet-codegenerator identity -dc RPauth.Data.ApplicationDbContext --files "Account.Register;Account.Register"
-->

[!INCLUDE[](~/includes/scaffold-identity/id-scaffold-dlg-auth.md)]

## Scaffold Identity into an MVC project without existing authorization

<!--
set projNam=MvcNoAuth
set projType=mvc
set version=2.1.0

dotnet new %projType% -o %projNam%
cd %projNam%
dotnet add package Microsoft.VisualStudio.Web.CodeGeneration.Design -v %version%
dotnet restore
dotnet aspnet-codegenerator identity --useDefaultUI
dotnet ef migrations add CreateIdentitySchema
dotnet ef database update
-->

[!INCLUDE[](~/includes/scaffold-identity/install-pkg.md)]

[!INCLUDE[](~/includes/scaffold-identity/id-scaffold-dlg.md)]

Optional: Add the login partial (`_LoginPartial`) to the `Views/Shared/_Layout.cshtml` file:

[!code-cshtml[](scaffold-identity/6.0sample/_Layout.cshtml?highlight=29)]

[!INCLUDE[](~/includes/scaffold-identity/migrations.md)]

Add `MapRazorPages` to `Program.cs` as shown in the following highlighted code:

[!code-cshtml[](scaffold-identity/6.0sample/ProgramMRP.cs?highlight=39)]

## Scaffold Identity into an MVC project with authorization

<!--
dotnet new mvc -au Individual -o MvcAuth
cd MvcAuth
dotnet add package Microsoft.VisualStudio.Web.CodeGeneration.Design
dotnet restore
dotnet aspnet-codegenerator identity -dc MvcAuth.Data.ApplicationDbContext --files "Account.Login;Account.Register"
-->

[!INCLUDE[](~/includes/scaffold-identity/install-pkg.md)]

[!INCLUDE[](~/includes/scaffold-identity/id-scaffold-dlg-auth.md)]

## Client-side Blazor apps

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](xref:blazor/security/index).

<a name="full"></a>

## Create full Identity UI source
<!-- remove AllowAreas #23280 -->
To maintain full control of the Identity UI, run the Identity scaffolder and select **Override all files**.

<!--
uld option: Use Local DB, not SQLite

dotnet new webapp -au Individual -uld -o RPauth
cd RPauth
dotnet add package Microsoft.VisualStudio.Web.CodeGeneration.Design
dotnet aspnet-codegenerator identity -dc RPauth.Data.ApplicationDbContext --files "Account.Register;Account.Login;Account.RegisterConfirmation"
-->

## Password configuration

If <xref:Microsoft.AspNetCore.Identity.PasswordOptions> are configured in `Startup.ConfigureServices`, [`[StringLength]` attribute](xref:System.ComponentModel.DataAnnotations.StringLengthAttribute) 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`

## Disable a page

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:

```dotnetcli
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:

[!code-csharp[](scaffold-identity/sample/Register.cshtml.cs?name=snippet)]

* Update `Areas/Identity/Pages/Account/Register.cshtml` to be consistent with the preceding changes:

[!code-cshtml[](scaffold-identity/sample/Register.cshtml)]

* Comment out or remove the registration link from `Areas/Identity/Pages/Account/Login.cshtml`

```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.

* Remove the code and links from the cshtml file.
* Remove the confirmation code from the `PageModel`:

```csharp
[AllowAnonymous]
public class RegisterConfirmationModel : PageModel
{
public IActionResult OnGet()
{
return Page();
}
}
```

### Use another app to add users

Provide a mechanism to add users outside the web app. Options to add users include:

* A dedicated admin web app.
* A console app.

The following code outlines one approach to adding users:

* A list of users is read into memory.
* A strong unique password is generated for each user.
* The user is added to the Identity database.
* The user is notified and told to change the password.

[!code-csharp[](scaffold-identity/consoleAddUser/Program.cs?name=snippet)]

The following code outlines adding a user:

[!code-csharp[](scaffold-identity/consoleAddUser/Data/SeedData.cs?name=snippet)]

A similar approach can be followed for production scenarios.

## Prevent publish of static Identity assets

To prevent publishing static Identity assets to the web root, see <xref:security/authentication/identity#prevent-publish-of-static-identity-assets>.

:::moniker-end

:::moniker range=">= aspnetcore-6.0 < aspnetcore-8.0"

ASP.NET Core provides [ASP.NET Core Identity](xref:security/authentication/identity) as a [Razor Class Library](xref:razor-pages/ui-class). Applications that include Identity can apply the scaffolder to selectively add the source code contained in the Identity Razor Class Library (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](#full).

Expand Down