Skip to content

Commit 8ecf6d5

Browse files
authored
[Do not merge until MSAL.NET 4.0 releases] Jmprieur/msal4.0 (#107)
* Updating the sample to MSAL.NET 4.0 Using the async serialization in the SessionTokenCacheProviders * Updating README.md with a sample connection string Updating README.md with a sample connection string, for localdb * Improving the Dev experience with the SQL token cache: - proposing a localdb connection string as a comment in the appsettings.json - Now, uncommenting the comments still builds (and it's obvious now which), now builds correctly (renamed tokenCacheDbContext into tokenCacheDbContextForCreation as it used to conflict with the tokenCacheDbContext in the AddScoped block
1 parent e1d8c9a commit 8ecf6d5

File tree

6 files changed

+45
-20
lines changed

6 files changed

+45
-20
lines changed

2-WebApp-graph-user/2-2-TokenCache/README.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,15 @@ Go to the `"2-WebApp-graph-user\2-2-TokenCache"` folder
5151
#### In the appsettings.json file, configure a Sql server database for token caching, if you have not already done so:
5252

5353
1. In the `TokenCacheDbConnStr` key, provide the Sql server connection string to the database you wish to use for token caching.
54+
> Note:
55+
> If you want to test this sample locally with Visual Studio, you might want to use localdb, which is installed with Visual Studio.
56+
> In that case, use the following connection string:
57+
>
58+
> ```XML
59+
> "ConnectionStrings": {
60+
> "TokenCacheDbConnStr": "Data Source=(LocalDb)\\MSSQLLocalDB;Database=MY_TOKEN_CACHE_DATABASE;Trusted_Connection=True;"
61+
> },
62+
> ```
5463
1. If you do not have an existing database and tables needed for token caching, this sample can use [EF Core- code first](https://docs.microsoft.com/en-us/ef/core/get-started/aspnetcore/new-db?tabs=visual-studio) to create a database and tables for you. to do that, follow the steps below.
5564
1. In the file `Microsoft.Identity.Web\Client\TokenCacheProviders\Sql\MSALAppSqlTokenCacheProviderExtension.cs`, uncomment the code under the **// Uncomment the following lines to create the database.**. This comment exists once in the **AddSqlAppTokenCache** and **AddSqlPerUserTokenCache** methods.
5665
1. Run the solution again, when a user signs-in the very first time, the Entity Framework will create the database and tables `AppTokenCache` and `UserTokenCache` for app and user token caching respectively.

2-WebApp-graph-user/2-2-TokenCache/appsettings.json

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,13 @@
99

1010
// To call an API
1111
"ClientSecret": "[Enter app key of the first app as obtained from Azure Portal, e.g. rZJJ9bHSi/cYnYwmQFxLYDn/6EfnrnIfKoNzv9NKgbo]"
12-
},
12+
},
13+
14+
/*
15+
To try the sample locally on your development machine, if you have installed Visual Studio you can
16+
use the following connection string
17+
"TokenCacheDbConnStr": "Data Source=(LocalDb)\\MSSQLLocalDB;Database=MY_TOKEN_CACHE_DATABASE;Trusted_Connection=True;"
18+
*/
1319
"ConnectionStrings": {
1420
"TokenCacheDbConnStr": "[Enter the Sql server connection string, e.g. Server=MY_SQL_SERVER;Database=MY_TOKEN_CACHE_DATABASE;Trusted_Connection=True;"
1521
},

Microsoft.Identity.Web/Client/TokenCacheProviders/Session/MSALAppSessionTokenCacheProvider.cs

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
2929
using System;
3030
using System.Diagnostics;
3131
using System.Threading;
32+
using System.Threading.Tasks;
3233

3334
namespace Microsoft.Identity.Web.Client.TokenCacheProviders
3435
{
@@ -46,7 +47,12 @@ public class MSALAppSessionTokenCacheProvider : IMSALAppTokenCacheProvider
4647
/// <summary>
4748
/// The HTTP context being used by this app
4849
/// </summary>
49-
internal HttpContext HttpContext = null;
50+
internal HttpContext HttpContext { get { return httpContextAccessor.HttpContext; } }
51+
52+
/// <summary>
53+
/// HTTP context accessor
54+
/// </summary>
55+
internal IHttpContextAccessor httpContextAccessor;
5056

5157
/// <summary>
5258
/// The duration till the tokens are kept in memory cache. In production, a higher value , upto 90 days is recommended.
@@ -63,26 +69,26 @@ public class MSALAppSessionTokenCacheProvider : IMSALAppTokenCacheProvider
6369
/// <summary>Initializes a new instance of the <see cref="MSALAppSessionTokenCacheProvider"/> class.</summary>
6470
/// <param name="azureAdOptionsAccessor">The azure ad options accessor.</param>
6571
/// <exception cref="ArgumentNullException">AzureADOptions - The app token cache needs {nameof(AzureADOptions)}</exception>
66-
public MSALAppSessionTokenCacheProvider(IOptionsMonitor<AzureADOptions> azureAdOptionsAccessor)
72+
public MSALAppSessionTokenCacheProvider(IOptionsMonitor<AzureADOptions> azureAdOptionsAccessor, IHttpContextAccessor httpContextAccessor)
6773
{
74+
this.httpContextAccessor = httpContextAccessor;
6875
if (azureAdOptionsAccessor.CurrentValue == null && string.IsNullOrWhiteSpace(azureAdOptionsAccessor.CurrentValue.ClientId))
6976
{
7077
throw new ArgumentNullException(nameof(AzureADOptions), $"The app token cache needs {nameof(AzureADOptions)}, populated with clientId to initialize.");
7178
}
7279

73-
this.AppId = azureAdOptionsAccessor.CurrentValue.ClientId;
80+
AppId = azureAdOptionsAccessor.CurrentValue.ClientId;
7481
}
7582

7683
/// <summary>Initializes this instance of TokenCacheProvider with essentials to initialize themselves.</summary>
7784
/// <param name="tokenCache">The token cache instance of MSAL application</param>
7885
/// <param name="httpcontext">The Httpcontext whose Session will be used for caching.This is required by some providers.</param>
7986
public void Initialize(ITokenCache tokenCache, HttpContext httpcontext)
8087
{
81-
this.AppCacheId = this.AppId + "_AppTokenCache";
82-
this.HttpContext = httpcontext;
88+
AppCacheId = this.AppId + "_AppTokenCache";
8389

84-
tokenCache.SetBeforeAccess(this.AppTokenCacheBeforeAccessNotification);
85-
tokenCache.SetAfterAccess(this.AppTokenCacheAfterAccessNotification);
90+
tokenCache.SetBeforeAccessAsync(this.AppTokenCacheBeforeAccessNotificationAsync);
91+
tokenCache.SetAfterAccessAsync(this.AppTokenCacheAfterAccessNotificationAsync);
8692
tokenCache.SetBeforeWrite(this.AppTokenCacheBeforeWriteNotification);
8793
}
8894

@@ -119,9 +125,9 @@ public void Clear()
119125
/// Triggered right before MSAL needs to access the cache. Reload the cache from the persistence store in case it changed since the last access.
120126
/// </summary>
121127
/// <param name="args">Contains parameters used by the MSAL call accessing the cache.</param>
122-
private void AppTokenCacheBeforeAccessNotification(TokenCacheNotificationArgs args)
128+
private async Task AppTokenCacheBeforeAccessNotificationAsync(TokenCacheNotificationArgs args)
123129
{
124-
this.HttpContext.Session.LoadAsync().Wait();
130+
await this.HttpContext.Session.LoadAsync();
125131

126132
SessionLock.EnterReadLock();
127133
try
@@ -147,7 +153,7 @@ private void AppTokenCacheBeforeAccessNotification(TokenCacheNotificationArgs ar
147153
/// Triggered right after MSAL accessed the cache.
148154
/// </summary>
149155
/// <param name="args">Contains parameters used by the MSAL call accessing the cache.</param>
150-
private void AppTokenCacheAfterAccessNotification(TokenCacheNotificationArgs args)
156+
private async Task AppTokenCacheAfterAccessNotificationAsync(TokenCacheNotificationArgs args)
151157
{
152158
// if the access operation resulted in a cache update
153159
if (args.HasStateChanged)
@@ -159,8 +165,8 @@ private void AppTokenCacheAfterAccessNotification(TokenCacheNotificationArgs arg
159165

160166
// Reflect changes in the persistent store
161167
byte[] blob = args.TokenCache.SerializeMsalV3();
162-
this.HttpContext.Session.Set(this.AppCacheId, blob);
163-
this.HttpContext.Session.CommitAsync().Wait();
168+
HttpContext.Session.Set(this.AppCacheId, blob);
169+
await HttpContext.Session.CommitAsync();
164170
}
165171
finally
166172
{

Microsoft.Identity.Web/Client/TokenCacheProviders/Session/MSALAppSessionTokenCacheProviderExtension.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
2323
*/
2424

2525
using Microsoft.AspNetCore.Authentication.AzureAD.UI;
26+
using Microsoft.AspNetCore.Http;
2627
using Microsoft.Extensions.DependencyInjection;
2728
using Microsoft.Extensions.Options;
2829

@@ -46,9 +47,11 @@ public static IServiceCollection AddSessionTokenCaches(this IServiceCollection s
4647
/// <returns></returns>
4748
public static IServiceCollection AddSessionAppTokenCache(this IServiceCollection services)
4849
{
50+
services.AddHttpContextAccessor();
4951
services.AddScoped<IMSALAppTokenCacheProvider>(factory =>
5052
{
51-
return new MSALAppSessionTokenCacheProvider(factory.GetRequiredService<IOptionsMonitor<AzureADOptions>>());
53+
return new MSALAppSessionTokenCacheProvider(factory.GetRequiredService<IOptionsMonitor<AzureADOptions>>(),
54+
factory.GetRequiredService<IHttpContextAccessor>());
5255
});
5356

5457
return services;

Microsoft.Identity.Web/Client/TokenCacheProviders/Sql/MSALAppSqlTokenCacheProviderExtension.cs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -52,12 +52,13 @@ public static IServiceCollection AddSqlAppTokenCache(this IServiceCollection ser
5252
{
5353
// Uncomment the following lines to create the database. In production scenarios, the database
5454
// will most probably be already present.
55-
//var tokenCacheDbContextBuilder = new DbContextOptionsBuilder<TokenCacheDbContext>();
56-
//tokenCacheDbContextBuilder.UseSqlServer(sqlTokenCacheOptions.SqlConnectionString);
57-
58-
//var tokenCacheDbContext = new TokenCacheDbContext(tokenCacheDbContextBuilder.Options);
59-
//tokenCacheDbContext.Database.EnsureCreated();
55+
/*
56+
var tokenCacheDbContextBuilder = new DbContextOptionsBuilder<TokenCacheDbContext>();
57+
tokenCacheDbContextBuilder.UseSqlServer(sqlTokenCacheOptions.SqlConnectionString);
6058
59+
var tokenCacheDbContextForCreation = new TokenCacheDbContext(tokenCacheDbContextBuilder.Options);
60+
tokenCacheDbContextForCreation.Database.EnsureCreated();
61+
*/
6162
services.AddDataProtection();
6263

6364
services.AddDbContext<TokenCacheDbContext>(options =>

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,6 @@
77
<ItemGroup>
88
<PackageReference Include="Microsoft.AspNetCore.App" />
99
<PackageReference Include="Microsoft.AspNetCore.Authentication.AzureAD.UI" Version="2.2.0" />
10-
<PackageReference Include="Microsoft.Identity.Client" Version="3.0.8" />
10+
<PackageReference Include="Microsoft.Identity.Client" Version="4.0.0" />
1111
</ItemGroup>
1212
</Project>

0 commit comments

Comments
 (0)