Skip to content

Commit 42dd95b

Browse files
authored
Additional shared DP key ring guidance (#35564)
1 parent 5d2fb6b commit 42dd95b

2 files changed

Lines changed: 140 additions & 32 deletions

File tree

aspnetcore/blazor/call-web-api.md

Lines changed: 65 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ description: Learn how to call a web API from Blazor apps.
55
monikerRange: '>= aspnetcore-3.1'
66
ms.author: wpickett
77
ms.custom: mvc
8-
ms.date: 05/30/2025
8+
ms.date: 06/03/2025
99
uid: blazor/call-web-api
1010
---
1111
# Call a web API from ASP.NET Core Blazor
@@ -124,6 +124,10 @@ To configure a production distributed cache provider, see <xref:performance/cach
124124
125125
For more information, see [Token cache serialization: Distributed caches](/entra/msal/dotnet/how-to/token-cache-serialization?tabs=msal#distributed-caches). However, the code examples shown don't apply to ASP.NET Core apps, which configure distributed caches via <xref:Microsoft.Extensions.DependencyInjection.MemoryCacheServiceCollectionExtensions.AddDistributedMemoryCache%2A>, not <xref:Microsoft.Identity.Web.TokenCacheExtensions.AddDistributedTokenCache%2A>.
126126
127+
<!-- DOC AUTHOR NOTE: The next part on using a shared DP key ring is also
128+
covered in the *BWA+Entra* security article. Mirror
129+
changes when updating this portion of content. -->
130+
127131
Use a shared Data Protection key ring in production so that instances of the app across servers in a web farm can decrypt tokens when <xref:Microsoft.Identity.Web.TokenCacheProviders.Distributed.MsalDistributedTokenCacheAdapterOptions.Encrypt%2A?displayProperty=nameWithType> is set to `true`.
128132
129133
> [!NOTE]
@@ -135,22 +139,73 @@ Use a shared Data Protection key ring in production so that instances of the app
135139
>
136140
> Later in the development and testing period, enable token encryption and adopt a shared Data Protection key ring.
137141
138-
The following example shows how to use [Azure Blob Storage and Azure Key Vault](xref:security/data-protection/configuration/overview#protectkeyswithazurekeyvault) for the shared key ring. Add the following packages to the server project of the Blazor Web App:
142+
The following example shows how to use [Azure Blob Storage and Azure Key Vault (`PersistKeysToAzureBlobStorage`/`ProtectKeysWithAzureKeyVault`)](xref:security/data-protection/configuration/overview#protectkeyswithazurekeyvault) for the shared key ring. The service configurations are base case scenarios for demonstration purposes. Before deploying production apps, familiarize yourself with the Azure services and adopt best practices using their dedicated documentation sets, which are listed at the end of this section.
143+
144+
Add the following packages to the server project of the Blazor Web App:
139145
140146
* [`Azure.Extensions.AspNetCore.DataProtection.Blobs`](https://www.nuget.org/packages/Azure.Extensions.AspNetCore.DataProtection.Blobs)
141147
* [`Azure.Extensions.AspNetCore.DataProtection.Keys`](https://www.nuget.org/packages/Azure.Extensions.AspNetCore.DataProtection.Keys)
142148
143149
[!INCLUDE[](~/includes/package-reference.md)]
144150
145-
Configure Azure Blob Storage to maintain the encrypted keys and protect them with Azure Key Vault. In the following example, the `{BLOB URI WITH SAS TOKEN}` placeholder is the full URI where the key file should be stored with the SAS token as a query string parameter, and the `{KEY IDENTIFIER}` placeholder is the key vault key identifier used for key encryption:
151+
> [!NOTE]
152+
> Before proceeding with the following steps, confirm that the app is registered with Microsoft Entra.
153+
154+
Configure Azure Blob Storage to maintain Data Protection keys and encrypt them at rest with Azure Key Vault:
155+
156+
* Create an Azure storage account. The account name in the following example is `contoso`.
157+
158+
* Create a container to hold the Data Protection keys. The container name in the following example is `data-protection`.
159+
160+
* Create the key file on your local machine. In the following example, the key file is named `keys.xml`. You can use a text editor to create the file.
161+
162+
`keys.xml`:
163+
164+
```xml
165+
<?xml version="1.0" encoding="utf-8"?>
166+
<repository>
167+
</repository>
168+
```
169+
170+
* Upload the key file (`keys.xml`) to the container of the storage account. Use the context menu's **View/edit** command at the end of the key row in the portal to confirm that the blob contains the preceding content.
171+
172+
* Use the context menu's **Generate SAS** command to obtain the blob's URI with a shared access signature (SAS). When you create the SAS, use the following permissions: `Read`, `Add`, `Create`, `Write`, `Delete`. The URI is used later where the `{BLOB URI WITH SAS}` placeholder appears.
173+
174+
When establishing the key vault in the Entra or Azure portal:
175+
176+
* Configure the key vault to use a **Vault access policy**. Confirm that public access on the **Networking** step is **enabled** (checked).
177+
178+
* In the **Access policies** pane, create a new access policy with `Get`, `Unwrap Key`, and `Wrap Key` Key permissions. Select the registered application as the service principal.
179+
180+
* When key encryption is active, keys in the key file include the comment, ":::no-loc text="This key is encrypted with Azure Key Vault.":::" After starting the app, select the **View/edit** command from the context menu at the end of the key row to confirm that a key is present with key vault security applied.
181+
182+
The <xref:Microsoft.Extensions.Azure.AzureEventSourceLogForwarder> service in the following example forwards log messages from Azure SDK for logging and requires the [`Microsoft.Extensions.Azure` NuGet package](https://www.nuget.org/packages/Microsoft.Extensions.Azure).
183+
184+
[!INCLUDE[](~/includes/package-reference.md)]
185+
186+
At the top of the `Program` file, provide access to the API in the <xref:Microsoft.Extensions.Azure?displayProperty=fullName> namespace:
187+
188+
```csharp
189+
using Microsoft.Extensions.Azure;
190+
```
191+
192+
Use the following code in the `Program` file where services are registered:
146193
147194
```csharp
195+
builder.Services.TryAddSingleton<AzureEventSourceLogForwarder>();
196+
148197
builder.Services.AddDataProtection()
149-
.PersistKeysToAzureBlobStorage(new Uri("{BLOB URI WITH SAS TOKEN}"))
198+
.PersistKeysToAzureBlobStorage(new Uri("{BLOB URI WITH SAS}"))
150199
.ProtectKeysWithAzureKeyVault(new Uri("{KEY IDENTIFIER}"), new DefaultAzureCredential());
151200
```
152201
153-
For more information on using a shared Data Protection key ring, see <xref:host-and-deploy/web-farm#data-protection> and <xref:security/data-protection/configuration/overview>.
202+
`{BLOB URI WITH SAS}`: The full URI where the key file should be stored with the SAS token as a query string parameter. The URI is generated by Azure Storage when you request a SAS for the uploaded key file. The container name in the following example is `data-protection`, and the storage account name is `contoso`. The key file is named `keys.xml`.
203+
204+
Example: :::no-loc text="https://contoso.blob.core.windows.net/data-protection/keys.xml?sp={PERMISSIONS}&st={START DATETIME}&se={EXPIRATION DATETIME}&spr=https&sv={STORAGE VERSION DATE}&sr=c&sig={TOKEN}":::
205+
206+
`{KEY IDENTIFIER}`: Azure Key Vault key identifier used for key encryption. The key vault name is `contoso` in the following example, and an access policy allows the application to access the key vault with `Get`, `Unwrap Key`, and `Wrap Key` permissions. The example key name is `data-protection`. The version of the key (`{KEY VERSION}` placeholder) is obtained from the key in the Entra or Azure portal after it's created.
207+
208+
Example: :::no-loc text="https://contoso.vault.azure.net/keys/data-protection/{KEY VERSION}":::
154209
155210
Inject <xref:Microsoft.Identity.Abstractions.IDownstreamApi> and call <xref:Microsoft.Identity.Abstractions.IDownstreamApi.CallApiForUserAsync%2A> when calling on behalf of a user:
156211
@@ -180,6 +235,11 @@ For more information, see the following resources:
180235
* *Secure an ASP.NET Core Blazor Web App with Microsoft Entra ID*
181236
* [Non-BFF pattern (Interactive Auto)](xref:blazor/security/blazor-web-app-entra?pivots=non-bff-pattern)
182237
* [BFF pattern (Interactive Auto)](xref:blazor/security/blazor-web-app-entra?pivots=non-bff-pattern-server)
238+
* [Host ASP.NET Core in a web farm: Data Protection](xref:host-and-deploy/web-farm#data-protection)
239+
* <xref:security/data-protection/configuration/overview>
240+
* <xref:security/data-protection/implementation/key-storage-providers>
241+
* [Azure Key Vault documentation](/azure/key-vault/general/)
242+
* [Azure Storage documentation](/azure/storage/)
183243
184244
## Sample apps
185245

0 commit comments

Comments
 (0)