From 453ca93ab797dabf16937ef80bc704021609fd09 Mon Sep 17 00:00:00 2001 From: guardrex <1622880+guardrex@users.noreply.github.com> Date: Fri, 25 Oct 2024 12:06:50 -0400 Subject: [PATCH 01/12] Add Key Vault approach for client secret --- .../security/blazor-web-app-with-entra.md | 72 +++++++++++++++++++ 1 file changed, 72 insertions(+) diff --git a/aspnetcore/blazor/security/blazor-web-app-with-entra.md b/aspnetcore/blazor/security/blazor-web-app-with-entra.md index 0e7d9edd0b4a..b2ba3116e723 100644 --- a/aspnetcore/blazor/security/blazor-web-app-with-entra.md +++ b/aspnetcore/blazor/security/blazor-web-app-with-entra.md @@ -153,6 +153,78 @@ The important changes to the `LogInOrOut` component are demonstrated in the foll ``` +## Obtain the client secret from Azure Key Vault + +[Azure Key Vault](https://azure.microsoft.com/products/key-vault/) provides a safe approach for providing the app's client secret to the app when hosting in [Microsoft Azure](https://azure.microsoft.com/). + +To create a key vault and set a client secret, see [About Azure Key Vault secrets (Azure documentation)](/azure/key-vault/secrets/about-secrets), which cross-links resources to get started with Azure Key Vault. To implement the code in this section, record the key vault URI and the secret name from Azure when you create the key vault and secret. + +The following `GetSecretFromKeyVault` method retrieves a secret from a key vault using the Entra tenant ID. Add this method to the server project. Adjust the namespace (`BlazorSample.Helpers`) to match your project namespace scheme. + +`Helpers/AzureHelper`: + +```csharp +using Azure; +using Azure.Identity; +using Azure.Security.KeyVault.Secrets; + +namespace BlazorSample.Helpers; + +public static class AzureHelper +{ + public static string GetKeyVaultSecret(string tenantId, string vaultUri, string secretName) + { + DefaultAzureCredentialOptions options = new() + { + // Specify the tenant ID to use the dev credentials when running the app locally + VisualStudioTenantId = tenantId, + SharedTokenCacheTenantId = tenantId + }; + + var client = new SecretClient(new Uri(vaultUri), new DefaultAzureCredential(options)); + var secret = client.GetSecretAsync(secretName).Result; + + return secret.Value.Value; + } +} +``` + +In the server project's `Program` file after Microsoft identity platform services are added (`AddMicrosoftIdentityWebApp`), obtain and apply the client secret using the following code: + +```csharp +string tenantId = builder.Configuration.GetValue("AzureAd:TenantId")!; +string vaultUri = builder.Configuration.GetValue("AzureAd:VaultUri")!; +string secretName = builder.Configuration.GetValue("AzureAd:SecretName")!; + +builder.Services.Configure( + options => + { + options.ClientSecret = + AzureHelper.GetKeyVaultSecret(tenantId, vaultUri, secretName); + }); +``` + +Supply the vault URI and secret name from configuration. + +In the `AzureAd` section of `appsettings.json`, add configuration keys and values: + +* The `{VAULT URI}` placeholder is the key vault URI. Include the trailing slash on the URI. +* The `{SECRET NAME}` placeholder is the secret name. + +```json +"VaultUri": "{VAULT URI}", +"SecretName": "{SECRET NAME}" +``` + +Example: + +```json +"VaultUri": "https://contoso.vault.azure.net/", +"SecretName": "BlazorSample_Entra" +``` + +Configuration is used to facilitate supplying values based on the app's environmental configuration files. For example, `appsettings.Development.json` for Development, `appsettings.Staging.json` for Staging, and `appsettings.Production.json` for Production can use dedicated key vaults for each environment. + ## Troubleshoot [!INCLUDE[](~/blazor/security/includes/troubleshoot-server.md)] From 289896683b181d179b517acfe80de3903ad9e8a9 Mon Sep 17 00:00:00 2001 From: guardrex <1622880+guardrex@users.noreply.github.com> Date: Fri, 25 Oct 2024 12:12:24 -0400 Subject: [PATCH 02/12] Updates --- aspnetcore/blazor/security/blazor-web-app-with-entra.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/aspnetcore/blazor/security/blazor-web-app-with-entra.md b/aspnetcore/blazor/security/blazor-web-app-with-entra.md index b2ba3116e723..105137a03da6 100644 --- a/aspnetcore/blazor/security/blazor-web-app-with-entra.md +++ b/aspnetcore/blazor/security/blazor-web-app-with-entra.md @@ -159,7 +159,7 @@ The important changes to the `LogInOrOut` component are demonstrated in the foll To create a key vault and set a client secret, see [About Azure Key Vault secrets (Azure documentation)](/azure/key-vault/secrets/about-secrets), which cross-links resources to get started with Azure Key Vault. To implement the code in this section, record the key vault URI and the secret name from Azure when you create the key vault and secret. -The following `GetSecretFromKeyVault` method retrieves a secret from a key vault using the Entra tenant ID. Add this method to the server project. Adjust the namespace (`BlazorSample.Helpers`) to match your project namespace scheme. +The following `GetKeyVaultSecret` method retrieves a secret from a key vault. Add this method to the server project. Adjust the namespace (`BlazorSample.Helpers`) to match your project namespace scheme. `Helpers/AzureHelper`: @@ -223,7 +223,7 @@ Example: "SecretName": "BlazorSample_Entra" ``` -Configuration is used to facilitate supplying values based on the app's environmental configuration files. For example, `appsettings.Development.json` for Development, `appsettings.Staging.json` for Staging, and `appsettings.Production.json` for Production can use dedicated key vaults for each environment. +Configuration is used to facilitate supplying values based on the app's environmental configuration files. For example, `appsettings.Development.json` for Development, `appsettings.Staging.json` for Staging, and `appsettings.Production.json` for Production can use dedicated key vaults and secret names for each environment. ## Troubleshoot From ff25b93535de2fdc0ae907f16418ff12f93d2f8e Mon Sep 17 00:00:00 2001 From: guardrex <1622880+guardrex@users.noreply.github.com> Date: Mon, 28 Oct 2024 10:14:53 -0400 Subject: [PATCH 03/12] Updates --- .../security/blazor-web-app-with-entra.md | 139 ++++++++++-------- 1 file changed, 76 insertions(+), 63 deletions(-) diff --git a/aspnetcore/blazor/security/blazor-web-app-with-entra.md b/aspnetcore/blazor/security/blazor-web-app-with-entra.md index 105137a03da6..3b7cd51ae015 100644 --- a/aspnetcore/blazor/security/blazor-web-app-with-entra.md +++ b/aspnetcore/blazor/security/blazor-web-app-with-entra.md @@ -59,20 +59,6 @@ This section explains how to configure the sample app. In the app's registration in the Entra or Azure portal, use a **Web** platform configuration with a **Redirect URI** of `https://localhost/signin-oidc` (a port isn't required). Confirm that **ID tokens** and access tokens under **Implicit grant and hybrid flows** are **not** selected. The OpenID Connect handler automatically requests the appropriate tokens using the code returned from the authorization endpoint. -### Establish the client secret - -Use the [Secret Manager tool](xref:security/app-secrets) to store the server app's client secret under the configuration key `AzureAd:ClientSecret`. - -Create a client secret in the app's Entra ID registration in the Entra or Azure portal (**Manage** > **Certificates & secrets** > **New client secret**). Use the **Value** of the new secret in the following guidance. - -Execute the following command in a command shell from the server project's directory, such as the Developer PowerShell command shell in Visual Studio. The `{SECRET}` placeholder is the client secret obtained from the app's registration: - -```dotnetcli -dotnet user-secrets set "AzureAd:ClientSecret" "{SECRET}" -``` - -If using Visual Studio, you can confirm the secret is set by right-clicking the server project in **Solution Explorer** and selecting **Manage User Secrets**. - ### Configure the app In the server project's app settings file (`appsettings.json`), provide the app's `AzureAd` section configuration. Obtain the application (client) ID, tenant (publisher) domain, and directory (tenant) ID from the app's registration in the Entra or Azure portal: @@ -109,57 +95,41 @@ Example: The callback path (`CallbackPath`) must match the redirect URI (login callback path) configured when registering the application in the Entra or Azure portal. Paths are configured in the **Authentication** blade of the app's registration. The default value of `CallbackPath` is `/signin-oidc` for a registered redirect URI of `https://localhost/signin-oidc` (a port isn't required). - +### Establish the client secret -> [!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. +Create a client secret in the app's Entra ID registration in the Entra or Azure portal (**Manage** > **Certificates & secrets** > **New client secret**). Use the **Value** of the new secret in the following guidance. -## Redirect to the home page on sign out +Use one of the following approaches to supply the client secret to the app: -When a user navigates around the app, the `LogInOrOut` component (`Layout/LogInOrOut.razor`) sets a hidden field for the return URL (`ReturnUrl`) to the value of the current URL (`currentURL`). When the user signs out of the app, the identity provider returns them to the page from which they signed out. +* [Secret Manager tool](#secret-manager-tool) +* [Azure Key Vault](#azure-key-vault) -If the user signs out from a secure page, they're returned back to the same secure page after signing out only to be sent back through the authentication process. This behavior is fine when users need to switch accounts frequently. However, a alternative app specification may call for the user to be returned to the app's home page or some other page after signing out. The following example shows how to set the app's home page as the return URL for sign-out operations. +We strongly recommend that you avoid storing client secrets in project code or configuration files. Use secure authentication flows, such as either of the approaches in this section. -The important changes to the `LogInOrOut` component are demonstrated in the following example. There's no need to provide a hidden field for the `ReturnUrl` set to the home page at `/` because that's the default path. is no longer implemented. The is no longer injected. The entire `@code` block is removed. +### Secret Manager tool -`Layout/LogInOrOut.razor`: +The [Secret Manager tool](xref:security/app-secrets) can store the server app's client secret under the configuration key `AzureAd:ClientSecret`. -```razor -@using Microsoft.AspNetCore.Authorization +Execute the following command in a command shell from the server project's directory, such as the Developer PowerShell command shell in Visual Studio. The `{SECRET}` placeholder is the client secret obtained from the app's registration: - +```dotnetcli +dotnet user-secrets set "AzureAd:ClientSecret" "{SECRET}" ``` -## Obtain the client secret from Azure Key Vault +If using Visual Studio, you can confirm the secret is set by right-clicking the server project in **Solution Explorer** and selecting **Manage User Secrets**. + +### Azure Key Vault [Azure Key Vault](https://azure.microsoft.com/products/key-vault/) provides a safe approach for providing the app's client secret to the app when hosting in [Microsoft Azure](https://azure.microsoft.com/). -To create a key vault and set a client secret, see [About Azure Key Vault secrets (Azure documentation)](/azure/key-vault/secrets/about-secrets), which cross-links resources to get started with Azure Key Vault. To implement the code in this section, record the key vault URI and the secret name from Azure when you create the key vault and secret. +To create a key vault and set a client secret, see [About Azure Key Vault secrets (Azure documentation)](/azure/key-vault/secrets/about-secrets), which cross-links resources to get started with Azure Key Vault. To implement the code in this section, record the key vault URI and the secret name from Azure when you create the key vault and secret. When you set the access policy for the secret in the **Access policies** panel: + +* Only the **Get** secret permission is required. +* Select the application as the **Principal** for the secret. -The following `GetKeyVaultSecret` method retrieves a secret from a key vault. Add this method to the server project. Adjust the namespace (`BlazorSample.Helpers`) to match your project namespace scheme. +The following `GetKeyVaultSecret` method retrieves a secret from a key vault. Add this method to the server project. Adjust the namespace (`BlazorSample.Helpers`) to match your project namespace scheme. If you aren't using Visual Studio, you can use the [Secret Manager tool](#secret-manager-tool) locally to store the secret and use the approach in this section in staging/production when the app is deployed. `Helpers/AzureHelper`: @@ -177,6 +147,7 @@ public static class AzureHelper DefaultAzureCredentialOptions options = new() { // Specify the tenant ID to use the dev credentials when running the app locally + // in Visual Studio. VisualStudioTenantId = tenantId, SharedTokenCacheTenantId = tenantId }; @@ -189,24 +160,32 @@ public static class AzureHelper } ``` -In the server project's `Program` file after Microsoft identity platform services are added (`AddMicrosoftIdentityWebApp`), obtain and apply the client secret using the following code: +In the server project's `Program` file where services are registered, obtain and apply the client secret using the following code: ```csharp -string tenantId = builder.Configuration.GetValue("AzureAd:TenantId")!; -string vaultUri = builder.Configuration.GetValue("AzureAd:VaultUri")!; -string secretName = builder.Configuration.GetValue("AzureAd:SecretName")!; +var tenantId = builder.Configuration.GetValue("AzureAd:TenantId")!; +var vaultUri = builder.Configuration.GetValue("AzureAd:VaultUri")!; +var secretName = builder.Configuration.GetValue("AzureAd:SecretName")!; builder.Services.Configure( - options => - { - options.ClientSecret = - AzureHelper.GetKeyVaultSecret(tenantId, vaultUri, secretName); - }); + OpenIdConnectDefaults.AuthenticationScheme, + options => + { + options.ClientSecret = + AzureHelper.GetKeyVaultSecret(tenantId, vaultUri, secretName); + }); ``` -Supply the vault URI and secret name from configuration. +If you wish to control the environment where the preceding code operates, for example to avoid running the code locally because you've opted to use the [Secret Manager tool](#secret-manager-tool) for local development, you can wrap the preceding code in a conditional statement that checks the environment: -In the `AzureAd` section of `appsettings.json`, add configuration keys and values: +```csharp +if (!context.HostingEnvironment.IsDevelopment()) +{ + ... +} +``` + +In the `AzureAd` section of `appsettings.json`, add the following configuration keys and values: * The `{VAULT URI}` placeholder is the key vault URI. Include the trailing slash on the URI. * The `{SECRET NAME}` placeholder is the secret name. @@ -220,10 +199,44 @@ Example: ```json "VaultUri": "https://contoso.vault.azure.net/", -"SecretName": "BlazorSample_Entra" +"SecretName": "BlazorWebAppEntra" ``` -Configuration is used to facilitate supplying values based on the app's environmental configuration files. For example, `appsettings.Development.json` for Development, `appsettings.Staging.json` for Staging, and `appsettings.Production.json` for Production can use dedicated key vaults and secret names for each environment. +Configuration is used to facilitate supplying dedicated key vaults and secret values based on the app's environmental configuration files. For example, you can supply different values for `appsettings.Development.json` in Development, `appsettings.Staging.json` when Staging, and `appsettings.Production.json` for the production deployment. For more information, see . + +## Redirect to the home page on sign out + +When a user navigates around the app, the `LogInOrOut` component (`Layout/LogInOrOut.razor`) sets a hidden field for the return URL (`ReturnUrl`) to the value of the current URL (`currentURL`). When the user signs out of the app, the identity provider returns them to the page from which they signed out. + +If the user signs out from a secure page, they're returned back to the same secure page after signing out only to be sent back through the authentication process. This behavior is fine when users need to switch accounts frequently. However, a alternative app specification may call for the user to be returned to the app's home page or some other page after signing out. The following example shows how to set the app's home page as the return URL for sign-out operations. + +The important changes to the `LogInOrOut` component are demonstrated in the following example. There's no need to provide a hidden field for the `ReturnUrl` set to the home page at `/` because that's the default path. is no longer implemented. The is no longer injected. The entire `@code` block is removed. + +`Layout/LogInOrOut.razor`: + +```razor +@using Microsoft.AspNetCore.Authorization + + +``` ## Troubleshoot From 7968e4abc8252ef547018f7518ca8ccc3f70e70d Mon Sep 17 00:00:00 2001 From: guardrex <1622880+guardrex@users.noreply.github.com> Date: Mon, 28 Oct 2024 10:19:34 -0400 Subject: [PATCH 04/12] Updates --- aspnetcore/blazor/security/blazor-web-app-with-entra.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/aspnetcore/blazor/security/blazor-web-app-with-entra.md b/aspnetcore/blazor/security/blazor-web-app-with-entra.md index 3b7cd51ae015..8d759fae82bd 100644 --- a/aspnetcore/blazor/security/blazor-web-app-with-entra.md +++ b/aspnetcore/blazor/security/blazor-web-app-with-entra.md @@ -112,6 +112,12 @@ We strongly recommend that you avoid storing client secrets in project code or c The [Secret Manager tool](xref:security/app-secrets) can store the server app's client secret under the configuration key `AzureAd:ClientSecret`. +The [sample app](#sample-app) has already been initialized for the Secret Manager tool, where a user secrets Id (``) is already present in the app's project file (`.csproj`). If you're working with an app that hasn't been initialized, use the following command from the server project's directory to establish a user secrets Id: + +```dotnetcli +dotnet user-secrets init +``` + Execute the following command in a command shell from the server project's directory, such as the Developer PowerShell command shell in Visual Studio. The `{SECRET}` placeholder is the client secret obtained from the app's registration: ```dotnetcli From d973b3cfc7e8e00b6617a38a357a53f60b4e92e2 Mon Sep 17 00:00:00 2001 From: guardrex <1622880+guardrex@users.noreply.github.com> Date: Mon, 28 Oct 2024 10:29:27 -0400 Subject: [PATCH 05/12] Updates --- aspnetcore/blazor/security/blazor-web-app-with-entra.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aspnetcore/blazor/security/blazor-web-app-with-entra.md b/aspnetcore/blazor/security/blazor-web-app-with-entra.md index 8d759fae82bd..8a7dff04a427 100644 --- a/aspnetcore/blazor/security/blazor-web-app-with-entra.md +++ b/aspnetcore/blazor/security/blazor-web-app-with-entra.md @@ -112,7 +112,7 @@ We strongly recommend that you avoid storing client secrets in project code or c The [Secret Manager tool](xref:security/app-secrets) can store the server app's client secret under the configuration key `AzureAd:ClientSecret`. -The [sample app](#sample-app) has already been initialized for the Secret Manager tool, where a user secrets Id (``) is already present in the app's project file (`.csproj`). If you're working with an app that hasn't been initialized, use the following command from the server project's directory to establish a user secrets Id: +The [sample app](#sample-app) hasn't been initialized for the Secret Manager tool. Use the following command from the server project's directory to establish a user secrets identifier (`` in the app's project file): ```dotnetcli dotnet user-secrets init From 42b7625334255088cf4f925e7f61904a0b95245e Mon Sep 17 00:00:00 2001 From: guardrex <1622880+guardrex@users.noreply.github.com> Date: Mon, 28 Oct 2024 10:37:08 -0400 Subject: [PATCH 06/12] Updates --- aspnetcore/blazor/security/blazor-web-app-with-entra.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/aspnetcore/blazor/security/blazor-web-app-with-entra.md b/aspnetcore/blazor/security/blazor-web-app-with-entra.md index 8a7dff04a427..0d302eba085a 100644 --- a/aspnetcore/blazor/security/blazor-web-app-with-entra.md +++ b/aspnetcore/blazor/security/blazor-web-app-with-entra.md @@ -101,10 +101,10 @@ The callback path (`CallbackPath`) must match the redirect URI (login callback p Create a client secret in the app's Entra ID registration in the Entra or Azure portal (**Manage** > **Certificates & secrets** > **New client secret**). Use the **Value** of the new secret in the following guidance. -Use one of the following approaches to supply the client secret to the app: +Use either or both of the following approaches to supply the client secret to the app: -* [Secret Manager tool](#secret-manager-tool) -* [Azure Key Vault](#azure-key-vault) +* [Secret Manager tool](#secret-manager-tool): The Secret Manager tool is only used during local development. +* [Azure Key Vault](#azure-key-vault): You can store the client secret in a key vault for use in any environment, including the Development environment locally. Some developers prefer to use key vaults for staging and production deployments and use the [Secret Manager tool](#secret-manager-tool) for local development, which this section explains how to set up. We strongly recommend that you avoid storing client secrets in project code or configuration files. Use secure authentication flows, such as either of the approaches in this section. From 09959fd82c3d680e01327c4e84793ae1b81894f8 Mon Sep 17 00:00:00 2001 From: guardrex <1622880+guardrex@users.noreply.github.com> Date: Mon, 28 Oct 2024 10:43:37 -0400 Subject: [PATCH 07/12] Updates --- .../blazor/security/blazor-web-app-with-entra.md | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/aspnetcore/blazor/security/blazor-web-app-with-entra.md b/aspnetcore/blazor/security/blazor-web-app-with-entra.md index 0d302eba085a..8e276def3714 100644 --- a/aspnetcore/blazor/security/blazor-web-app-with-entra.md +++ b/aspnetcore/blazor/security/blazor-web-app-with-entra.md @@ -124,11 +124,11 @@ Execute the following command in a command shell from the server project's direc dotnet user-secrets set "AzureAd:ClientSecret" "{SECRET}" ``` -If using Visual Studio, you can confirm the secret is set by right-clicking the server project in **Solution Explorer** and selecting **Manage User Secrets**. +If using Visual Studio, you can confirm that the secret is set by right-clicking the server project in **Solution Explorer** and selecting **Manage User Secrets**. ### Azure Key Vault -[Azure Key Vault](https://azure.microsoft.com/products/key-vault/) provides a safe approach for providing the app's client secret to the app when hosting in [Microsoft Azure](https://azure.microsoft.com/). +[Azure Key Vault](https://azure.microsoft.com/products/key-vault/) provides a safe approach for providing the app's client secret to the app. To create a key vault and set a client secret, see [About Azure Key Vault secrets (Azure documentation)](/azure/key-vault/secrets/about-secrets), which cross-links resources to get started with Azure Key Vault. To implement the code in this section, record the key vault URI and the secret name from Azure when you create the key vault and secret. When you set the access policy for the secret in the **Access policies** panel: @@ -137,7 +137,7 @@ To create a key vault and set a client secret, see [About Azure Key Vault secret The following `GetKeyVaultSecret` method retrieves a secret from a key vault. Add this method to the server project. Adjust the namespace (`BlazorSample.Helpers`) to match your project namespace scheme. If you aren't using Visual Studio, you can use the [Secret Manager tool](#secret-manager-tool) locally to store the secret and use the approach in this section in staging/production when the app is deployed. -`Helpers/AzureHelper`: +`Helpers/AzureHelper.cs`: ```csharp using Azure; @@ -191,16 +191,18 @@ if (!context.HostingEnvironment.IsDevelopment()) } ``` -In the `AzureAd` section of `appsettings.json`, add the following configuration keys and values: - -* The `{VAULT URI}` placeholder is the key vault URI. Include the trailing slash on the URI. -* The `{SECRET NAME}` placeholder is the secret name. +In the `AzureAd` section of `appsettings.json`, add the following `VaultUri` and `SecretName` configuration keys and values: ```json "VaultUri": "{VAULT URI}", "SecretName": "{SECRET NAME}" ``` +In the preceding example: + +* The `{VAULT URI}` placeholder is the key vault URI. Include the trailing slash on the URI. +* The `{SECRET NAME}` placeholder is the secret name. + Example: ```json From 381ddbc3ac533f319faa6f8c2bbc370cb11bd491 Mon Sep 17 00:00:00 2001 From: guardrex <1622880+guardrex@users.noreply.github.com> Date: Mon, 28 Oct 2024 10:54:16 -0400 Subject: [PATCH 08/12] Updates --- aspnetcore/blazor/security/blazor-web-app-with-entra.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/aspnetcore/blazor/security/blazor-web-app-with-entra.md b/aspnetcore/blazor/security/blazor-web-app-with-entra.md index 8e276def3714..b3c08d6d17c0 100644 --- a/aspnetcore/blazor/security/blazor-web-app-with-entra.md +++ b/aspnetcore/blazor/security/blazor-web-app-with-entra.md @@ -112,13 +112,13 @@ We strongly recommend that you avoid storing client secrets in project code or c The [Secret Manager tool](xref:security/app-secrets) can store the server app's client secret under the configuration key `AzureAd:ClientSecret`. -The [sample app](#sample-app) hasn't been initialized for the Secret Manager tool. Use the following command from the server project's directory to establish a user secrets identifier (`` in the app's project file): +The [sample app](#sample-app) hasn't been initialized for the Secret Manager tool. Execute the following command in a command shell from the server project's directory, such as the Developer PowerShell command shell in Visual Studio. The command establishes a user secrets identifier (`` in the app's project file): ```dotnetcli dotnet user-secrets init ``` -Execute the following command in a command shell from the server project's directory, such as the Developer PowerShell command shell in Visual Studio. The `{SECRET}` placeholder is the client secret obtained from the app's registration: +Execute the following command to set the client secret. The `{SECRET}` placeholder is the client secret obtained from the app's registration: ```dotnetcli dotnet user-secrets set "AzureAd:ClientSecret" "{SECRET}" From 0b8ccd5400e9eb8fb149eb04a1eccca688e13e6a Mon Sep 17 00:00:00 2001 From: guardrex <1622880+guardrex@users.noreply.github.com> Date: Mon, 28 Oct 2024 10:56:17 -0400 Subject: [PATCH 09/12] Updates --- aspnetcore/blazor/security/blazor-web-app-with-entra.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aspnetcore/blazor/security/blazor-web-app-with-entra.md b/aspnetcore/blazor/security/blazor-web-app-with-entra.md index b3c08d6d17c0..4574cba88e76 100644 --- a/aspnetcore/blazor/security/blazor-web-app-with-entra.md +++ b/aspnetcore/blazor/security/blazor-web-app-with-entra.md @@ -112,7 +112,7 @@ We strongly recommend that you avoid storing client secrets in project code or c The [Secret Manager tool](xref:security/app-secrets) can store the server app's client secret under the configuration key `AzureAd:ClientSecret`. -The [sample app](#sample-app) hasn't been initialized for the Secret Manager tool. Execute the following command in a command shell from the server project's directory, such as the Developer PowerShell command shell in Visual Studio. The command establishes a user secrets identifier (`` in the app's project file): +The [sample app](#sample-app) hasn't been initialized for the Secret Manager tool. Use a command shell, such as the Developer PowerShell command shell in Visual Studio, to execute the following command. Before executing the command, change the directory with the `cd` command to the server project's directory. The command establishes a user secrets identifier (`` in the server app's project file): ```dotnetcli dotnet user-secrets init From 10cec6d9d7b9ddfea785b5fcb3206d03e592f2f3 Mon Sep 17 00:00:00 2001 From: guardrex <1622880+guardrex@users.noreply.github.com> Date: Tue, 29 Oct 2024 05:59:51 -0400 Subject: [PATCH 10/12] Updates --- .../blazor/security/blazor-web-app-with-entra.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/aspnetcore/blazor/security/blazor-web-app-with-entra.md b/aspnetcore/blazor/security/blazor-web-app-with-entra.md index 4574cba88e76..ec7e5f84e660 100644 --- a/aspnetcore/blazor/security/blazor-web-app-with-entra.md +++ b/aspnetcore/blazor/security/blazor-web-app-with-entra.md @@ -103,22 +103,22 @@ Create a client secret in the app's Entra ID registration in the Entra or Azure Use either or both of the following approaches to supply the client secret to the app: -* [Secret Manager tool](#secret-manager-tool): The Secret Manager tool is only used during local development. -* [Azure Key Vault](#azure-key-vault): You can store the client secret in a key vault for use in any environment, including the Development environment locally. Some developers prefer to use key vaults for staging and production deployments and use the [Secret Manager tool](#secret-manager-tool) for local development, which this section explains how to set up. +* [Secret Manager tool](#secret-manager-tool): The Secret Manager tool stores private data on the local machine and is only used during local development. +* [Azure Key Vault](#azure-key-vault): You can store the client secret in a key vault for use in any environment, including for the Development environment when working locally. Some developers prefer to use key vaults for staging and production deployments and use the [Secret Manager tool](#secret-manager-tool) for local development. -We strongly recommend that you avoid storing client secrets in project code or configuration files. Use secure authentication flows, such as either of the approaches in this section. +We strongly recommend that you avoid storing client secrets in project code or configuration files. Use secure authentication flows, such as either or both of the approaches in this section. ### Secret Manager tool The [Secret Manager tool](xref:security/app-secrets) can store the server app's client secret under the configuration key `AzureAd:ClientSecret`. -The [sample app](#sample-app) hasn't been initialized for the Secret Manager tool. Use a command shell, such as the Developer PowerShell command shell in Visual Studio, to execute the following command. Before executing the command, change the directory with the `cd` command to the server project's directory. The command establishes a user secrets identifier (`` in the server app's project file): +The [sample app](#sample-app) hasn't been initialized for the Secret Manager tool. Use a command shell, such as the Developer PowerShell command shell in Visual Studio, to execute the following command. Before executing the command, change the directory with the `cd` command to the server project's directory. The command establishes a user secrets identifier (``) in the server app's project file, which is used internally by the tooling to track secrets for the app: ```dotnetcli dotnet user-secrets init ``` -Execute the following command to set the client secret. The `{SECRET}` placeholder is the client secret obtained from the app's registration: +Execute the following command to set the client secret. The `{SECRET}` placeholder is the client secret obtained from the app's Entra registration: ```dotnetcli dotnet user-secrets set "AzureAd:ClientSecret" "{SECRET}" @@ -135,7 +135,7 @@ To create a key vault and set a client secret, see [About Azure Key Vault secret * Only the **Get** secret permission is required. * Select the application as the **Principal** for the secret. -The following `GetKeyVaultSecret` method retrieves a secret from a key vault. Add this method to the server project. Adjust the namespace (`BlazorSample.Helpers`) to match your project namespace scheme. If you aren't using Visual Studio, you can use the [Secret Manager tool](#secret-manager-tool) locally to store the secret and use the approach in this section in staging/production when the app is deployed. +The following `GetKeyVaultSecret` method retrieves a secret from a key vault. Add this method to the server project. Adjust the namespace (`BlazorSample.Helpers`) to match your project namespace scheme. `Helpers/AzureHelper.cs`: @@ -166,7 +166,7 @@ public static class AzureHelper } ``` -In the server project's `Program` file where services are registered, obtain and apply the client secret using the following code: +Where services are registered in the server project's `Program` file, obtain and apply the client secret using the following code: ```csharp var tenantId = builder.Configuration.GetValue("AzureAd:TenantId")!; @@ -210,7 +210,7 @@ Example: "SecretName": "BlazorWebAppEntra" ``` -Configuration is used to facilitate supplying dedicated key vaults and secret values based on the app's environmental configuration files. For example, you can supply different values for `appsettings.Development.json` in Development, `appsettings.Staging.json` when Staging, and `appsettings.Production.json` for the production deployment. For more information, see . +Configuration is used to facilitate supplying dedicated key vaults and secret names based on the app's environmental configuration files. For example, you can supply different configuration values for `appsettings.Development.json` in development, `appsettings.Staging.json` when staging, and `appsettings.Production.json` for the production deployment. For more information, see . ## Redirect to the home page on sign out From 155183a1ad712609697a121b14ed4a4971cf17f7 Mon Sep 17 00:00:00 2001 From: guardrex <1622880+guardrex@users.noreply.github.com> Date: Tue, 19 Nov 2024 08:19:37 -0500 Subject: [PATCH 11/12] Updates --- aspnetcore/grpc/why-migrate-wcf-to-dotnet-grpc.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aspnetcore/grpc/why-migrate-wcf-to-dotnet-grpc.md b/aspnetcore/grpc/why-migrate-wcf-to-dotnet-grpc.md index a444e6fa2d2c..0e1002e9d0bf 100644 --- a/aspnetcore/grpc/why-migrate-wcf-to-dotnet-grpc.md +++ b/aspnetcore/grpc/why-migrate-wcf-to-dotnet-grpc.md @@ -1,6 +1,6 @@ --- title: Why migrate WCF to ASP.NET Core gRPC -author: markrendle +author: jamesnk description: This article provides a summary of why ASP.NET Core gRPC is a good fit for Windows Communication Foundation (WCF) developers who want to migrate to modern architectures and platforms. monikerRange: '>= aspnetcore-3.0' ms.author: wpickett From 8d2b7426914effb34e9fafbcb3545756b7dac23d Mon Sep 17 00:00:00 2001 From: guardrex <1622880+guardrex@users.noreply.github.com> Date: Tue, 19 Nov 2024 08:33:07 -0500 Subject: [PATCH 12/12] Updates --- aspnetcore/blazor/security/blazor-web-app-with-entra.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/aspnetcore/blazor/security/blazor-web-app-with-entra.md b/aspnetcore/blazor/security/blazor-web-app-with-entra.md index 6d2b2e6035cf..cbd0ed7624f2 100644 --- a/aspnetcore/blazor/security/blazor-web-app-with-entra.md +++ b/aspnetcore/blazor/security/blazor-web-app-with-entra.md @@ -133,7 +133,10 @@ If using Visual Studio, you can confirm that the secret is set by right-clicking To create a key vault and set a client secret, see [About Azure Key Vault secrets (Azure documentation)](/azure/key-vault/secrets/about-secrets), which cross-links resources to get started with Azure Key Vault. To implement the code in this section, record the key vault URI and the secret name from Azure when you create the key vault and secret. When you set the access policy for the secret in the **Access policies** panel: * Only the **Get** secret permission is required. -* Select the application as the **Principal** for the secret. +* Select the application as the **Principal** for the secret. + +> [!IMPORTANT] +> A key vault secret is created with an expiration date. Be sure to track when a key vault secret is going to expire and create a new secret for the app prior to that date passing. The following `GetKeyVaultSecret` method retrieves a secret from a key vault. Add this method to the server project. Adjust the namespace (`BlazorSample.Helpers`) to match your project namespace scheme.