Skip to content

Commit 51f6434

Browse files
author
Kalyan Krishna
committed
2 parents 2ba7770 + 5fc5e04 commit 51f6434

23 files changed

+138
-454
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,3 +101,6 @@
101101
/2-WebApp-graph-user/2-4-Sovereign-Call-MSGraph/bin/Release/netcoreapp2.2
102102
/Microsoft.Identity.Web.Test/bin/Release/netcoreapp2.2
103103
/Microsoft.Identity.Web.Test/obj
104+
/4-WebApp-your-API/4-2-B2C/.vs
105+
/4-WebApp-your-API/4-2-B2C/Client/obj
106+
/4-WebApp-your-API/4-2-B2C/TodoListService/obj

2-WebApp-graph-user/2-2-TokenCache/Startup.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,7 @@ public void ConfigureServices(IServiceCollection services)
5151
// and chosen token cache implementation
5252
services.AddMicrosoftIdentityPlatformAuthentication(Configuration)
5353
.AddMsal(Configuration, new string[] { Constants.ScopeUserRead })
54-
.AddSqlAppTokenCache(msalSqlTokenCacheOptions)
55-
.AddSqlPerUserTokenCache(msalSqlTokenCacheOptions);
54+
.AddSqlTokenCaches(msalSqlTokenCacheOptions);
5655

5756

5857
// Add Graph

3-WebApp-multi-APIs/README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,8 @@ insert
189189

190190
## Troubleshooting
191191

192+
To access Azure Resource Management (ARM), you'll need a work or school account (AAD account) and an Azure subscription. If your Azure subscription is for a Microsoft personal account, just create a new user in your directory, and use this user to run the sample
193+
192194
OpenIdConnectProtocolException: Message contains error: 'invalid_client', error_description: 'AADSTS650052: The app needs access to a service (\"https://*.blob.core.windows.net\") that your organization \"*tenantname*.onmicrosoft.com\" has not subscribed to or enabled. Contact your IT Admin to review the configuration of your service subscriptions.
193195
this is because the AzureStorage API was not registered as an API used by your Web App
194196

@@ -198,4 +200,4 @@ You can learn more about the tokens by looking at the following articles in MSAL
198200

