From bed6a6c4604adbafb5716a357e07e3e93bd4ccfa Mon Sep 17 00:00:00 2001 From: Jean-Marc Prieur Date: Tue, 3 Sep 2019 13:33:55 +0200 Subject: [PATCH 1/3] Attempt to simplify the token cache providers DO NOT MERGE Ideally we'd want the implementation of the token cache providers to be simplified. However this is not yet possible because the MSAL Abstract token cache provider contains a boolean telling if the token cache is an app or user token cache (so that the key can be computed). Ideally we'd want the ITokenCache to tell the application if it's an app token cache or a user token cache. --- 2-WebApp-graph-user/2-2-TokenCache/Startup.cs | 3 +- Microsoft.Identity.Web/TokenAcquisition.cs | 17 +++--- .../IMSALUserTokenCacheProvider.cs | 16 ------ .../IMsalAppTokenCacheProvider.cs | 16 ------ .../InMemoryTokenCacheProviderExtension.cs | 25 +-------- .../MsalAppMemoryTokenCacheProvider.cs | 35 ------------ .../MsalPerUserMemoryTokenCacheProvider.cs | 35 ------------ .../MSALAppSessionTokenCacheProvider.cs | 45 ---------------- .../MsalPerUserSessionTokenCacheProvider.cs | 44 --------------- .../SessionTokenCacheProviderExtension.cs | 53 +------------------ .../Sql/MsalAppSqlTokenCacheProvider.cs | 41 -------------- .../Sql/MsalPerUserSqlTokenCacheProvider.cs | 43 --------------- .../Sql/SqlTokenCacheProviderExtension.cs | 36 +------------ 13 files changed, 12 insertions(+), 397 deletions(-) delete mode 100644 Microsoft.Identity.Web/TokenCacheProviders/IMSALUserTokenCacheProvider.cs delete mode 100644 Microsoft.Identity.Web/TokenCacheProviders/IMsalAppTokenCacheProvider.cs delete mode 100644 Microsoft.Identity.Web/TokenCacheProviders/InMemory/MsalAppMemoryTokenCacheProvider.cs delete mode 100644 Microsoft.Identity.Web/TokenCacheProviders/InMemory/MsalPerUserMemoryTokenCacheProvider.cs delete mode 100644 Microsoft.Identity.Web/TokenCacheProviders/Session/MSALAppSessionTokenCacheProvider.cs delete mode 100644 Microsoft.Identity.Web/TokenCacheProviders/Session/MsalPerUserSessionTokenCacheProvider.cs delete mode 100644 Microsoft.Identity.Web/TokenCacheProviders/Sql/MsalAppSqlTokenCacheProvider.cs delete mode 100644 Microsoft.Identity.Web/TokenCacheProviders/Sql/MsalPerUserSqlTokenCacheProvider.cs diff --git a/2-WebApp-graph-user/2-2-TokenCache/Startup.cs b/2-WebApp-graph-user/2-2-TokenCache/Startup.cs index 4f82027c..5dc0139e 100644 --- a/2-WebApp-graph-user/2-2-TokenCache/Startup.cs +++ b/2-WebApp-graph-user/2-2-TokenCache/Startup.cs @@ -51,8 +51,7 @@ public void ConfigureServices(IServiceCollection services) // and chosen token cache implementation services.AddMicrosoftIdentityPlatformAuthentication(Configuration) .AddMsal(Configuration, new string[] { Constants.ScopeUserRead }) - .AddSqlAppTokenCache(msalSqlTokenCacheOptions) - .AddSqlPerUserTokenCache(msalSqlTokenCacheOptions); + .AddSqlTokenCaches(msalSqlTokenCacheOptions); // Add Graph diff --git a/Microsoft.Identity.Web/TokenAcquisition.cs b/Microsoft.Identity.Web/TokenAcquisition.cs index 100ebcf5..015b3471 100644 --- a/Microsoft.Identity.Web/TokenAcquisition.cs +++ b/Microsoft.Identity.Web/TokenAcquisition.cs @@ -29,8 +29,7 @@ public class TokenAcquisition : ITokenAcquisition private readonly AzureADOptions _azureAdOptions; private readonly ConfidentialClientApplicationOptions _applicationOptions; - private readonly IMsalAppTokenCacheProvider _appTokenCacheProvider; - private readonly IMsalUserTokenCacheProvider _userTokenCacheProvider; + private readonly IMsalTokenCacheProvider _tokenCacheProvider; private IConfidentialClientApplication application; private readonly IHttpContextAccessor _httpContextAccessor; @@ -42,11 +41,10 @@ public class TokenAcquisition : ITokenAcquisition /// This constructor is called by ASP.NET Core dependency injection /// /// - /// The App token cache provider + /// The App token cache provider /// The User token cache provider public TokenAcquisition( - IMsalAppTokenCacheProvider appTokenCacheProvider, - IMsalUserTokenCacheProvider userTokenCacheProvider, + IMsalTokenCacheProvider tokenCacheProvider, IHttpContextAccessor httpContextAccessor, IOptions azureAdOptions, IOptions applicationOptions) @@ -54,8 +52,7 @@ public TokenAcquisition( _httpContextAccessor = httpContextAccessor; _azureAdOptions = azureAdOptions.Value; _applicationOptions = applicationOptions.Value; - _appTokenCacheProvider = appTokenCacheProvider; - _userTokenCacheProvider = userTokenCacheProvider; + _tokenCacheProvider = tokenCacheProvider; } /// @@ -283,7 +280,7 @@ public async Task RemoveAccountAsync(RedirectContext context) if (account != null) { await app.RemoveAsync(account).ConfigureAwait(false); - _userTokenCacheProvider?.ClearAsync().ConfigureAwait(false); + _tokenCacheProvider?.ClearAsync().ConfigureAwait(false); } } @@ -328,8 +325,8 @@ private IConfidentialClientApplication BuildConfidentialClientApplication() .Build(); // Initialize token cache providers - _appTokenCacheProvider?.InitializeAsync(app.AppTokenCache); - _userTokenCacheProvider?.InitializeAsync(app.UserTokenCache); + _tokenCacheProvider?.InitializeAsync(app.AppTokenCache, true); + _tokenCacheProvider?.InitializeAsync(app.UserTokenCache, false); return app; } diff --git a/Microsoft.Identity.Web/TokenCacheProviders/IMSALUserTokenCacheProvider.cs b/Microsoft.Identity.Web/TokenCacheProviders/IMSALUserTokenCacheProvider.cs deleted file mode 100644 index 83c5b755..00000000 --- a/Microsoft.Identity.Web/TokenCacheProviders/IMSALUserTokenCacheProvider.cs +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -using Microsoft.Identity.Client; -using System.Threading.Tasks; - -namespace Microsoft.Identity.Web.TokenCacheProviders -{ - /// - /// MSAL token cache provider interface for user accounts - /// - public interface IMsalUserTokenCacheProvider : IMsalTokenCacheProvider - { - Task InitializeAsync(ITokenCache tokenCache); - } -} \ No newline at end of file diff --git a/Microsoft.Identity.Web/TokenCacheProviders/IMsalAppTokenCacheProvider.cs b/Microsoft.Identity.Web/TokenCacheProviders/IMsalAppTokenCacheProvider.cs deleted file mode 100644 index f014b929..00000000 --- a/Microsoft.Identity.Web/TokenCacheProviders/IMsalAppTokenCacheProvider.cs +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -using Microsoft.Identity.Client; -using System.Threading.Tasks; - -namespace Microsoft.Identity.Web.TokenCacheProviders -{ - /// - /// MSAL token cache provider interface for application token cache - /// - public interface IMsalAppTokenCacheProvider : IMsalTokenCacheProvider - { - Task InitializeAsync(ITokenCache tokenCache); - } -} \ No newline at end of file diff --git a/Microsoft.Identity.Web/TokenCacheProviders/InMemory/InMemoryTokenCacheProviderExtension.cs b/Microsoft.Identity.Web/TokenCacheProviders/InMemory/InMemoryTokenCacheProviderExtension.cs index b9b5347a..d176c061 100644 --- a/Microsoft.Identity.Web/TokenCacheProviders/InMemory/InMemoryTokenCacheProviderExtension.cs +++ b/Microsoft.Identity.Web/TokenCacheProviders/InMemory/InMemoryTokenCacheProviderExtension.cs @@ -16,33 +16,10 @@ public static class InMemoryTokenCacheProviderExtension /// public static IServiceCollection AddInMemoryTokenCaches( this IServiceCollection services) - { - AddInMemoryAppTokenCache(services); - AddInMemoryPerUserTokenCache(services); - return services; - } - - /// Adds the in-memory based application token cache to the service collection. - /// The services collection to add to. - /// The MSALMemoryTokenCacheOptions allows the caller to set the token cache expiration - public static IServiceCollection AddInMemoryAppTokenCache( - this IServiceCollection services) - { - services.AddMemoryCache(); - services.AddSingleton(); - return services; - } - - /// Adds the in-memory based per user token cache to the service collection. - /// The services collection to add to. - /// The MSALMemoryTokenCacheOptions allows the caller to set the token cache expiration - /// - public static IServiceCollection AddInMemoryPerUserTokenCache( - this IServiceCollection services) { services.AddMemoryCache(); services.AddHttpContextAccessor(); - services.AddSingleton(); + services.AddSingleton(); return services; } } diff --git a/Microsoft.Identity.Web/TokenCacheProviders/InMemory/MsalAppMemoryTokenCacheProvider.cs b/Microsoft.Identity.Web/TokenCacheProviders/InMemory/MsalAppMemoryTokenCacheProvider.cs deleted file mode 100644 index 2c106551..00000000 --- a/Microsoft.Identity.Web/TokenCacheProviders/InMemory/MsalAppMemoryTokenCacheProvider.cs +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -using System.Security.Principal; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Authentication.AzureAD.UI; -using Microsoft.AspNetCore.Http; -using Microsoft.Extensions.Caching.Memory; -using Microsoft.Extensions.Options; -using Microsoft.Identity.Client; - -namespace Microsoft.Identity.Web.TokenCacheProviders.InMemory -{ - /// - /// An implementation of token cache for Confidential clients backed by MemoryCache. - /// MemoryCache is useful in Api scenarios where there is no HttpContext to cache data. - /// - /// - public class MsalAppMemoryTokenCacheProvider : MsalMemoryTokenCacheProvider, IMsalAppTokenCacheProvider - { - public MsalAppMemoryTokenCacheProvider(IOptions azureAdOptions, - IHttpContextAccessor httpContextAccessor, - IMemoryCache memoryCache, - IOptions cacheOptions) : - base(azureAdOptions, httpContextAccessor, memoryCache, cacheOptions) - { - - } - - public async Task InitializeAsync(ITokenCache tokenCache) - { - await InitializeAsync(tokenCache, true).ConfigureAwait(false); - } - } -} \ No newline at end of file diff --git a/Microsoft.Identity.Web/TokenCacheProviders/InMemory/MsalPerUserMemoryTokenCacheProvider.cs b/Microsoft.Identity.Web/TokenCacheProviders/InMemory/MsalPerUserMemoryTokenCacheProvider.cs deleted file mode 100644 index d3f5f785..00000000 --- a/Microsoft.Identity.Web/TokenCacheProviders/InMemory/MsalPerUserMemoryTokenCacheProvider.cs +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -using Microsoft.AspNetCore.Authentication.AzureAD.UI; -using Microsoft.AspNetCore.Http; -using Microsoft.Extensions.Caching.Memory; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.Options; -using Microsoft.Identity.Client; -using System.Threading.Tasks; - -namespace Microsoft.Identity.Web.TokenCacheProviders.InMemory -{ - /// - /// An implementation of token cache for both Confidential and Public clients backed by MemoryCache. - /// MemoryCache is useful in Api scenarios where there is no HttpContext.Session to cache data. - /// - /// - public class MsalPerUserMemoryTokenCacheProvider : MsalMemoryTokenCacheProvider, IMsalUserTokenCacheProvider - { - public MsalPerUserMemoryTokenCacheProvider(IOptions azureAdOptions, - IHttpContextAccessor httpContextAccessor, - IMemoryCache memoryCache, - IOptions cacheOptions) : - base(azureAdOptions, httpContextAccessor, memoryCache, cacheOptions) - { - - } - - public async Task InitializeAsync(ITokenCache tokenCache) - { - await InitializeAsync(tokenCache, false).ConfigureAwait(false); - } - } -} \ No newline at end of file diff --git a/Microsoft.Identity.Web/TokenCacheProviders/Session/MSALAppSessionTokenCacheProvider.cs b/Microsoft.Identity.Web/TokenCacheProviders/Session/MSALAppSessionTokenCacheProvider.cs deleted file mode 100644 index ab515a1d..00000000 --- a/Microsoft.Identity.Web/TokenCacheProviders/Session/MSALAppSessionTokenCacheProvider.cs +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -using Microsoft.AspNetCore.Authentication.AzureAD.UI; -using Microsoft.AspNetCore.Http; -using Microsoft.Extensions.Options; -using Microsoft.Identity.Client; -using System.Threading.Tasks; - -namespace Microsoft.Identity.Web.TokenCacheProviders.Session -{ - /// - /// An implementation of token cache for Confidential clients backed by Http session. - /// - /// For this session cache to work effectively the aspnetcore session has to be configured properly. - /// The latest guidance is provided at https://docs.microsoft.com/en-us/aspnet/core/fundamentals/app-state - /// - /// // In the method - public void ConfigureServices(IServiceCollection services) in startup.cs, add the following - /// services.AddSession(option => - /// { - /// option.Cookie.IsEssential = true; - /// }); - /// - /// In the method - public void Configure(IApplicationBuilder app, IHostingEnvironment env) in startup.cs, add the following - /// - /// app.UseSession(); // Before UseMvc() - /// - /// - public class MsalAppSessionTokenCacheProvider : MsalSessionTokenCacheProvider, IMsalAppTokenCacheProvider - { - public MsalAppSessionTokenCacheProvider(IOptions azureAdOptions, - IHttpContextAccessor httpContextAccessor) : - base(azureAdOptions, httpContextAccessor) - { - - } - - /// Initializes this instance of TokenCacheProvider with essentials to initialize themselves. - /// The token cache instance of MSAL application - public async Task InitializeAsync(ITokenCache tokenCache) - { - await InitializeAsync(tokenCache, true).ConfigureAwait(false); - } - } -} \ No newline at end of file diff --git a/Microsoft.Identity.Web/TokenCacheProviders/Session/MsalPerUserSessionTokenCacheProvider.cs b/Microsoft.Identity.Web/TokenCacheProviders/Session/MsalPerUserSessionTokenCacheProvider.cs deleted file mode 100644 index 4bcf3d1f..00000000 --- a/Microsoft.Identity.Web/TokenCacheProviders/Session/MsalPerUserSessionTokenCacheProvider.cs +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -using Microsoft.AspNetCore.Authentication.AzureAD.UI; -using Microsoft.AspNetCore.Http; -using Microsoft.Extensions.Options; -using Microsoft.Identity.Client; -using System.Threading.Tasks; - -namespace Microsoft.Identity.Web.TokenCacheProviders.Session -{ - /// - /// This is a MSAL's TokenCache implementation for one user. It uses Http session as a persistence store - /// - /// For this session cache to work effectively the aspnetcore session has to be configured properly. - /// The latest guidance is provided at https://docs.microsoft.com/en-us/aspnet/core/fundamentals/app-state - /// - /// // In the method - public void ConfigureServices(IServiceCollection services) in startup.cs, add the following - /// services.AddSession(option => - /// { - /// option.Cookie.IsEssential = true; - /// }); - /// - /// In the method - public void Configure(IApplicationBuilder app, IHostingEnvironment env) in startup.cs, add the following - /// - /// app.UseSession(); // Before UseMvc() - /// - public class MsalPerUserSessionTokenCacheProvider : MsalSessionTokenCacheProvider, IMsalUserTokenCacheProvider - { - public MsalPerUserSessionTokenCacheProvider(IOptions azureAdOptions, - IHttpContextAccessor httpContextAccessor) : - base(azureAdOptions, httpContextAccessor) - { - - } - - /// Initializes this instance of TokenCacheProvider with essentials to initialize themselves. - /// The token cache instance of MSAL application - public async Task InitializeAsync(ITokenCache tokenCache) - { - await InitializeAsync(tokenCache, true).ConfigureAwait(false); - } - } -} \ No newline at end of file diff --git a/Microsoft.Identity.Web/TokenCacheProviders/Session/SessionTokenCacheProviderExtension.cs b/Microsoft.Identity.Web/TokenCacheProviders/Session/SessionTokenCacheProviderExtension.cs index a16cad3b..8564d4ea 100644 --- a/Microsoft.Identity.Web/TokenCacheProviders/Session/SessionTokenCacheProviderExtension.cs +++ b/Microsoft.Identity.Web/TokenCacheProviders/Session/SessionTokenCacheProviderExtension.cs @@ -50,59 +50,10 @@ public static IServiceCollection AddSessionTokenCaches(this IServiceCollection s }); } - AddSessionAppTokenCache(services); - AddSessionPerUserTokenCache(services); + services.AddHttpContextAccessor();; + services.AddScoped(); return services; } - - /// Adds the Http session based application token cache to the service collection. - /// For this session cache to work effectively the aspnetcore session has to be configured properly. - /// The latest guidance is provided at https://docs.microsoft.com/en-us/aspnet/core/fundamentals/app-state - /// - /// // In the method - public void ConfigureServices(IServiceCollection services) in startup.cs, add the following - /// services.AddSession(option => - /// { - /// option.Cookie.IsEssential = true; - /// }); - /// - /// In the method - public void Configure(IApplicationBuilder app, IHostingEnvironment env) in startup.cs, add the following - /// - /// app.UseSession(); // Before UseMvc() - /// - /// The services collection to add to. - /// - public static IServiceCollection AddSessionAppTokenCache(this IServiceCollection services) - { - services.AddHttpContextAccessor(); - services.AddScoped(); - return services; - } - - /// Adds the http session based per user token cache to the service collection. - /// For this session cache to work effectively the aspnetcore session has to be configured properly. - /// The latest guidance is provided at https://docs.microsoft.com/en-us/aspnet/core/fundamentals/app-state - /// - /// // In the method - public void ConfigureServices(IServiceCollection services) in startup.cs, add the following - /// services.AddSession(option => - /// { - /// option.Cookie.IsEssential = true; - /// }); - /// - /// In the method - public void Configure(IApplicationBuilder app, IHostingEnvironment env) in startup.cs, add the following - /// - /// app.UseSession(); // Before UseMvc() - /// - /// The services collection to add to. - /// - public static IServiceCollection AddSessionPerUserTokenCache(this IServiceCollection services) - { - services.AddHttpContextAccessor(); - services.AddSession(option => - { option.Cookie.IsEssential = true; } - ); - services.AddScoped(); - return services; - } } } \ No newline at end of file diff --git a/Microsoft.Identity.Web/TokenCacheProviders/Sql/MsalAppSqlTokenCacheProvider.cs b/Microsoft.Identity.Web/TokenCacheProviders/Sql/MsalAppSqlTokenCacheProvider.cs deleted file mode 100644 index 42223e35..00000000 --- a/Microsoft.Identity.Web/TokenCacheProviders/Sql/MsalAppSqlTokenCacheProvider.cs +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -using Microsoft.AspNetCore.Authentication.AzureAD.UI; -using Microsoft.AspNetCore.DataProtection; -using Microsoft.AspNetCore.Http; -using Microsoft.Extensions.Options; -using Microsoft.Identity.Client; -using System; -using System.Threading.Tasks; - -namespace Microsoft.Identity.Web.TokenCacheProviders.Sql -{ - /// - /// An implementation of token cache for Confidential clients backed by Sql server and Entity Framework - /// - /// - public class MsalAppSqlTokenCacheProvider : MsalSqlTokenCacheProvider, IMsalAppTokenCacheProvider - { - /// Initializes a new instance of the class. - /// The token cache database context. - /// The azure ad options accessor. - /// The protection provider. - /// - /// protectionProvider - The app token cache needs an {nameof(IDataProtectionProvider)} to operate. Please use 'serviceCollection.AddDataProtection();' to add the data protection provider to the service collection - /// or - /// protectionProvider - The app token cache needs the '{nameof(AzureADOptions)}' section in configuration, populated with clientId to initialize. - /// - public MsalAppSqlTokenCacheProvider(IHttpContextAccessor httpContextAccessor, TokenCacheDbContext tokenCacheDbContext, IOptions azureAdOptionsAccessor, IDataProtectionProvider protectionProvider) - : base(httpContextAccessor, tokenCacheDbContext, azureAdOptionsAccessor, protectionProvider) - { - } - - /// Initializes this instance of TokenCacheProvider with essentials to initialize themselves. - /// The token cache instance of MSAL application - public async Task InitializeAsync(ITokenCache tokenCache) - { - await InitializeAsync(tokenCache, true).ConfigureAwait(false); - } - } -} \ No newline at end of file diff --git a/Microsoft.Identity.Web/TokenCacheProviders/Sql/MsalPerUserSqlTokenCacheProvider.cs b/Microsoft.Identity.Web/TokenCacheProviders/Sql/MsalPerUserSqlTokenCacheProvider.cs deleted file mode 100644 index 87cf5b68..00000000 --- a/Microsoft.Identity.Web/TokenCacheProviders/Sql/MsalPerUserSqlTokenCacheProvider.cs +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -using Microsoft.AspNetCore.Authentication.AzureAD.UI; -using Microsoft.AspNetCore.DataProtection; -using Microsoft.AspNetCore.Http; -using Microsoft.EntityFrameworkCore; -using Microsoft.Extensions.Options; -using Microsoft.Identity.Client; -using System; -using System.Linq; -using System.Threading.Tasks; - -namespace Microsoft.Identity.Web.TokenCacheProviders.Sql -{ - /// - /// This is a MSAL's TokenCache implementation for one user. It uses Sql server as the persistence store and uses the Entity Framework to read and write to that database. - /// - /// - public class MsalPerUserSqlTokenCacheProvider : MsalSqlTokenCacheProvider, IMsalUserTokenCacheProvider - { - /// Initializes a new instance of the class. - /// The token cache database context. - /// The azure ad options accessor. - /// The protection provider. - /// - /// protectionProvider - The app token cache needs an {nameof(IDataProtectionProvider)} to operate. Please use 'serviceCollection.AddDataProtection();' to add the data protection provider to the service collection - /// or - /// protectionProvider - The app token cache needs the '{nameof(AzureADOptions)}' section in configuration, populated with clientId to initialize. - /// - public MsalPerUserSqlTokenCacheProvider(IHttpContextAccessor httpContextAccessor, TokenCacheDbContext tokenCacheDbContext, IOptions azureAdOptionsAccessor, IDataProtectionProvider protectionProvider) - : base(httpContextAccessor, tokenCacheDbContext, azureAdOptionsAccessor, protectionProvider) - { - } - - /// Initializes this instance of TokenCacheProvider with essentials to initialize themselves. - /// The token cache instance of MSAL application - public async Task InitializeAsync(ITokenCache tokenCache) - { - await InitializeAsync(tokenCache, false).ConfigureAwait(false); - } - } -} \ No newline at end of file diff --git a/Microsoft.Identity.Web/TokenCacheProviders/Sql/SqlTokenCacheProviderExtension.cs b/Microsoft.Identity.Web/TokenCacheProviders/Sql/SqlTokenCacheProviderExtension.cs index 2592be80..874f5a19 100644 --- a/Microsoft.Identity.Web/TokenCacheProviders/Sql/SqlTokenCacheProviderExtension.cs +++ b/Microsoft.Identity.Web/TokenCacheProviders/Sql/SqlTokenCacheProviderExtension.cs @@ -1,12 +1,10 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -using Microsoft.AspNetCore.Authentication.AzureAD.UI; using Microsoft.AspNetCore.DataProtection; using Microsoft.AspNetCore.Http; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Options; namespace Microsoft.Identity.Web.TokenCacheProviders.Sql { @@ -22,37 +20,6 @@ public static class SqlTokenCacheProviderExtension public static IServiceCollection AddSqlTokenCaches( this IServiceCollection services, MsalSqlTokenCacheOptions sqlTokenCacheOptions) - { - AddSqlAppTokenCache(services, sqlTokenCacheOptions); - AddSqlPerUserTokenCache(services, sqlTokenCacheOptions); - return services; - } - - /// Adds the Sql Server based application token cache to the service collection. - /// The services collection to add to. - /// The MSALSqlTokenCacheOptions is used by the caller to specify the Sql connection string - /// - public static IServiceCollection AddSqlAppTokenCache( - this IServiceCollection services, - MsalSqlTokenCacheOptions sqlTokenCacheOptions) - { - services.AddDataProtection(); - - services.AddDbContext(options => - options.UseSqlServer(sqlTokenCacheOptions.SqlConnectionString)); - - services.AddScoped(); - - return services; - } - - /// Adds the Sql Server based per user token cache to the service collection. - /// The services collection to add to. - /// The MSALSqlTokenCacheOptions is used by the caller to specify the Sql connection string - /// - public static IServiceCollection AddSqlPerUserTokenCache( - this IServiceCollection services, - MsalSqlTokenCacheOptions sqlTokenCacheOptions) { // To share protected payloads among apps, configure SetApplicationName in each app with the same value. // https://docs.microsoft.com/en-us/aspnet/core/security/data-protection/configuration/overview?view=aspnetcore-2.2#setapplicationname @@ -63,8 +30,7 @@ public static IServiceCollection AddSqlPerUserTokenCache( options.UseSqlServer(sqlTokenCacheOptions.SqlConnectionString)); services.AddSingleton(); - - services.AddScoped(); + services.AddScoped(); return services; } From 0efd1697a6597a1138b5ebaada380792a90801b2 Mon Sep 17 00:00:00 2001 From: Jean-Marc Prieur Date: Wed, 23 Oct 2019 16:41:04 +0200 Subject: [PATCH 2/3] Updating the PR now that MSAL.NET's TokenCacheNotificationArgs has a member named IsApplicationTokenCache, brought by https://github.com/AzureAD/microsoft-authentication-library-for-dotnet/pull/1448 cc: @bgavrilMS @jennyf19 --- .../Microsoft.Identity.Web.csproj | 2 +- .../DistributedTokenCacheAdapterExtension.cs | 4 +- .../MsalAppDistributedTokenCacheProvider.cs | 36 ------------------ ...salPerUserDistributedTokenCacheProvider.cs | 37 ------------------- .../MsalAbstractTokenCacheProvider.cs | 32 ++++++++-------- .../SessionTokenCacheProviderExtension.cs | 4 +- 6 files changed, 21 insertions(+), 94 deletions(-) delete mode 100644 Microsoft.Identity.Web/TokenCacheProviders/Distributed/MsalAppDistributedTokenCacheProvider.cs delete mode 100644 Microsoft.Identity.Web/TokenCacheProviders/Distributed/MsalPerUserDistributedTokenCacheProvider.cs diff --git a/Microsoft.Identity.Web/Microsoft.Identity.Web.csproj b/Microsoft.Identity.Web/Microsoft.Identity.Web.csproj index 987fad91..ac3bfe12 100644 --- a/Microsoft.Identity.Web/Microsoft.Identity.Web.csproj +++ b/Microsoft.Identity.Web/Microsoft.Identity.Web.csproj @@ -57,6 +57,6 @@ - + diff --git a/Microsoft.Identity.Web/TokenCacheProviders/Distributed/DistributedTokenCacheAdapterExtension.cs b/Microsoft.Identity.Web/TokenCacheProviders/Distributed/DistributedTokenCacheAdapterExtension.cs index 8608b844..c56bc1fb 100644 --- a/Microsoft.Identity.Web/TokenCacheProviders/Distributed/DistributedTokenCacheAdapterExtension.cs +++ b/Microsoft.Identity.Web/TokenCacheProviders/Distributed/DistributedTokenCacheAdapterExtension.cs @@ -29,7 +29,7 @@ public static IServiceCollection AddDistributedAppTokenCache( this IServiceCollection services) { services.AddDistributedMemoryCache(); - services.AddSingleton(); + services.AddSingleton(); return services; } @@ -42,7 +42,7 @@ public static IServiceCollection AddDistributedUserTokenCache( { services.AddDistributedMemoryCache(); services.AddHttpContextAccessor(); - services.AddSingleton(); + services.AddSingleton(); return services; } } diff --git a/Microsoft.Identity.Web/TokenCacheProviders/Distributed/MsalAppDistributedTokenCacheProvider.cs b/Microsoft.Identity.Web/TokenCacheProviders/Distributed/MsalAppDistributedTokenCacheProvider.cs deleted file mode 100644 index 764e333c..00000000 --- a/Microsoft.Identity.Web/TokenCacheProviders/Distributed/MsalAppDistributedTokenCacheProvider.cs +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -using System.Security.Principal; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Authentication.AzureAD.UI; -using Microsoft.AspNetCore.Http; -using Microsoft.Extensions.Caching.Distributed; -using Microsoft.Extensions.Caching.Memory; -using Microsoft.Extensions.Options; -using Microsoft.Identity.Client; - -namespace Microsoft.Identity.Web.TokenCacheProviders.Distributed -{ - /// - /// An implementation of token cache for Confidential clients backed by a IDistributedCache . - /// MemoryCache is useful in Api scenarios where there is no HttpContext to cache data. - /// - /// - public class MsalAppDistributedTokenCacheProvider : MsalDistributedTokenCacheAdapter, IMsalAppTokenCacheProvider - { - public MsalAppDistributedTokenCacheProvider(IOptions azureAdOptions, - IHttpContextAccessor httpContextAccessor, - IDistributedCache memoryCache, - IOptions cacheOptions) : - base(azureAdOptions, httpContextAccessor, memoryCache, cacheOptions) - { - - } - - public async Task InitializeAsync(ITokenCache tokenCache) - { - await InitializeAsync(tokenCache, true).ConfigureAwait(false); - } - } -} \ No newline at end of file diff --git a/Microsoft.Identity.Web/TokenCacheProviders/Distributed/MsalPerUserDistributedTokenCacheProvider.cs b/Microsoft.Identity.Web/TokenCacheProviders/Distributed/MsalPerUserDistributedTokenCacheProvider.cs deleted file mode 100644 index 594588be..00000000 --- a/Microsoft.Identity.Web/TokenCacheProviders/Distributed/MsalPerUserDistributedTokenCacheProvider.cs +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -using Microsoft.AspNetCore.Authentication.AzureAD.UI; -using Microsoft.AspNetCore.Http; -using Microsoft.Extensions.Caching.Memory; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.Options; -using Microsoft.Identity.Client; -using System.Threading.Tasks; -using Microsoft.Extensions.Caching.Distributed; - - -namespace Microsoft.Identity.Web.TokenCacheProviders.Distributed -{ - /// - /// An implementation of token cache for both Confidential and Public clients backed by MemoryCache. - /// MemoryCache is useful in Api scenarios where there is no HttpContext.Session to cache data. - /// - /// - public class MsalPerUserDistributedTokenCacheProvider : MsalDistributedTokenCacheAdapter, IMsalUserTokenCacheProvider - { - public MsalPerUserDistributedTokenCacheProvider(IOptions azureAdOptions, - IHttpContextAccessor httpContextAccessor, - IDistributedCache memoryCache, - IOptions cacheOptions) : - base(azureAdOptions, httpContextAccessor, memoryCache, cacheOptions) - { - - } - - public async Task InitializeAsync(ITokenCache tokenCache) - { - await InitializeAsync(tokenCache, false).ConfigureAwait(false); - } - } -} \ No newline at end of file diff --git a/Microsoft.Identity.Web/TokenCacheProviders/MsalAbstractTokenCacheProvider.cs b/Microsoft.Identity.Web/TokenCacheProviders/MsalAbstractTokenCacheProvider.cs index 040bcdbb..f38c9418 100644 --- a/Microsoft.Identity.Web/TokenCacheProviders/MsalAbstractTokenCacheProvider.cs +++ b/Microsoft.Identity.Web/TokenCacheProviders/MsalAbstractTokenCacheProvider.cs @@ -59,20 +59,16 @@ public Task InitializeAsync(ITokenCache tokenCache, bool isAppTokenCache) /// /// Cache key /// - private string CacheKey + private string GetCacheKey(bool isAppTokenCache) { - get + if (isAppTokenCache) { - if (_isAppTokenCache) - { - return $"{_azureAdOptions.Value.ClientId}_AppTokenCache"; - } - else - { - return _httpContextAccessor.HttpContext.User.GetMsalAccountId(); - } + return $"{_azureAdOptions.Value.ClientId}_AppTokenCache"; + } + else + { + return _httpContextAccessor.HttpContext.User.GetMsalAccountId(); } - } /// @@ -87,18 +83,21 @@ private async Task OnAfterAccessAsync(TokenCacheNotificationArgs args) // if the access operation resulted in a cache update if (args.HasStateChanged) { - if (!string.IsNullOrWhiteSpace(CacheKey)) + string cacheKey = GetCacheKey(args.IsApplicationTokenCache); + if (!string.IsNullOrWhiteSpace(cacheKey)) { - await WriteCacheBytesAsync(CacheKey, args.TokenCache.SerializeMsalV3()).ConfigureAwait(false); + await WriteCacheBytesAsync(cacheKey, args.TokenCache.SerializeMsalV3()).ConfigureAwait(false); } } } private async Task OnBeforeAccessAsync(TokenCacheNotificationArgs args) { - if (!string.IsNullOrEmpty(CacheKey)) + string cacheKey = GetCacheKey(args.IsApplicationTokenCache); + + if (!string.IsNullOrEmpty(cacheKey)) { - byte[] tokenCacheBytes = await ReadCacheBytesAsync(CacheKey).ConfigureAwait(false); + byte[] tokenCacheBytes = await ReadCacheBytesAsync(cacheKey).ConfigureAwait(false); args.TokenCache.DeserializeMsalV3(tokenCacheBytes, shouldClearExistingCache: true); } } @@ -111,7 +110,8 @@ protected virtual Task OnBeforeWriteAsync(TokenCacheNotificationArgs args) public async Task ClearAsync() { - await RemoveKeyAsync(CacheKey).ConfigureAwait(false); + // This is here a user token cache + await RemoveKeyAsync(GetCacheKey(false)).ConfigureAwait(false); } protected abstract Task WriteCacheBytesAsync(string cacheKey, byte[] bytes); diff --git a/Microsoft.Identity.Web/TokenCacheProviders/Session/SessionTokenCacheProviderExtension.cs b/Microsoft.Identity.Web/TokenCacheProviders/Session/SessionTokenCacheProviderExtension.cs index 64563407..754e48e6 100644 --- a/Microsoft.Identity.Web/TokenCacheProviders/Session/SessionTokenCacheProviderExtension.cs +++ b/Microsoft.Identity.Web/TokenCacheProviders/Session/SessionTokenCacheProviderExtension.cs @@ -75,7 +75,7 @@ public static IServiceCollection AddSessionTokenCaches(this IServiceCollection s public static IServiceCollection AddSessionAppTokenCache(this IServiceCollection services) { services.AddHttpContextAccessor(); - services.AddScoped(); + services.AddScoped(); return services; } @@ -101,7 +101,7 @@ public static IServiceCollection AddSessionPerUserTokenCache(this IServiceCollec services.AddSession(option => { option.Cookie.IsEssential = true; } ); - services.AddScoped(); + services.AddScoped(); return services; } } From f5174d97f0397ef445f5bebf09d200f305b5d852 Mon Sep 17 00:00:00 2001 From: Jean-Marc Prieur Date: Wed, 23 Oct 2019 17:21:59 +0200 Subject: [PATCH 3/3] Further simplifying the token cache implementations --- Microsoft.Identity.Web/TokenAcquisition.cs | 4 +-- .../IMsalTokenCacheProvider .cs | 2 +- .../MsalAbstractTokenCacheProvider.cs | 25 ++++++++++++------- 3 files changed, 19 insertions(+), 12 deletions(-) diff --git a/Microsoft.Identity.Web/TokenAcquisition.cs b/Microsoft.Identity.Web/TokenAcquisition.cs index 32c48be3..a2405cce 100644 --- a/Microsoft.Identity.Web/TokenAcquisition.cs +++ b/Microsoft.Identity.Web/TokenAcquisition.cs @@ -323,8 +323,8 @@ private IConfidentialClientApplication BuildConfidentialClientApplication() .Build(); // Initialize token cache providers - _tokenCacheProvider?.InitializeAsync(app.AppTokenCache, true); - _tokenCacheProvider?.InitializeAsync(app.UserTokenCache, false); + _tokenCacheProvider?.InitializeAsync(app.AppTokenCache); + _tokenCacheProvider?.InitializeAsync(app.UserTokenCache); return app; } diff --git a/Microsoft.Identity.Web/TokenCacheProviders/IMsalTokenCacheProvider .cs b/Microsoft.Identity.Web/TokenCacheProviders/IMsalTokenCacheProvider .cs index 8bbfa3c1..bf52e847 100644 --- a/Microsoft.Identity.Web/TokenCacheProviders/IMsalTokenCacheProvider .cs +++ b/Microsoft.Identity.Web/TokenCacheProviders/IMsalTokenCacheProvider .cs @@ -18,7 +18,7 @@ public interface IMsalTokenCacheProvider /// Is the token cache an App token cache or /// a user token cache /// - Task InitializeAsync(ITokenCache tokenCache, bool isAppTokenCache); + Task InitializeAsync(ITokenCache tokenCache); /// /// Clear the cache diff --git a/Microsoft.Identity.Web/TokenCacheProviders/MsalAbstractTokenCacheProvider.cs b/Microsoft.Identity.Web/TokenCacheProviders/MsalAbstractTokenCacheProvider.cs index f38c9418..ef77563d 100644 --- a/Microsoft.Identity.Web/TokenCacheProviders/MsalAbstractTokenCacheProvider.cs +++ b/Microsoft.Identity.Web/TokenCacheProviders/MsalAbstractTokenCacheProvider.cs @@ -23,11 +23,6 @@ public abstract class MsalAbstractTokenCacheProvider : IMsalTokenCacheProvider /// protected readonly IHttpContextAccessor _httpContextAccessor; - /// - /// Is the cache an app token cache, or a user token cache? - /// - private bool _isAppTokenCache; - /// /// Constructor of the abstract token cache provider /// @@ -43,16 +38,13 @@ protected MsalAbstractTokenCacheProvider(IOptions azureAdOptions /// Initializes the token cache serialization. /// /// Token cache to serialize/deserialize - /// Is it an app token cache, or a user token cache /// - public Task InitializeAsync(ITokenCache tokenCache, bool isAppTokenCache) + public Task InitializeAsync(ITokenCache tokenCache) { tokenCache.SetBeforeAccessAsync(OnBeforeAccessAsync); tokenCache.SetAfterAccessAsync(OnAfterAccessAsync); tokenCache.SetBeforeWriteAsync(OnBeforeWriteAsync); - _isAppTokenCache = isAppTokenCache; - return Task.CompletedTask; } @@ -114,10 +106,25 @@ public async Task ClearAsync() await RemoveKeyAsync(GetCacheKey(false)).ConfigureAwait(false); } + /// + /// Method to be implemented by concrete cache serializers to write the cache bytes + /// + /// Cache key + /// Bytes to write + /// protected abstract Task WriteCacheBytesAsync(string cacheKey, byte[] bytes); + /// + /// Method to be implemented by concrete cache serializers to Read the cache bytes + /// + /// Cache key + /// Read bytes protected abstract Task ReadCacheBytesAsync(string cacheKey); + /// + /// Method to be implemented by concrete cache serializers to remove an entry from the cache + /// + /// Cache key protected abstract Task RemoveKeyAsync(string cacheKey); } }