Skip to content

Commit c9c38e5

Browse files
authored
Additional distributed token cache guidance (#35546)
1 parent 8dd727c commit c9c38e5

1 file changed

Lines changed: 76 additions & 3 deletions

File tree

aspnetcore/blazor/security/blazor-web-app-with-entra.md

Lines changed: 76 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -611,7 +611,6 @@ Example:
611611
"ResponseType": "code",
612612
"TenantId": "aaaabbbb-0000-cccc-1111-dddd2222eeee"
613613
},
614-
...
615614
"DownstreamApi": {
616615
"BaseUrl": "https://localhost:7277",
617616
"Scopes": [ "api://11112222-bbbb-3333-cccc-4444dddd5555/Weather.Get" ]
@@ -763,15 +762,89 @@ The following example shows how to use [Azure Blob Storage and Azure Key Vault](
763762
764763
[!INCLUDE[](~/includes/package-reference.md)]
765764
766-
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:
765+
Configure Azure Blob Storage to maintain the encrypted keys and protect them with Azure Key Vault. The following code is typically implemented at the same time that a [production distributed token cache provider](xref:performance/caching/distributed) is implemented. Other options, both within Azure and outside of Azure, are available for managing Data Protection keys across multiple app instances, but the sample app demonstrates how to use Azure services.
766+
767+
The <xref:Microsoft.Extensions.Azure.AzureEventSourceLogForwarder> service in the following example requires the [`Microsoft.Extensions.Azure` NuGet package](https://www.nuget.org/packages/Microsoft.Extensions.Azure) and a `using` statement at the top of the `Program` file for the <xref:Microsoft.Extensions.Azure?displayProperty=fullName> namespace.
768+
769+
[!INCLUDE[](~/includes/package-reference.md)]
767770
768771
```csharp
772+
builder.Services.TryAddSingleton<AzureEventSourceLogForwarder>();
773+
769774
builder.Services.AddDataProtection()
770775
.PersistKeysToAzureBlobStorage(new Uri("{BLOB URI WITH SAS TOKEN}"))
771776
.ProtectKeysWithAzureKeyVault(new Uri("{KEY IDENTIFIER}"), new DefaultAzureCredential());
772777
```
773778
774-
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>.
779+
* `{BLOB URI WITH SAS TOKEN}`: The full URI where the key file should be stored with the SAS (shared access signature) token as a query string parameter. The URI is generated by Azure Storage when you request a SAS after creating a container. The container name in the following example is `data-protection`, and the storage account name is `contoso`. The key file is named `keys.xml`. When you create the SAS, use the following permissions: `Read`, `Write`, `Delete`, `List`, and `Create`.
780+
781+
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}":::
782+
783+
> [!TIP]
784+
> If you run the app once without enabling the code that calls <xref:Microsoft.AspNetCore.DataProtection.AzureDataProtectionBuilderExtensions.ProtectKeysWithAzureKeyVault%2A>, the Data Protection key file (`keys.xml`) is automatically generated in Azure Blob Storage for you. After you've verified the file's presence in Azure Blob Storage with the Storage Browser in the Entra or Azure portal, enable the call to <xref:Microsoft.AspNetCore.DataProtection.AzureDataProtectionBuilderExtensions.ProtectKeysWithAzureKeyVault%2A>.
785+
786+
* `{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`, `Wrap Key`, and `Unwrap Key` permissions. The example key name is `data-protection`. The version of the key for the `{KEY VERSION}` placeholder is obtained from the key in the Entra or Azure Portal after it's created.
787+
788+
Example: :::no-loc text="https://contoso.vault.azure.net/keys/data-protection/{KEY VERSION}":::
789+
790+
To configure the app with app settings, add the following to the app settings file:
791+
792+
```json
793+
"DistributedTokenCache": {
794+
"DisableL1Cache": false,
795+
"L1CacheSizeLimit": 524288000,
796+
"Encrypt": true,
797+
"SlidingExpirationInHours": 1
798+
},
799+
"DataProtection": {
800+
"BlobUriWithSasToken": "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}",
801+
"KeyIdentifier": "https://contoso.vault.azure.net/keys/data-protection/{KEY VERSION}"
802+
}
803+
```
804+
805+
Make the following changes in the `Program` file:
806+
807+
```diff
808+
builder.Services.Configure<MsalDistributedTokenCacheAdapterOptions>(
809+
options =>
810+
{
811+
+ var config = builder.Configuration.GetSection("DistributedTokenCache");
812+
813+
- options.DisableL1Cache = false;
814+
+ options.DisableL1Cache = config.GetValue<bool>("DisableL1Cache");
815+
816+
- options.L1CacheOptions.SizeLimit = 500 * 1024 * 1024;
817+
+ options.L1CacheOptions.SizeLimit = config.GetValue<long>("L1CacheSizeLimit");
818+
819+
- options.Encrypt = true;
820+
+ options.Encrypt = config.GetValue<bool>("Encrypt");
821+
822+
- options.SlidingExpiration = TimeSpan.FromHours(1);
823+
+ options.SlidingExpiration =
824+
+ TimeSpan.FromHours(config.GetValue<int>("SlidingExpirationInHours"));
825+
});
826+
827+
- builder.Services.AddDataProtection()
828+
- .PersistKeysToAzureBlobStorage(new Uri("{BLOB URI WITH SAS TOKEN}"))
829+
- .ProtectKeysWithAzureKeyVault(new Uri("{KEY IDENTIFIER}"), new DefaultAzureCredential());
830+
831+
+ var config = builder.Configuration.GetSection("DataProtection");
832+
833+
+ builder.Services.AddDataProtection()
834+
+ .PersistKeysToAzureBlobStorage(
835+
+ new Uri(config.GetValue<string>("BlobUriWithSasToken") ??
836+
+ throw new Exception("Missing Blob URI")))
837+
+ .ProtectKeysWithAzureKeyVault(
838+
+ new Uri(config.GetValue<string>("KeyIdentifier") ??
839+
+ throw new Exception("Missing Key Identifier")),
840+
+ new DefaultAzureCredential());
841+
```
842+
843+
For more information on using a shared Data Protection key ring and key storage providers, see the following resources:
844+
845+
* <xref:host-and-deploy/web-farm#data-protection>
846+
* <xref:security/data-protection/configuration/overview>
847+
* <xref:security/data-protection/implementation/key-storage-providers>
775848
776849
## Redirect to the home page on logout
777850

0 commit comments

Comments
 (0)