199201
- The [Authorization code flow](https://aka.ms/msal-net-authorization-code), which is used, after the user signed-in with Open ID Connect, in order to get a token and cache it for a later use. See [TokenAcquisition L 107](https://github.com/Azure-Samples/active-directory-aspnetcore-webapp-openidconnect-v2/blob/f99e913cc032e16c59b748241111e97108e87918/Extensions/TokenAcquisition.cs#L107) for details of this code
200202
- [AcquireTokenSilent](https://aka.ms/msal-net-acquiretokensilent ), which is used by the controller to get an access token for the downstream API. See [TokenAcquisition L 168](https://github.com/Azure-Samples/active-directory-aspnetcore-webapp-openidconnect-v2/blob/f99e913cc032e16c59b748241111e97108e87918/Extensions/TokenAcquisition.cs#L168) for details of this code
201-
- [Token cache serialization](msal-net-token-cache-serialization)
203+
- [Token cache serialization](msal-net-token-cache-serialization)

4-WebApp-your-API/README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -417,6 +417,10 @@ In the left-hand navigation pane, select the **Azure Active Directory** service,
417417
> NOTE: Remember, the To Do list is stored in memory in this TodoListService sample. Azure Web Sites will spin down your web site if it is inactive, and your To Do list will get emptied.
418418
Also, if you increase the instance count of the web site, requests will be distributed among the instances. To Do will, therefore, not be the same on each instance.
419419
420+
## Next steps
421+
422+
If you're interested in the Web API calling a downstream API, you might want to have a look at the [ASP.NET Core Web API tutorial](https://github.com/Azure-Samples/active-directory-dotnet-native-aspnetcore-v2), in chapter 2 [2. Web API now calls Microsoft Graph/](https://github.com/Azure-Samples/active-directory-dotnet-native-aspnetcore-v2/tree/master/2.%20Web%20API%20now%20calls%20Microsoft%20Graph). The client is a desktop app there, whereas you have a Web App, but apart from that all the app registration steps apply.
423+
420424
## Community Help and Support
421425
422426
Use [Stack Overflow](http://stackoverflow.com/questions/tagged/msal) to get support from the community.

6-Deploy-to-Azure/README.md

Lines changed: 78 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,84 @@ In the left-hand navigation pane, select the **Azure Active Directory** service,
5252

5353
Secure key management is essential to protect data in the cloud. Use [Azure Key Vault](https://azure.microsoft.com/en-ca/services/key-vault/) to encrypt keys and small secrets like passwords that use keys stored in hardware security modules (HSMs).
5454

55-
You can follow [this sample](https://github.com/Azure-Samples/app-service-msi-keyvault-dotnet) as a guide on how to use Azure KeyVault from App Service with Managed Service Identity (MSI).
55+
Use [this sample](https://github.com/Azure-Samples/app-service-msi-keyvault-dotnet) as a guide on how to use Azure Key Vault from App Service with Managed Service Identity (MSI).
56+
57+
## MSAL token cache on distributed environments
58+
59+
The samples in this tutorial have their token cache providers configured for apps running on a single machine. On a production environment, these apps could be deployed in many machines for scalability purpose, so the token cache provider needs to be configured accordingly for this distributed architecture.
60+
61+
These are the necessary changes for each cache provider option:
62+
63+
### In memory
64+
65+
If you want to use in memory cache, use this configuration on `Startup.cs`:
66+
67+
```csharp
68+
services.AddDistributedTokenCaches()
69+
.AddDistributedMemoryCache();
70+
```
71+
72+
### Redis
73+
74+
If you want to use a distributed Redis cache, use this configuration on `Startup.cs`:
75+
76+
```csharp
77+
services.AddDistributedTokenCaches()
78+
.AddStackExchangeRedisCache(options =>
79+
{
80+
options.Configuration = "<your_redis_primary_connection_string_here>";
81+
options.InstanceName = "<your_redis_instance_name>";
82+
});
83+
```
84+
85+
### SQL Server
86+
87+
There are two options for distributed SQL cache:
88+
89+
- [using .Net Core distributed cache extensions](https://docs.microsoft.com/en-us/aspnet/core/performance/caching/distributed?view=aspnetcore-2.2)
90+
- [configuring DataProtection for distributed environments](https://docs.microsoft.com/en-us/aspnet/core/security/data-protection/configuration/overview?view=aspnetcore-2.2)
91+
92+
#### If you want to use .Net Core distributed cache extensions
93+
94+
Create the cache database by running the CLI (change the parameters according to your configurations)
95+
96+
```csharp
97+
dotnet sql-cache create "<your DB connection string>" dbo <cacheTableName>
98+
```
99+
100+
Then use this configuration on `Startup.cs`:
101+
102+
```csharp
103+
services.AddDistributedTokenCaches()
104+
.AddDistributedSqlServerCache(options =>
105+
{
106+
options.ConnectionString = "<your_sql_connection_string_here>";
107+
options.SchemaName = "dbo";
108+
options.TableName = "<your_cache_table_name_here>";
109+
});
110+
```
111+
112+
#### If you want to configure `DataProtection` for distributed environments
113+
114+
You have to configure the key ring storage to a centralized location. It could be in [Azure Key Vault](https://azure.microsoft.com/services/key-vault/) or on a [UNC share](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-dfsc/149a3039-98ce-491a-9268-2f5ddef08192).
115+
116+
> **Note**: If you change the key persistence location, the system no longer automatically encrypts keys at rest. It is recommended that you use one of the ProtectKeysWith* methods listed [in this doc](https://docs.microsoft.com/en-us/aspnet/core/security/data-protection/configuration/overview?view=aspnetcore-2.2).
117+
118+
For Azure Key Vault, configure the system with [PersistKeysToAzureBlobStorage](https://docs.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.dataprotection.azuredataprotectionbuilderextensions.persistkeystoazureblobstorage?view=aspnetcore-2.2) (also consider using [ProtectKeysWithAzureKeyVault](https://docs.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.dataprotection.azuredataprotectionbuilderextensions.protectkeyswithazurekeyvault)) in the `Startup` class:
119+
120+
```csharp
121+
services.AddDataProtection()
122+
.PersistKeysToAzureBlobStorage("<storage account connection or uri>");
123+
```
124+
125+
> **Note**: Your app must have **Unwrap Key** and **Wrap Key** permissions to the Azure Key Vault.
126+
127+
For UNC share, configure the system with [PersistKeysToFileSystem](https://docs.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.dataprotection.dataprotectionbuilderextensions.persistkeystofilesystem) (also consider using [ProtectKeysWithCertificate](https://docs.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.dataprotection.dataprotectionbuilderextensions.protectkeyswithcertificate?view=aspnetcore-2.2)) in the `Startup` class:
128+
129+
```csharp
130+
services.AddDataProtection()
131+
.PersistKeysToFileSystem(new DirectoryInfo(@"\\server\share\directory\"));
132+
```
56133

57134
## Community Help and Support
58135

Microsoft.Identity.Web/Microsoft.Identity.Web.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,6 @@
5757
<PackageReference Include="Microsoft.AspNetCore.Authentication.AzureAD.UI" Version="2.2.0" />
5858
<PackageReference Include="Microsoft.AspNetCore.Authentication.AzureADB2C.UI" Version="2.2.0" />
5959
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="2.2.0" />
60-
<PackageReference Include="Microsoft.Identity.Client" Version="4.5.1" />
60+
<PackageReference Include="Microsoft.Identity.Client" Version="4.6.0" />
6161
</ItemGroup>
6262
</Project>

Microsoft.Identity.Web/TokenAcquisition.cs

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,7 @@ public class TokenAcquisition : ITokenAcquisition
2929
private readonly AzureADOptions _azureAdOptions;
3030
private readonly ConfidentialClientApplicationOptions _applicationOptions;
3131

32-
private readonly IMsalAppTokenCacheProvider _appTokenCacheProvider;
33-
private readonly IMsalUserTokenCacheProvider _userTokenCacheProvider;
32+
private readonly IMsalTokenCacheProvider _tokenCacheProvider;
3433

3534
private IConfidentialClientApplication application;
3635
private readonly IHttpContextAccessor _httpContextAccessor;
@@ -42,20 +41,18 @@ public class TokenAcquisition : ITokenAcquisition
4241
/// This constructor is called by ASP.NET Core dependency injection
4342
/// </summary>
4443
/// <param name="configuration"></param>
45-
/// <param name="appTokenCacheProvider">The App token cache provider</param>
44+
/// <param name="tokenCacheProvider">The App token cache provider</param>
4645
/// <param name="userTokenCacheProvider">The User token cache provider</param>
4746
public TokenAcquisition(
48-
IMsalAppTokenCacheProvider appTokenCacheProvider,
49-
IMsalUserTokenCacheProvider userTokenCacheProvider,
47+
IMsalTokenCacheProvider tokenCacheProvider,
5048
IHttpContextAccessor httpContextAccessor,
5149
IOptions<AzureADOptions> azureAdOptions,
5250
IOptions<ConfidentialClientApplicationOptions> applicationOptions)
5351
{
5452
_httpContextAccessor = httpContextAccessor;
5553
_azureAdOptions = azureAdOptions.Value;
5654
_applicationOptions = applicationOptions.Value;
57-
_appTokenCacheProvider = appTokenCacheProvider;
58-
_userTokenCacheProvider = userTokenCacheProvider;
55+
_tokenCacheProvider = tokenCacheProvider;
5956
}
6057

6158
/// <summary>
@@ -283,7 +280,7 @@ public async Task RemoveAccountAsync(RedirectContext context)
283280
if (account != null)
284281
{
285282
await app.RemoveAsync(account).ConfigureAwait(false);
286-
_userTokenCacheProvider?.ClearAsync().ConfigureAwait(false);
283+
_tokenCacheProvider?.ClearAsync().ConfigureAwait(false);
287284
}
288285
}
289286

@@ -326,8 +323,8 @@ private IConfidentialClientApplication BuildConfidentialClientApplication()
326323
.Build();
327324

328325
// Initialize token cache providers
329-
_appTokenCacheProvider?.InitializeAsync(app.AppTokenCache);
330-
_userTokenCacheProvider?.InitializeAsync(app.UserTokenCache);
326+
_tokenCacheProvider?.InitializeAsync(app.AppTokenCache);
327+
_tokenCacheProvider?.InitializeAsync(app.UserTokenCache);
331328

332329
return app;
333330
}

Microsoft.Identity.Web/TokenCacheProviders/Distributed/DistributedTokenCacheAdapterExtension.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ public static IServiceCollection AddDistributedAppTokenCache(
2929
this IServiceCollection services)
3030
{
3131
services.AddDistributedMemoryCache();
32-
services.AddSingleton<IMsalAppTokenCacheProvider, MsalAppDistributedTokenCacheProvider>();
32+
services.AddSingleton<IMsalTokenCacheProvider, MsalDistributedTokenCacheAdapter>();
3333
return services;
3434
}
3535

@@ -42,7 +42,7 @@ public static IServiceCollection AddDistributedUserTokenCache(
4242
{
4343
services.AddDistributedMemoryCache();
4444
services.AddHttpContextAccessor();
45-
services.AddSingleton<IMsalUserTokenCacheProvider, MsalPerUserDistributedTokenCacheProvider>();
45+
services.AddSingleton<IMsalTokenCacheProvider, MsalDistributedTokenCacheAdapter>();
4646
return services;
4747
}
4848
}

Microsoft.Identity.Web/TokenCacheProviders/Distributed/MsalAppDistributedTokenCacheProvider.cs

Lines changed: 0 additions & 36 deletions
This file was deleted.

Microsoft.Identity.Web/TokenCacheProviders/Distributed/MsalPerUserDistributedTokenCacheProvider.cs

Lines changed: 0 additions & 37 deletions
This file was deleted.

0 commit comments

Comments
 (0)