diff --git a/aspnetcore/blazor/blazor-ef-core.md b/aspnetcore/blazor/blazor-ef-core.md index 1e79be74bde2..59e5bd945677 100644 --- a/aspnetcore/blazor/blazor-ef-core.md +++ b/aspnetcore/blazor/blazor-ef-core.md @@ -150,6 +150,8 @@ The fastest way to create a new i * Using [`DbContextOptions`](/ef/core/miscellaneous/configuring-dbcontext#configuring-dbcontextoptions) to configure the context. * Using a connection string per , such as when you use [ASP.NET Core's Identity model](xref:security/authentication/customize_identity_model). For more information, see [Multi-tenancy (EF Core documentation)](/ef/core/miscellaneous/multitenancy). +[!INCLUDE[](~/blazor/security/includes/secure-authentication-flows.md)] + The recommended approach to create a new with dependencies is to use a factory. EF Core 5.0 or later provides a built-in factory for creating new contexts. :::moniker range="< aspnetcore-5.0" diff --git a/aspnetcore/blazor/components/data-binding.md b/aspnetcore/blazor/components/data-binding.md index 62f8fc73d9d4..6cf2a9a0cdcc 100644 --- a/aspnetcore/blazor/components/data-binding.md +++ b/aspnetcore/blazor/components/data-binding.md @@ -656,6 +656,8 @@ In a more sophisticated and real-world example, the following `PasswordEntry` co * Exposes changes of a `Password` property to a parent component with an [`EventCallback`](xref:blazor/components/event-handling#eventcallback) that passes in the current value of the child's `password` field as its argument. * Uses the `onclick` event to trigger the `ToggleShowPassword` method. For more information, see . +[!INCLUDE[](~/blazor/security/includes/secure-authentication-flows.md)] + `PasswordEntry.razor`: :::moniker range=">= aspnetcore-8.0" diff --git a/aspnetcore/blazor/security/blazor-web-app-with-oidc.md b/aspnetcore/blazor/security/blazor-web-app-with-oidc.md index 4d4b105d8089..77553c551848 100644 --- a/aspnetcore/blazor/security/blazor-web-app-with-oidc.md +++ b/aspnetcore/blazor/security/blazor-web-app-with-oidc.md @@ -111,31 +111,12 @@ The following : The OIDC client secret. - **The following example is only for testing and demonstration purposes. Don't store the client secret in the app's assembly or check the secret into source control.** Store the client secret in [User Secrets](xref:security/app-secrets), [Azure Key Vault](xref:security/key-vault-configuration), or an [environment variable](xref:fundamentals/configuration/index#non-prefixed-environment-variables). - - Authentication scheme configuration is automatically read from `builder.Configuration["Authentication:Schemes:{SCHEME NAME}:{PropertyName}"]`, where the `{SCHEME NAME}` placeholder is the scheme, which is `MicrosoftOidc`. Because configuration is preconfigured, a client secret can automatically be read via the `Authentication:Schemes:MicrosoftOidc:ClientSecret` configuration key. On the server using environment variables, name the environment variable `Authentication__Schemes__MicrosoftOidc__ClientSecret`: + Don't store the client secret in the app's assembly or check the secret into source control. For more information, see [Securely maintain sensitive data and credentials](xref:blazor/security/index#securely-maintain-sensitive-data-and-credentials). - ```dotnetcli - set Authentication__Schemes__MicrosoftOidc__ClientSecret={CLIENT SECRET} - ``` + **For local development and testing**, use one of the following approaches: - **For demonstration and testing only**, the can be set directly. Don't set the value directly for deployed production apps. For slightly improved security, [conditionally compile](/dotnet/csharp/language-reference/preprocessor-directives#conditional-compilation) the line with the `DEBUG` symbol: - - ```csharp - #if DEBUG - oidcOptions.ClientSecret = "{CLIENT SECRET}"; - #endif - ``` - - Example: - - Client secret (`{CLIENT SECRET}`): `463471c8c4...f90d674bc9` (shortened for display) - - ```csharp - #if DEBUG - oidcOptions.ClientSecret = "463471c8c4...137f90d674bc9"; - #endif - ``` + * Use the [Secret Manager tool](xref:security/app-secrets) to secure the secret locally. + * Authentication scheme configuration is automatically read from `builder.Configuration["Authentication:Schemes:{SCHEME NAME}:{PropertyName}"]`, where the `{SCHEME NAME}` placeholder is the scheme, which is `MicrosoftOidc`. The client secret can automatically be read during local development via the `Authentication:Schemes:MicrosoftOidc:ClientSecret` configuration key from an `appsettings.Development.json` file. * : Configures the OIDC handler to only perform authorization code flow. Implicit grants and hybrid flows are unnecessary in this mode. @@ -379,31 +360,12 @@ The following : The OIDC client secret. - **The following example is only for testing and demonstration purposes. Don't store the client secret in the app's assembly or check the secret into source control.** Store the client secret in [User Secrets](xref:security/app-secrets), [Azure Key Vault](xref:security/key-vault-configuration), or an [environment variable](xref:fundamentals/configuration/index#non-prefixed-environment-variables). - - Authentication scheme configuration is automatically read from `builder.Configuration["Authentication:Schemes:{SCHEME NAME}:{PropertyName}"]`, where the `{SCHEME NAME}` placeholder is the scheme, which is `MicrosoftOidc`. Because configuration is preconfigured, a client secret can automatically be read via the `Authentication:Schemes:MicrosoftOidc:ClientSecret` configuration key. On the server using environment variables, name the environment variable `Authentication__Schemes__MicrosoftOidc__ClientSecret`: + Don't store the client secret in the app's assembly or check the secret into source control. For more information, see [Securely maintain sensitive data and credentials](xref:blazor/security/index#securely-maintain-sensitive-data-and-credentials). - ```dotnetcli - set Authentication__Schemes__MicrosoftOidc__ClientSecret={CLIENT SECRET} - ``` + **For local development and testing**, use one of the following approaches: - **For demonstration and testing only**, the can be set directly. Don't set the value directly for deployed production apps. For slightly improved security, [conditionally compile](/dotnet/csharp/language-reference/preprocessor-directives#conditional-compilation) the line with the `DEBUG` symbol: - - ```csharp - #if DEBUG - oidcOptions.ClientSecret = "{CLIENT SECRET}"; - #endif - ``` - - Example: - - Client secret (`{CLIENT SECRET}`): `463471c8c4...f90d674bc9` (shortened for display) - - ```csharp - #if DEBUG - oidcOptions.ClientSecret = "463471c8c4...137f90d674bc9"; - #endif - ``` + * Use the [Secret Manager tool](xref:security/app-secrets) to secure the secret locally. + * Authentication scheme configuration is automatically read from `builder.Configuration["Authentication:Schemes:{SCHEME NAME}:{PropertyName}"]`, where the `{SCHEME NAME}` placeholder is the scheme, which is `MicrosoftOidc`. The client secret can automatically be read during local development via the `Authentication:Schemes:MicrosoftOidc:ClientSecret` configuration key from an `appsettings.Development.json` file. * : Configures the OIDC handler to only perform authorization code flow. Implicit grants and hybrid flows are unnecessary in this mode. diff --git a/aspnetcore/blazor/security/includes/secure-authentication-flows.md b/aspnetcore/blazor/security/includes/secure-authentication-flows.md new file mode 100644 index 000000000000..b3567bf4e229 --- /dev/null +++ b/aspnetcore/blazor/security/includes/secure-authentication-flows.md @@ -0,0 +1,2 @@ +> [!WARNING] +> Don't store app secrets, connection strings, credentials, passwords, personal identification numbers (PINs), private C#/.NET code, or private keys/tokens in client-side code, which is ***always insecure***. In test/staging and production environments, server-side Blazor code and web APIs should use secure authentication flows that avoid maintaining credentials within project code or configuration files. Outside of local development testing, we recommend avoiding the use of environment variables to store sensitive data, as environment variables aren't the most secure approach. For local development testing, the [Secret Manager tool](xref:security/app-secrets) is recommended for securing sensitive data. For more information, see [Securely maintain sensitive data and credentials](xref:blazor/security/index#securely-maintain-sensitive-data-and-credentials). diff --git a/aspnetcore/blazor/security/index.md b/aspnetcore/blazor/security/index.md index ad48066f3da9..c11fe65fd28d 100644 --- a/aspnetcore/blazor/security/index.md +++ b/aspnetcore/blazor/security/index.md @@ -43,6 +43,17 @@ ASP.NET Core abstractions, such as [!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 in .NET 6 or later. When targeting ASP.NET Core 5.0 or earlier, remove the null type designation (`?`) from examples in this article. +## Securely maintain sensitive data and credentials + +Don't store app secrets, connection strings, credentials, passwords, personal identification numbers (PINs), private .NET/C# code, or private keys/tokens in client-side code, which is ***always insecure***. Client-side Blazor code should access secure services and databases through a secure web API that you control. + +In test/staging and production environments, server-side Blazor code and web APIs should use secure authentication flows that avoid maintaining credentials within project code or configuration files. Outside of local development testing, we recommend avoiding the use of environment variables to store sensitive data, as environment variables aren't the most secure approach. For local development testing, the [Secret Manager tool](xref:security/app-secrets) is recommended for securing sensitive data. For more information, see the following resources: + +* [Secure authentication flows (ASP.NET Core documentation)](xref:security/index#secure-authentication-flows) +* [Managed identities for Microsoft Azure services (this article)](#managed-identities-for-microsoft-azure-services) + +For client-side and server-side local development and testing, use the [Secret Manager tool](xref:security/app-secrets) to secure sensitive credentials. + ## Managed identities for Microsoft Azure services For Microsoft Azure services, we recommend using *managed identities*. Managed identities securely authenticate to Azure services without storing credentials in app code. For more information, see the following resources: diff --git a/aspnetcore/blazor/security/server/account-confirmation-and-password-recovery.md b/aspnetcore/blazor/security/server/account-confirmation-and-password-recovery.md index 1398cf63424f..568b3d64e619 100644 --- a/aspnetcore/blazor/security/server/account-confirmation-and-password-recovery.md +++ b/aspnetcore/blazor/security/server/account-confirmation-and-password-recovery.md @@ -40,7 +40,7 @@ builder.Services.Configure(builder.Configuration); ## Configure a user secret for the provider's security key -Set the key with the [secret-manager tool](xref:security/app-secrets). In the following example, the key name is `EmailAuthKey` and the key is represented by the `{KEY}` placeholder. In a command shell, navigate to the app's root folder and execute the following command with the API key: +Set the key with the [Secret Manager tool](xref:security/app-secrets). In the following example, the key name is `EmailAuthKey`, and the key is represented by the `{KEY}` placeholder. In a command shell, navigate to the app's root folder and execute the following command with the API key: ```dotnetcli dotnet user-secrets set "EmailAuthKey" "{KEY}" @@ -48,6 +48,8 @@ dotnet user-secrets set "EmailAuthKey" "{KEY}" For more information, see . +[!INCLUDE[](~/blazor/security/includes/secure-authentication-flows.md)] + ## Implement `IEmailSender` Implement `IEmailSender` for the provider. The following example is based on Mailchimp's Transactional API using [Mandrill.net](https://www.nuget.org/packages/Mandrill.net). For a different provider, refer to their documentation on how to implement sending a message in the `Execute` method. diff --git a/aspnetcore/blazor/security/server/index.md b/aspnetcore/blazor/security/server/index.md index d8efba637c7b..2f7bde826708 100644 --- a/aspnetcore/blazor/security/server/index.md +++ b/aspnetcore/blazor/security/server/index.md @@ -28,6 +28,15 @@ Blazor differs from a traditional server-rendered web apps that make new HTTP re > [!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 in .NET 6 or later. When targeting ASP.NET Core 5.0 or earlier, remove the null type designation (`?`) from the examples in this article. +## Server-side security of sensitive data and credentials + +In test/staging and production environments, server-side Blazor code and web APIs should use secure authentication flows that avoid maintaining credentials within project code or configuration files. Outside of local development testing, we recommend avoiding the use of environment variables to store sensitive data, as environment variables aren't the most secure approach. For local development testing, the [Secret Manager tool](xref:security/app-secrets) is recommended for securing sensitive data. For more information, see the following resources: + +* [Secure authentication flows (ASP.NET Core documentation)](xref:security/index#secure-authentication-flows) +* [Managed identities for Microsoft Azure services (Blazor documentation)](xref:blazor/security/index#managed-identities-for-microsoft-azure-services) + +For client-side and server-side local development and testing, use the [Secret Manager tool](xref:security/app-secrets) to secure sensitive credentials. + ## Project template Create a new server-side Blazor app by following the guidance in . diff --git a/aspnetcore/blazor/security/webassembly/index.md b/aspnetcore/blazor/security/webassembly/index.md index a593f567cf88..8d855eb38f8f 100644 --- a/aspnetcore/blazor/security/webassembly/index.md +++ b/aspnetcore/blazor/security/webassembly/index.md @@ -16,12 +16,14 @@ Blazor WebAssembly apps are secured in the same manner as single-page applicatio The Blazor WebAssembly security documentation primarily focuses on how to accomplish user authentication and authorization tasks. For OAuth 2.0/OIDC general concept coverage, see the resources in the [main overview article's *Additional resources* section](xref:blazor/security/index#additional-resources). -## Client-side/SPA security +## Client-side/SPA security of sensitive data and credentials -A Blazor WebAssembly app's .NET/C# codebase is served to clients, and the app's code can't be protected from inspection and tampering by users. Never place anything of a secret nature into a Blazor WebAssembly app, such as private .NET/C# code, security keys, passwords, or any other type of sensitive information. +A Blazor WebAssembly app's .NET/C# codebase is served to clients, and the app's code can't be protected from inspection and tampering by users. Never place credentials or secrets into a Blazor WebAssembly app, such as app secrets, connection strings, passwords, private .NET/C# code, or other sensitive data. To protect .NET/C# code and use [ASP.NET Core Data Protection](xref:security/data-protection/introduction) features to secure data, use a server-side ASP.NET Core web API. Have the client-side Blazor WebAssembly app call the server-side web API for secure app features and data processing. For more information, see and the articles in this node. +For local development testing, the [Secret Manager tool](xref:security/app-secrets) is recommended for securing sensitive data. + ## Authentication library Blazor WebAssembly supports authenticating and authorizing apps using OIDC via the [`Microsoft.AspNetCore.Components.WebAssembly.Authentication`](https://www.nuget.org/packages/Microsoft.AspNetCore.Components.WebAssembly.Authentication) library using the [Microsoft identity platform](/entra/identity-platform/). The library provides a set of primitives for seamlessly authenticating against ASP.NET Core backends. The library can authenticate against any third-party Identity Provider (IP) that supports OIDC, which are called OpenID Providers (OP). diff --git a/aspnetcore/blazor/security/webassembly/standalone-with-identity.md b/aspnetcore/blazor/security/webassembly/standalone-with-identity.md index ce38bdab7b8d..84ae790caa97 100644 --- a/aspnetcore/blazor/security/webassembly/standalone-with-identity.md +++ b/aspnetcore/blazor/security/webassembly/standalone-with-identity.md @@ -94,6 +94,10 @@ For additional Identity scenarios provided by the API, see object. For local development, the connection string is read from the `appsettings.json` file. +[!INCLUDE[](~/blazor/security/includes/secure-authentication-flows.md)] + ## Test the app Run the app. diff --git a/aspnetcore/blazor/tutorials/movie-database-app/part-4.md b/aspnetcore/blazor/tutorials/movie-database-app/part-4.md index 937d263ab500..b44113a9a302 100644 --- a/aspnetcore/blazor/tutorials/movie-database-app/part-4.md +++ b/aspnetcore/blazor/tutorials/movie-database-app/part-4.md @@ -97,7 +97,9 @@ The following is an example connection string: > :::no-loc text="Server=(localdb)\\mssqllocaldb;Database=BlazorWebAppMoviesContext-c347f669-bddf-56a3-a32e-7fe010306593;Trusted_Connection=True;MultipleActiveResultSets=true"::: -When the app is deployed to a test/staging or production server, an environment variable can be used to set the connection string to a test/staging or production database server. +When the app is deployed to a test/staging or production server, securely store the connection string outside of the project's configuration files. + +[!INCLUDE[](~/blazor/security/includes/secure-authentication-flows.md)] ## Database technology