From d06ca94be2db7c29d3a42f73754799a656136b2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Chalet?= Date: Thu, 5 Apr 2018 21:08:33 +0200 Subject: [PATCH] Use unique GUID keys for cache entries to prevent collisions --- .../Stores/OpenIddictApplicationStore.cs | 20 +++------- .../Stores/OpenIddictAuthorizationStore.cs | 37 +++++++------------ .../Stores/OpenIddictScopeStore.cs | 16 +++----- .../Stores/OpenIddictTokenStore.cs | 32 ++++++---------- .../Stores/OpenIddictApplicationStore.cs | 12 ++---- .../Stores/OpenIddictScopeStore.cs | 4 +- 6 files changed, 39 insertions(+), 82 deletions(-) diff --git a/src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictApplicationStore.cs b/src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictApplicationStore.cs index efc2f7e6..a0449c42 100644 --- a/src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictApplicationStore.cs +++ b/src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictApplicationStore.cs @@ -250,9 +250,7 @@ namespace OpenIddict.EntityFrameworkCore throw new ArgumentException("The identifier cannot be null or empty.", nameof(identifier)); } - const string key = nameof(FindByClientIdAsync) + "\x1e" + nameof(identifier); - - var query = Cache.GetOrCreate(key, entry => + var query = Cache.GetOrCreate("b7c5b6ad-572f-4106-9a32-4f1dc1981b73", entry => { entry.SetPriority(CacheItemPriority.NeverRemove); @@ -281,15 +279,13 @@ namespace OpenIddict.EntityFrameworkCore throw new ArgumentException("The identifier cannot be null or empty.", nameof(identifier)); } - const string key = nameof(FindByIdAsync) + "\x1e" + nameof(identifier); - - var query = Cache.GetOrCreate(key, entry => + var query = Cache.GetOrCreate("91082918-b9b9-4701-b969-54e33999a1b9", entry => { entry.SetPriority(CacheItemPriority.NeverRemove); - return EF.CompileAsyncQuery((TContext context, TKey id) => + return EF.CompileAsyncQuery((TContext context, TKey key) => (from application in context.Set().AsTracking() - where application.Id.Equals(id) + where application.Id.Equals(key) select application).FirstOrDefault()); }); @@ -312,14 +308,12 @@ namespace OpenIddict.EntityFrameworkCore throw new ArgumentException("The address cannot be null or empty.", nameof(address)); } - const string key = nameof(FindByPostLogoutRedirectUriAsync) + "\x1e" + nameof(address); - // To optimize the efficiency of the query a bit, only applications whose stringified // PostLogoutRedirectUris contains the specified URL are returned. Once the applications // are retrieved, a second pass is made to ensure only valid elements are returned. // Implementers that use this method in a hot path may want to override this method // to use SQL Server 2016 functions like JSON_VALUE to make the query more efficient. - var query = Cache.GetOrCreate(key, entry => + var query = Cache.GetOrCreate("a805ce67-2c5b-4617-a772-56413dccac45", entry => { entry.SetPriority(CacheItemPriority.NeverRemove); @@ -367,14 +361,12 @@ namespace OpenIddict.EntityFrameworkCore throw new ArgumentException("The address cannot be null or empty.", nameof(address)); } - const string key = nameof(FindByRedirectUriAsync) + "\x1e" + nameof(address); - // To optimize the efficiency of the query a bit, only applications whose stringified // RedirectUris property contains the specified URL are returned. Once the applications // are retrieved, a second pass is made to ensure only valid elements are returned. // Implementers that use this method in a hot path may want to override this method // to use SQL Server 2016 functions like JSON_VALUE to make the query more efficient. - var query = Cache.GetOrCreate(key, entry => + var query = Cache.GetOrCreate("b3883c99-646f-4027-9855-dad8370b977a", entry => { entry.SetPriority(CacheItemPriority.NeverRemove); diff --git a/src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictAuthorizationStore.cs b/src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictAuthorizationStore.cs index 2e290309..beb3d846 100644 --- a/src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictAuthorizationStore.cs +++ b/src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictAuthorizationStore.cs @@ -235,23 +235,21 @@ namespace OpenIddict.EntityFrameworkCore throw new ArgumentException("The client cannot be null or empty.", nameof(client)); } - const string key = nameof(FindAsync) + "\x1e" + nameof(subject) + "\x1e" + nameof(client); - // Note: due to a bug in Entity Framework Core's query visitor, the authorizations can't be // filtered using authorization.Application.Id.Equals(key). To work around this issue, // this method is overriden to use an explicit join before applying the equality check. // See https://github.com/openiddict/openiddict-core/issues/499 for more information. - var query = Cache.GetOrCreate(key, entry => + var query = Cache.GetOrCreate("a3235f5b-2be5-452e-a43e-b10f5d6a01ff", entry => { entry.SetPriority(CacheItemPriority.NeverRemove); - return EF.CompileAsyncQuery((TContext context, TKey id, string principal) => + return EF.CompileAsyncQuery((TContext context, TKey key, string principal) => from authorization in context.Set() .Include(authorization => authorization.Application) .AsTracking() where authorization.Subject == principal join application in context.Set().AsTracking() on authorization.Application.Id equals application.Id - where application.Id.Equals(id) + where application.Id.Equals(key) select authorization); }); @@ -289,23 +287,21 @@ namespace OpenIddict.EntityFrameworkCore throw new ArgumentException("The status cannot be null or empty.", nameof(status)); } - const string key = nameof(FindAsync) + "\x1e" + nameof(subject) + "\x1e" + nameof(client) + "\x1e" + nameof(status); - // Note: due to a bug in Entity Framework Core's query visitor, the authorizations can't be // filtered using authorization.Application.Id.Equals(key). To work around this issue, // this method is overriden to use an explicit join before applying the equality check. // See https://github.com/openiddict/openiddict-core/issues/499 for more information. - var query = Cache.GetOrCreate(key, entry => + var query = Cache.GetOrCreate("bdf6b8aa-cd27-4b23-9961-fdd896a6660e", entry => { entry.SetPriority(CacheItemPriority.NeverRemove); - return EF.CompileAsyncQuery((TContext context, TKey id, string principal, string state) => + return EF.CompileAsyncQuery((TContext context, TKey key, string principal, string state) => from authorization in context.Set() .Include(authorization => authorization.Application) .AsTracking() where authorization.Subject == principal && authorization.Status == state join application in context.Set().AsTracking() on authorization.Application.Id equals application.Id - where application.Id.Equals(id) + where application.Id.Equals(key) select authorization); }); @@ -349,18 +345,15 @@ namespace OpenIddict.EntityFrameworkCore throw new ArgumentException("The type cannot be null or empty.", nameof(type)); } - const string key = nameof(FindAsync) + "\x1e" + nameof(subject) + "\x1e" + - nameof(client) + "\x1e" + nameof(status) + "\x1e" + nameof(type); - // Note: due to a bug in Entity Framework Core's query visitor, the authorizations can't be // filtered using authorization.Application.Id.Equals(key). To work around this issue, // this method is overriden to use an explicit join before applying the equality check. // See https://github.com/openiddict/openiddict-core/issues/499 for more information. - var query = Cache.GetOrCreate(key, entry => + var query = Cache.GetOrCreate("5d06e679-70cd-4f4b-94f7-19ffe9d5d8ab", entry => { entry.SetPriority(CacheItemPriority.NeverRemove); - return EF.CompileAsyncQuery((TContext context, TKey id, string principal, string state, string kind) => + return EF.CompileAsyncQuery((TContext context, TKey key, string principal, string state, string kind) => from authorization in context.Set() .Include(authorization => authorization.Application) .AsTracking() @@ -368,7 +361,7 @@ namespace OpenIddict.EntityFrameworkCore authorization.Status == state && authorization.Type == kind join application in context.Set().AsTracking() on authorization.Application.Id equals application.Id - where application.Id.Equals(id) + where application.Id.Equals(key) select authorization); }); @@ -392,17 +385,15 @@ namespace OpenIddict.EntityFrameworkCore throw new ArgumentException("The identifier cannot be null or empty.", nameof(identifier)); } - const string key = nameof(FindByIdAsync) + "\x1e" + nameof(identifier); - - var query = Cache.GetOrCreate(key, entry => + var query = Cache.GetOrCreate("0f00e136-9277-484a-8ee4-12bf1d889c43", entry => { entry.SetPriority(CacheItemPriority.NeverRemove); - return EF.CompileAsyncQuery((TContext context, TKey id) => + return EF.CompileAsyncQuery((TContext context, TKey key) => (from authorization in context.Set() .Include(authorization => authorization.Application) .AsTracking() - where authorization.Id.Equals(id) + where authorization.Id.Equals(key) select authorization).FirstOrDefault()); }); @@ -426,9 +417,7 @@ namespace OpenIddict.EntityFrameworkCore throw new ArgumentException("The subject cannot be null or empty.", nameof(subject)); } - const string key = nameof(FindBySubjectAsync) + "\x1e" + nameof(subject); - - var query = Cache.GetOrCreate(key, entry => + var query = Cache.GetOrCreate("31e53867-fa49-4d1b-b846-acce353acd0b", entry => { entry.SetPriority(CacheItemPriority.NeverRemove); diff --git a/src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictScopeStore.cs b/src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictScopeStore.cs index 6366bba1..aabaf9b0 100644 --- a/src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictScopeStore.cs +++ b/src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictScopeStore.cs @@ -155,15 +155,13 @@ namespace OpenIddict.EntityFrameworkCore throw new ArgumentException("The identifier cannot be null or empty.", nameof(identifier)); } - const string key = nameof(FindByIdAsync) + "\x1e" + nameof(identifier); - - var query = Cache.GetOrCreate(key, entry => + var query = Cache.GetOrCreate("485f3372-2d38-4418-8d1e-acd8aa0c3555", entry => { entry.SetPriority(CacheItemPriority.NeverRemove); - return EF.CompileAsyncQuery((TContext context, TKey id) => + return EF.CompileAsyncQuery((TContext context, TKey key) => (from scope in context.Set().AsTracking() - where scope.Id.Equals(id) + where scope.Id.Equals(key) select scope).FirstOrDefault()); }); @@ -186,9 +184,7 @@ namespace OpenIddict.EntityFrameworkCore throw new ArgumentException("The scope name cannot be null or empty.", nameof(name)); } - const string key = nameof(FindByNameAsync) + "\x1e" + nameof(name); - - var query = Cache.GetOrCreate(key, entry => + var query = Cache.GetOrCreate("71cb2f7a-7adb-4b3e-8833-772e254f9b03", entry => { entry.SetPriority(CacheItemPriority.NeverRemove); @@ -218,9 +214,7 @@ namespace OpenIddict.EntityFrameworkCore throw new ArgumentException("Scope names cannot be null or empty.", nameof(names)); } - const string key = nameof(FindByNamesAsync) + "\x1e" + nameof(names); - - var query = Cache.GetOrCreate(key, entry => + var query = Cache.GetOrCreate("e19404af-8586-4693-9b9c-8185b653ee2d", entry => { entry.SetPriority(CacheItemPriority.NeverRemove); diff --git a/src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictTokenStore.cs b/src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictTokenStore.cs index 696d8f55..85d5b37c 100644 --- a/src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictTokenStore.cs +++ b/src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictTokenStore.cs @@ -178,23 +178,21 @@ namespace OpenIddict.EntityFrameworkCore throw new ArgumentException("The identifier cannot be null or empty.", nameof(identifier)); } - const string key = nameof(FindByApplicationIdAsync) + "\x1e" + nameof(identifier); - // Note: due to a bug in Entity Framework Core's query visitor, the tokens can't be // filtered using token.Application.Id.Equals(key). To work around this issue, // this method is overriden to use an explicit join before applying the equality check. // See https://github.com/openiddict/openiddict-core/issues/499 for more information. - var query = Cache.GetOrCreate(key, entry => + var query = Cache.GetOrCreate("9c2e8fed-053a-477c-be42-ec4037109be6", entry => { entry.SetPriority(CacheItemPriority.NeverRemove); - return EF.CompileAsyncQuery((TContext context, TKey id) => + return EF.CompileAsyncQuery((TContext context, TKey key) => from token in context.Set() .Include(token => token.Application) .Include(token => token.Authorization) .AsTracking() join application in context.Set().AsTracking() on token.Application.Id equals application.Id - where application.Id.Equals(id) + where application.Id.Equals(key) select token); }); @@ -218,23 +216,21 @@ namespace OpenIddict.EntityFrameworkCore throw new ArgumentException("The identifier cannot be null or empty.", nameof(identifier)); } - const string key = nameof(FindByAuthorizationIdAsync) + "\x1e" + nameof(identifier); - // Note: due to a bug in Entity Framework Core's query visitor, the tokens can't be // filtered using token.Authorization.Id.Equals(key). To work around this issue, // this method is overriden to use an explicit join before applying the equality check. // See https://github.com/openiddict/openiddict-core/issues/499 for more information. - var query = Cache.GetOrCreate(key, entry => + var query = Cache.GetOrCreate("bfc92016-710f-492b-bcf0-48452a832950", entry => { entry.SetPriority(CacheItemPriority.NeverRemove); - return EF.CompileAsyncQuery((TContext context, TKey id) => + return EF.CompileAsyncQuery((TContext context, TKey key) => from token in context.Set() .Include(token => token.Application) .Include(token => token.Authorization) .AsTracking() join authorization in context.Set().AsTracking() on token.Authorization.Id equals authorization.Id - where authorization.Id.Equals(id) + where authorization.Id.Equals(key) select token); }); @@ -258,18 +254,16 @@ namespace OpenIddict.EntityFrameworkCore throw new ArgumentException("The identifier cannot be null or empty.", nameof(identifier)); } - const string key = nameof(FindByIdAsync) + "\x1e" + nameof(identifier); - - var query = Cache.GetOrCreate(key, entry => + var query = Cache.GetOrCreate("a311088f-3b26-4ca7-bbe5-6194d3375777", entry => { entry.SetPriority(CacheItemPriority.NeverRemove); - return EF.CompileAsyncQuery((TContext context, TKey id) => + return EF.CompileAsyncQuery((TContext context, TKey key) => (from token in context.Set() .Include(token => token.Application) .Include(token => token.Authorization) .AsTracking() - where token.Id.Equals(id) + where token.Id.Equals(key) select token).FirstOrDefault()); }); @@ -293,9 +287,7 @@ namespace OpenIddict.EntityFrameworkCore throw new ArgumentException("The identifier cannot be null or empty.", nameof(identifier)); } - const string key = nameof(FindByReferenceIdAsync) + "\x1e" + nameof(identifier); - - var query = Cache.GetOrCreate(key, entry => + var query = Cache.GetOrCreate("26fd749d-9198-466a-b78e-afbc1b4d89d3", entry => { entry.SetPriority(CacheItemPriority.NeverRemove); @@ -327,9 +319,7 @@ namespace OpenIddict.EntityFrameworkCore throw new ArgumentException("The subject cannot be null or empty.", nameof(subject)); } - const string key = nameof(FindBySubjectAsync) + "\x1e" + nameof(subject); - - var query = Cache.GetOrCreate(key, entry => + var query = Cache.GetOrCreate("61a80b05-d069-4e05-b2e2-66d4bc89b492", entry => { entry.SetPriority(CacheItemPriority.NeverRemove); diff --git a/src/OpenIddict.Stores/Stores/OpenIddictApplicationStore.cs b/src/OpenIddict.Stores/Stores/OpenIddictApplicationStore.cs index c3f4ebb6..d422282a 100644 --- a/src/OpenIddict.Stores/Stores/OpenIddictApplicationStore.cs +++ b/src/OpenIddict.Stores/Stores/OpenIddictApplicationStore.cs @@ -392,9 +392,7 @@ namespace OpenIddict.Stores // Note: parsing the stringified permissions is an expensive operation. // To mitigate that, the resulting array is stored in the memory cache. - var key = string.Concat(nameof(GetPermissionsAsync), "\x1e", application.Permissions); - - var permissions = Cache.GetOrCreate(key, entry => + var permissions = Cache.GetOrCreate("0347e0aa-3a26-410a-97e8-a83bdeb21a1f", entry => { entry.SetPriority(CacheItemPriority.High) .SetSlidingExpiration(TimeSpan.FromMinutes(1)); @@ -430,9 +428,7 @@ namespace OpenIddict.Stores // Note: parsing the stringified addresses is an expensive operation. // To mitigate that, the resulting array is stored in the memory cache. - var key = string.Concat(nameof(GetPostLogoutRedirectUrisAsync), "\x1e", application.PostLogoutRedirectUris); - - var addresses = Cache.GetOrCreate(key, entry => + var addresses = Cache.GetOrCreate("fb14dfb9-9216-4b77-bfa9-7e85f8201ff4", entry => { entry.SetPriority(CacheItemPriority.High) .SetSlidingExpiration(TimeSpan.FromMinutes(1)); @@ -492,9 +488,7 @@ namespace OpenIddict.Stores // Note: parsing the stringified addresses is an expensive operation. // To mitigate that, the resulting array is stored in the memory cache. - var key = string.Concat(nameof(GetRedirectUrisAsync), "\x1e", application.RedirectUris); - - var addresses = Cache.GetOrCreate(key, entry => + var addresses = Cache.GetOrCreate("851d6f08-2ee0-4452-bbe5-ab864611ecaa", entry => { entry.SetPriority(CacheItemPriority.High) .SetSlidingExpiration(TimeSpan.FromMinutes(1)); diff --git a/src/OpenIddict.Stores/Stores/OpenIddictScopeStore.cs b/src/OpenIddict.Stores/Stores/OpenIddictScopeStore.cs index 5871229c..2686bd75 100644 --- a/src/OpenIddict.Stores/Stores/OpenIddictScopeStore.cs +++ b/src/OpenIddict.Stores/Stores/OpenIddictScopeStore.cs @@ -301,9 +301,7 @@ namespace OpenIddict.Stores // Note: parsing the stringified resources is an expensive operation. // To mitigate that, the resulting array is stored in the memory cache. - var key = string.Concat(nameof(GetResourcesAsync), "\x1e", scope.Resources); - - var resources = Cache.GetOrCreate(key, entry => + var resources = Cache.GetOrCreate("b6148250-aede-4fb9-a621-07c9bcf238c3", entry => { entry.SetPriority(CacheItemPriority.High) .SetSlidingExpiration(TimeSpan.FromMinutes(1));