diff --git a/identity-server/hosts/UI/Main/Pages/Grants/Index.cshtml.cs b/identity-server/hosts/UI/Main/Pages/Grants/Index.cshtml.cs
index 985616b00..337d628e6 100644
--- a/identity-server/hosts/UI/Main/Pages/Grants/Index.cshtml.cs
+++ b/identity-server/hosts/UI/Main/Pages/Grants/Index.cshtml.cs
@@ -43,7 +43,7 @@ public class Index : PageModel
var client = await _clients.FindClientByIdAsync(grant.ClientId, HttpContext.RequestAborted);
if (client != null)
{
- var resources = await _resources.FindResourcesByScopeAsync(grant.Scopes);
+ var resources = await _resources.FindResourcesByScopeAsync(grant.Scopes, HttpContext.RequestAborted);
var item = new GrantViewModel()
{
diff --git a/identity-server/src/EntityFramework.Storage/Stores/ResourceStore.cs b/identity-server/src/EntityFramework.Storage/Stores/ResourceStore.cs
index c1b0012f4..9745966e0 100644
--- a/identity-server/src/EntityFramework.Storage/Stores/ResourceStore.cs
+++ b/identity-server/src/EntityFramework.Storage/Stores/ResourceStore.cs
@@ -52,8 +52,9 @@ public class ResourceStore : IResourceStore
/// Finds the API resources by name.
///
/// The names.
+ ///
///
- public virtual async Task> FindApiResourcesByNameAsync(IEnumerable apiResourceNames)
+ public virtual async Task> FindApiResourcesByNameAsync(IEnumerable apiResourceNames, CT ct)
{
using var activity = Tracing.StoreActivitySource.StartActivity("ResourceStore.FindApiResourcesByName");
activity?.SetTag(Tracing.Properties.ApiResourceNames, apiResourceNames.ToSpaceSeparatedString());
@@ -72,7 +73,7 @@ public class ResourceStore : IResourceStore
.Include(x => x.Properties)
.AsNoTracking();
- var result = (await apis.ToArrayAsync(CancellationTokenProvider.CancellationToken))
+ var result = (await apis.ToArrayAsync(ct))
.Where(x => apiResourceNames.Contains(x.Name))
.Select(x => x.ToModel()).ToArray();
@@ -92,8 +93,9 @@ public class ResourceStore : IResourceStore
/// Gets API resources by scope name.
///
///
+ ///
///
- public virtual async Task> FindApiResourcesByScopeNameAsync(IEnumerable scopeNames)
+ public virtual async Task> FindApiResourcesByScopeNameAsync(IEnumerable scopeNames, CT ct)
{
using var activity = Tracing.StoreActivitySource.StartActivity("ResourceStore.FindApiResourcesByScopeName");
activity?.SetTag(Tracing.Properties.ScopeNames, scopeNames.ToSpaceSeparatedString());
@@ -112,7 +114,7 @@ public class ResourceStore : IResourceStore
.Include(x => x.Properties)
.AsNoTracking();
- var results = (await apis.ToArrayAsync(CancellationTokenProvider.CancellationToken))
+ var results = (await apis.ToArrayAsync(ct))
.Where(api => api.Scopes.Any(x => names.Contains(x.Scope)));
var models = results.Select(x => x.ToModel()).ToArray();
@@ -125,8 +127,9 @@ public class ResourceStore : IResourceStore
/// Gets identity resources by scope name.
///
///
+ ///
///
- public virtual async Task> FindIdentityResourcesByScopeNameAsync(IEnumerable scopeNames)
+ public virtual async Task> FindIdentityResourcesByScopeNameAsync(IEnumerable scopeNames, CT ct)
{
using var activity = Tracing.StoreActivitySource.StartActivity("ResourceStore.FindIdentityResourcesByScopeName");
activity?.SetTag(Tracing.Properties.ScopeNames, scopeNames.ToSpaceSeparatedString());
@@ -143,7 +146,7 @@ public class ResourceStore : IResourceStore
.Include(x => x.Properties)
.AsNoTracking();
- var results = (await resources.ToArrayAsync(CancellationTokenProvider.CancellationToken))
+ var results = (await resources.ToArrayAsync(ct))
.Where(x => scopes.Contains(x.Name));
Logger.LogDebug("Found {scopes} identity scopes in database", results.Select(x => x.Name));
@@ -155,8 +158,9 @@ public class ResourceStore : IResourceStore
/// Gets scopes by scope name.
///
///
+ ///
///
- public virtual async Task> FindApiScopesByNameAsync(IEnumerable scopeNames)
+ public virtual async Task> FindApiScopesByNameAsync(IEnumerable scopeNames, CT ct)
{
using var activity = Tracing.StoreActivitySource.StartActivity("ResourceStore.FindApiScopesByName");
activity?.SetTag(Tracing.Properties.ScopeNames, scopeNames.ToSpaceSeparatedString());
@@ -173,7 +177,7 @@ public class ResourceStore : IResourceStore
.Include(x => x.Properties)
.AsNoTracking();
- var results = (await resources.ToArrayAsync(CancellationTokenProvider.CancellationToken))
+ var results = (await resources.ToArrayAsync(ct))
.Where(x => scopes.Contains(x.Name));
Logger.LogDebug("Found {scopes} scopes in database", results.Select(x => x.Name));
@@ -185,7 +189,7 @@ public class ResourceStore : IResourceStore
/// Gets all resources.
///
///
- public virtual async Task GetAllResourcesAsync()
+ public virtual async Task GetAllResourcesAsync(CT ct)
{
using var activity = Tracing.StoreActivitySource.StartActivity("ResourceStore.GetAllResources");
@@ -207,9 +211,9 @@ public class ResourceStore : IResourceStore
.AsNoTracking();
var result = new Resources(
- (await identity.ToArrayAsync(CancellationTokenProvider.CancellationToken)).Select(x => x.ToModel()),
- (await apis.ToArrayAsync(CancellationTokenProvider.CancellationToken)).Select(x => x.ToModel()),
- (await scopes.ToArrayAsync(CancellationTokenProvider.CancellationToken)).Select(x => x.ToModel())
+ (await identity.ToArrayAsync(ct)).Select(x => x.ToModel()),
+ (await apis.ToArrayAsync(ct)).Select(x => x.ToModel()),
+ (await scopes.ToArrayAsync(ct)).Select(x => x.ToModel())
);
Logger.LogDebug("Found {scopes} as all scopes, and {apis} as API resources",
diff --git a/identity-server/src/IdentityServer/Extensions/IResourceStoreExtensions.cs b/identity-server/src/IdentityServer/Extensions/IResourceStoreExtensions.cs
index d658dd740..0cbb6b9f4 100644
--- a/identity-server/src/IdentityServer/Extensions/IResourceStoreExtensions.cs
+++ b/identity-server/src/IdentityServer/Extensions/IResourceStoreExtensions.cs
@@ -16,12 +16,13 @@ public static class IResourceStoreExtensions
///
/// The store.
/// The scope names.
+ /// The used to propagate notifications that the operation should be cancelled.
///
- public static async Task FindResourcesByScopeAsync(this IResourceStore store, IEnumerable scopeNames)
+ public static async Task FindResourcesByScopeAsync(this IResourceStore store, IEnumerable scopeNames, CT ct)
{
- var identity = await store.FindIdentityResourcesByScopeNameAsync(scopeNames);
- var apiResources = await store.FindApiResourcesByScopeNameAsync(scopeNames);
- var scopes = await store.FindApiScopesByNameAsync(scopeNames);
+ var identity = await store.FindIdentityResourcesByScopeNameAsync(scopeNames, ct);
+ var apiResources = await store.FindApiResourcesByScopeNameAsync(scopeNames, ct);
+ var scopes = await store.FindApiScopesByNameAsync(scopeNames, ct);
ValidateNameUniqueness(identity, apiResources, scopes);
@@ -88,17 +89,19 @@ public static class IResourceStoreExtensions
///
/// The store.
/// The scope names.
+ /// The used to propagate notifications that the operation should be cancelled.
///
- public static async Task FindEnabledResourcesByScopeAsync(this IResourceStore store, IEnumerable scopeNames) => (await store.FindResourcesByScopeAsync(scopeNames)).FilterEnabled();
+ public static async Task FindEnabledResourcesByScopeAsync(this IResourceStore store, IEnumerable scopeNames, CT ct) => (await store.FindResourcesByScopeAsync(scopeNames, ct)).FilterEnabled();
///
/// Gets all enabled resources.
///
/// The store.
+ /// The used to propagate notifications that the operation should be cancelled.
///
- public static async Task GetAllEnabledResourcesAsync(this IResourceStore store)
+ public static async Task GetAllEnabledResourcesAsync(this IResourceStore store, CT ct)
{
- var resources = await store.GetAllResourcesAsync();
+ var resources = await store.GetAllResourcesAsync(ct);
ValidateNameUniqueness(resources.IdentityResources, resources.ApiResources, resources.ApiScopes);
return resources.FilterEnabled();
@@ -109,11 +112,15 @@ public static class IResourceStoreExtensions
///
/// The store.
/// The scope names.
+ /// The used to propagate notifications that the operation should be cancelled.
///
- public static async Task> FindEnabledIdentityResourcesByScopeAsync(this IResourceStore store, IEnumerable scopeNames) => (await store.FindIdentityResourcesByScopeNameAsync(scopeNames)).Where(x => x.Enabled).ToArray();
+ public static async Task> FindEnabledIdentityResourcesByScopeAsync(this IResourceStore store, IEnumerable scopeNames, CT ct) => (await store.FindIdentityResourcesByScopeNameAsync(scopeNames, ct)).Where(x => x.Enabled).ToArray();
///
/// Finds the enabled API resources by name.
///
- public static async Task> FindEnabledApiResourcesByNameAsync(this IResourceStore store, IEnumerable resourceNames) => (await store.FindApiResourcesByNameAsync(resourceNames)).Where(x => x.Enabled).ToArray();
+ /// The store.
+ /// The resource names.
+ /// The used to propagate notifications that the operation should be cancelled.
+ public static async Task> FindEnabledApiResourcesByNameAsync(this IResourceStore store, IEnumerable resourceNames, CT ct) => (await store.FindApiResourcesByNameAsync(resourceNames, ct)).Where(x => x.Enabled).ToArray();
}
diff --git a/identity-server/src/IdentityServer/ResponseHandling/Default/DiscoveryResponseGenerator.cs b/identity-server/src/IdentityServer/ResponseHandling/Default/DiscoveryResponseGenerator.cs
index c43b1a7de..ef05e64cf 100644
--- a/identity-server/src/IdentityServer/ResponseHandling/Default/DiscoveryResponseGenerator.cs
+++ b/identity-server/src/IdentityServer/ResponseHandling/Default/DiscoveryResponseGenerator.cs
@@ -236,7 +236,7 @@ public class DiscoveryResponseGenerator : IDiscoveryResponseGenerator
Options.Discovery.ShowApiScopes ||
Options.Discovery.ShowClaims)
{
- var resources = await ResourceStore.GetAllEnabledResourcesAsync();
+ var resources = await ResourceStore.GetAllEnabledResourcesAsync(default);
var scopes = new List();
// scopes
diff --git a/identity-server/src/IdentityServer/ResponseHandling/Default/UserInfoResponseGenerator.cs b/identity-server/src/IdentityServer/ResponseHandling/Default/UserInfoResponseGenerator.cs
index d9f2002a4..ea1be9e23 100644
--- a/identity-server/src/IdentityServer/ResponseHandling/Default/UserInfoResponseGenerator.cs
+++ b/identity-server/src/IdentityServer/ResponseHandling/Default/UserInfoResponseGenerator.cs
@@ -121,7 +121,7 @@ public class UserInfoResponseGenerator : IUserInfoResponseGenerator
Logger.LogDebug("Scopes in access token: {scopes}", scopeString);
// if we ever parameterized identity scopes, then we would need to invoke the resource validator's parse API here
- var identityResources = await Resources.FindEnabledIdentityResourcesByScopeAsync(scopes);
+ var identityResources = await Resources.FindEnabledIdentityResourcesByScopeAsync(scopes, default);
var resources = new Resources(identityResources, Enumerable.Empty(), Enumerable.Empty());
var result = new ResourceValidationResult(resources);
diff --git a/identity-server/src/IdentityServer/Stores/Caching/CachingResourceStore.cs b/identity-server/src/IdentityServer/Stores/Caching/CachingResourceStore.cs
index bcfa37e7e..1dd697984 100644
--- a/identity-server/src/IdentityServer/Stores/Caching/CachingResourceStore.cs
+++ b/identity-server/src/IdentityServer/Stores/Caching/CachingResourceStore.cs
@@ -80,7 +80,7 @@ public class CachingResourceStore : IResourceStore
}
///
- public async Task GetAllResourcesAsync()
+ public async Task GetAllResourcesAsync(CT ct)
{
using var activity = Tracing.StoreActivitySource.StartActivity("CachingResourceStore.GetAllResources");
@@ -88,13 +88,13 @@ public class CachingResourceStore : IResourceStore
var all = await _allCache.GetOrAddAsync(key,
_options.Caching.ResourceStoreExpiration,
- async () => await _inner.GetAllResourcesAsync());
+ async () => await _inner.GetAllResourcesAsync(ct));
return all;
}
///
- public async Task> FindApiResourcesByScopeNameAsync(IEnumerable scopeNames)
+ public async Task> FindApiResourcesByScopeNameAsync(IEnumerable scopeNames, CT ct)
{
using var activity = Tracing.StoreActivitySource.StartActivity("CachingResourceStore.FindApiResourcesByScopeName");
activity?.SetTag(Tracing.Properties.ScopeNames, scopeNames.ToSpaceSeparatedString());
@@ -133,7 +133,7 @@ public class CachingResourceStore : IResourceStore
// do the cache/DB lookup
var resources = await _allCache.GetOrAddAsync(allCacheItemsKey, itemsDuration, async () =>
{
- var results = await _inner.FindApiResourcesByScopeNameAsync(uncachedScopes);
+ var results = await _inner.FindApiResourcesByScopeNameAsync(uncachedScopes, ct);
return new Resources(null, results, null);
});
@@ -160,51 +160,52 @@ public class CachingResourceStore : IResourceStore
}
// now that we have all the ApiResource names, just use our other API (that should find the cacted items)
- return await FindApiResourcesByNameAsync(apiResourceNames);
+ return await FindApiResourcesByNameAsync(apiResourceNames, ct);
}
///
- public async Task> FindApiResourcesByNameAsync(IEnumerable apiResourceNames)
+ public async Task> FindApiResourcesByNameAsync(IEnumerable apiResourceNames, CT ct)
{
using var activity = Tracing.StoreActivitySource.StartActivity("CachingResourceStore.FindApiResourcesByName");
activity?.SetTag(Tracing.Properties.ApiResourceNames, apiResourceNames.ToSpaceSeparatedString());
return await FindItemsAsync(apiResourceNames, _apiResourceCache,
- async names => new Resources(null, await _inner.FindApiResourcesByNameAsync(names), null),
- x => x.ApiResources, x => x.Name, "ApiResources-");
+ async (names, innerCt) => new Resources(null, await _inner.FindApiResourcesByNameAsync(names, innerCt), null),
+ x => x.ApiResources, x => x.Name, "ApiResources-", ct);
}
///
- public async Task> FindIdentityResourcesByScopeNameAsync(IEnumerable scopeNames)
+ public async Task> FindIdentityResourcesByScopeNameAsync(IEnumerable scopeNames, CT ct)
{
using var activity = Tracing.StoreActivitySource.StartActivity("CachingResourceStore.FindIdentityResourcesByScopeName");
activity?.SetTag(Tracing.Properties.ScopeNames, scopeNames.ToSpaceSeparatedString());
return await FindItemsAsync(scopeNames, _identityCache,
- async names => new Resources(await _inner.FindIdentityResourcesByScopeNameAsync(names), null, null),
- x => x.IdentityResources, x => x.Name, "IdentityResources-");
+ async (names, innerCt) => new Resources(await _inner.FindIdentityResourcesByScopeNameAsync(names, innerCt), null, null),
+ x => x.IdentityResources, x => x.Name, "IdentityResources-", ct);
}
///
- public async Task> FindApiScopesByNameAsync(IEnumerable scopeNames)
+ public async Task> FindApiScopesByNameAsync(IEnumerable scopeNames, CT ct)
{
using var activity = Tracing.StoreActivitySource.StartActivity("CachingResourceStore.FindApiScopesByName");
activity?.SetTag(Tracing.Properties.ScopeNames, scopeNames.ToSpaceSeparatedString());
return await FindItemsAsync(scopeNames, _apiScopeCache,
- async names => new Resources(null, null, await _inner.FindApiScopesByNameAsync(names)),
- x => x.ApiScopes, x => x.Name, "ApiScopes-");
+ async (names, innerCt) => new Resources(null, null, await _inner.FindApiScopesByNameAsync(names, innerCt)),
+ x => x.ApiScopes, x => x.Name, "ApiScopes-", ct);
}
private async Task> FindItemsAsync(
IEnumerable names,
ICache cache,
- Func, Task> getResourcesFunc,
+ Func, CT, Task> getResourcesFunc,
Func> getFromResourcesFunc,
Func getNameFunc,
- string allCachePrefix
+ string allCachePrefix,
+ CT ct
)
where TItem : class
{
@@ -237,7 +238,7 @@ public class CachingResourceStore : IResourceStore
// expire this entry much faster than the normal items
var itemsDuration = _options.Caching.ResourceStoreExpiration / 20;
// do the cache/DB lookup
- var resources = await _allCache.GetOrAddAsync(allCacheItemsKey, itemsDuration, async () => await getResourcesFunc(uncachedNames));
+ var resources = await _allCache.GetOrAddAsync(allCacheItemsKey, itemsDuration, async () => await getResourcesFunc(uncachedNames, ct));
// get the specific items from the Resources object
var uncachedItems = getFromResourcesFunc(resources);
diff --git a/identity-server/src/IdentityServer/Stores/Empty/EmptyResourceStore.cs b/identity-server/src/IdentityServer/Stores/Empty/EmptyResourceStore.cs
index 236c73572..834918475 100644
--- a/identity-server/src/IdentityServer/Stores/Empty/EmptyResourceStore.cs
+++ b/identity-server/src/IdentityServer/Stores/Empty/EmptyResourceStore.cs
@@ -8,13 +8,13 @@ namespace Duende.IdentityServer.Stores.Empty;
internal class EmptyResourceStore : IResourceStore
{
- public Task> FindApiResourcesByNameAsync(IEnumerable apiResourceNames) => Task.FromResult(Enumerable.Empty());
+ public Task> FindApiResourcesByNameAsync(IEnumerable apiResourceNames, CT ct) => Task.FromResult(Enumerable.Empty());
- public Task> FindApiResourcesByScopeNameAsync(IEnumerable scopeNames) => Task.FromResult(Enumerable.Empty());
+ public Task> FindApiResourcesByScopeNameAsync(IEnumerable scopeNames, CT ct) => Task.FromResult(Enumerable.Empty());
- public Task> FindApiScopesByNameAsync(IEnumerable scopeNames) => Task.FromResult(Enumerable.Empty());
+ public Task> FindApiScopesByNameAsync(IEnumerable scopeNames, CT ct) => Task.FromResult(Enumerable.Empty());
- public Task> FindIdentityResourcesByScopeNameAsync(IEnumerable scopeNames) => Task.FromResult(Enumerable.Empty());
+ public Task> FindIdentityResourcesByScopeNameAsync(IEnumerable scopeNames, CT ct) => Task.FromResult(Enumerable.Empty());
- public Task GetAllResourcesAsync() => Task.FromResult(new Resources() { OfflineAccess = true });
+ public Task GetAllResourcesAsync(CT ct) => Task.FromResult(new Resources() { OfflineAccess = true });
}
diff --git a/identity-server/src/IdentityServer/Stores/InMemory/InMemoryResourcesStore.cs b/identity-server/src/IdentityServer/Stores/InMemory/InMemoryResourcesStore.cs
index ec45ec19a..74070c49e 100644
--- a/identity-server/src/IdentityServer/Stores/InMemory/InMemoryResourcesStore.cs
+++ b/identity-server/src/IdentityServer/Stores/InMemory/InMemoryResourcesStore.cs
@@ -45,7 +45,7 @@ public class InMemoryResourcesStore : IResourceStore
}
///
- public Task GetAllResourcesAsync()
+ public Task GetAllResourcesAsync(CT ct)
{
using var activity = Tracing.StoreActivitySource.StartActivity("InMemoryResourceStore.GetAllResources");
@@ -54,7 +54,7 @@ public class InMemoryResourcesStore : IResourceStore
}
///
- public Task> FindApiResourcesByNameAsync(IEnumerable apiResourceNames)
+ public Task> FindApiResourcesByNameAsync(IEnumerable apiResourceNames, CT ct)
{
ArgumentNullException.ThrowIfNull(apiResourceNames);
using var activity = Tracing.StoreActivitySource.StartActivity("InMemoryResourceStore.FindApiResourcesByName");
@@ -67,7 +67,7 @@ public class InMemoryResourcesStore : IResourceStore
}
///
- public Task> FindIdentityResourcesByScopeNameAsync(IEnumerable scopeNames)
+ public Task> FindIdentityResourcesByScopeNameAsync(IEnumerable scopeNames, CT ct)
{
ArgumentNullException.ThrowIfNull(scopeNames);
using var activity = Tracing.StoreActivitySource.StartActivity("InMemoryResourceStore.FindIdentityResourcesByScopeName");
@@ -81,7 +81,7 @@ public class InMemoryResourcesStore : IResourceStore
}
///
- public Task> FindApiResourcesByScopeNameAsync(IEnumerable scopeNames)
+ public Task> FindApiResourcesByScopeNameAsync(IEnumerable scopeNames, CT ct)
{
ArgumentNullException.ThrowIfNull(scopeNames);
using var activity = Tracing.StoreActivitySource.StartActivity("InMemoryResourceStore.FindApiResourcesByScopeName");
@@ -95,7 +95,7 @@ public class InMemoryResourcesStore : IResourceStore
}
///
- public Task> FindApiScopesByNameAsync(IEnumerable scopeNames)
+ public Task> FindApiScopesByNameAsync(IEnumerable scopeNames, CT ct)
{
ArgumentNullException.ThrowIfNull(scopeNames);
using var activity = Tracing.StoreActivitySource.StartActivity("InMemoryResourceStore.FindApiScopesByName");
diff --git a/identity-server/src/IdentityServer/Validation/Default/ApiSecretValidator.cs b/identity-server/src/IdentityServer/Validation/Default/ApiSecretValidator.cs
index 459fd3b8f..0826b5334 100644
--- a/identity-server/src/IdentityServer/Validation/Default/ApiSecretValidator.cs
+++ b/identity-server/src/IdentityServer/Validation/Default/ApiSecretValidator.cs
@@ -64,7 +64,7 @@ public class ApiSecretValidator : IApiSecretValidator
}
// load API resource
- var apis = await _resources.FindApiResourcesByNameAsync(new[] { parsedSecret.Id });
+ var apis = await _resources.FindApiResourcesByNameAsync(new[] { parsedSecret.Id }, context.RequestAborted);
if (apis == null || !apis.Any())
{
await RaiseFailureEventAsync(parsedSecret.Id, "Unknown API resource");
diff --git a/identity-server/src/IdentityServer/Validation/Default/DefaultResourceValidator.cs b/identity-server/src/IdentityServer/Validation/Default/DefaultResourceValidator.cs
index ccd146123..0af93c407 100644
--- a/identity-server/src/IdentityServer/Validation/Default/DefaultResourceValidator.cs
+++ b/identity-server/src/IdentityServer/Validation/Default/DefaultResourceValidator.cs
@@ -55,7 +55,7 @@ public class DefaultResourceValidator : IResourceValidator
var scopeNames = parsedScopesResult.ParsedScopes.Select(x => x.ParsedName).Distinct().ToArray();
// todo: this API might want to pass resource indicators to better filter
- var scopeResourcesFromStore = await _store.FindEnabledResourcesByScopeAsync(scopeNames);
+ var scopeResourcesFromStore = await _store.FindEnabledResourcesByScopeAsync(scopeNames, default);
if (request.ResourceIndicators?.Any() == true)
{
diff --git a/identity-server/src/IdentityServer/Validation/Default/TokenRequestValidator.cs b/identity-server/src/IdentityServer/Validation/Default/TokenRequestValidator.cs
index 4d721af09..903a822c4 100644
--- a/identity-server/src/IdentityServer/Validation/Default/TokenRequestValidator.cs
+++ b/identity-server/src/IdentityServer/Validation/Default/TokenRequestValidator.cs
@@ -1106,12 +1106,12 @@ internal class TokenRequestValidator : ITokenRequestValidator
var clientAllowedScopes = new List();
if (!ignoreImplicitIdentityScopes)
{
- var resources = await _resourceStore.FindResourcesByScopeAsync(_validatedRequest.Client.AllowedScopes);
+ var resources = await _resourceStore.FindResourcesByScopeAsync(_validatedRequest.Client.AllowedScopes, _ct);
clientAllowedScopes.AddRange(resources.ToScopeNames().Where(x => _validatedRequest.Client.AllowedScopes.Contains(x)));
}
else
{
- var apiScopes = await _resourceStore.FindApiScopesByNameAsync(_validatedRequest.Client.AllowedScopes);
+ var apiScopes = await _resourceStore.FindApiScopesByNameAsync(_validatedRequest.Client.AllowedScopes, _ct);
clientAllowedScopes.AddRange(apiScopes.Select(x => x.Name));
}
diff --git a/identity-server/src/Storage/Stores/IResourceStore.cs b/identity-server/src/Storage/Stores/IResourceStore.cs
index 5ad8d2b95..0ffa36e00 100644
--- a/identity-server/src/Storage/Stores/IResourceStore.cs
+++ b/identity-server/src/Storage/Stores/IResourceStore.cs
@@ -16,25 +16,34 @@ public interface IResourceStore
///
/// Gets identity resources by scope name.
///
- Task> FindIdentityResourcesByScopeNameAsync(IEnumerable scopeNames);
+ /// The scope names.
+ /// The used to propagate notifications that the operation should be cancelled.
+ Task> FindIdentityResourcesByScopeNameAsync(IEnumerable scopeNames, CT ct);
///
/// Gets API scopes by scope name.
///
- Task> FindApiScopesByNameAsync(IEnumerable scopeNames);
+ /// The scope names.
+ /// The used to propagate notifications that the operation should be cancelled.
+ Task> FindApiScopesByNameAsync(IEnumerable scopeNames, CT ct);
///
/// Gets API resources by scope name.
///
- Task> FindApiResourcesByScopeNameAsync(IEnumerable scopeNames);
+ /// The scope names.
+ /// The used to propagate notifications that the operation should be cancelled.
+ Task> FindApiResourcesByScopeNameAsync(IEnumerable scopeNames, CT ct);
///
/// Gets API resources by API resource name.
///
- Task> FindApiResourcesByNameAsync(IEnumerable apiResourceNames);
+ /// The API resource names.
+ /// The used to propagate notifications that the operation should be cancelled.
+ Task> FindApiResourcesByNameAsync(IEnumerable apiResourceNames, CT ct);
///
/// Gets all resources.
///
- Task GetAllResourcesAsync();
+ /// The used to propagate notifications that the operation should be cancelled.
+ Task GetAllResourcesAsync(CT ct);
}
diff --git a/identity-server/test/IdentityServer.IntegrationTests/EntityFramework/Storage/Stores/ResourceStoreTests.cs b/identity-server/test/IdentityServer.IntegrationTests/EntityFramework/Storage/Stores/ResourceStoreTests.cs
index f41e180df..4ab8b0566 100644
--- a/identity-server/test/IdentityServer.IntegrationTests/EntityFramework/Storage/Stores/ResourceStoreTests.cs
+++ b/identity-server/test/IdentityServer.IntegrationTests/EntityFramework/Storage/Stores/ResourceStoreTests.cs
@@ -16,6 +16,8 @@ namespace Duende.IdentityServer.IntegrationTests.EntityFramework.Storage.Stores;
public class ScopeStoreTests : IntegrationTest
{
+ private readonly CT _ct = TestContext.Current.CancellationToken;
+
public ScopeStoreTests(DatabaseProviderFixture fixture) : base(fixture)
{
foreach (var options in TestDatabaseProviders)
@@ -76,7 +78,7 @@ public class ScopeStoreTests : IntegrationTest(), new NoneCancellationTokenProvider());
- foundResource = (await store.FindApiResourcesByNameAsync(new[] { resource.Name })).SingleOrDefault();
+ foundResource = (await store.FindApiResourcesByNameAsync(new[] { resource.Name }, _ct)).SingleOrDefault();
}
foundResource.ShouldNotBeNull();
@@ -105,7 +107,7 @@ public class ScopeStoreTests : IntegrationTest(), new NoneCancellationTokenProvider());
- foundResource = (await store.FindApiResourcesByNameAsync(new[] { resource.Name })).SingleOrDefault();
+ foundResource = (await store.FindApiResourcesByNameAsync(new[] { resource.Name }, _ct)).SingleOrDefault();
}
foundResource.ShouldNotBeNull();
@@ -140,7 +142,7 @@ public class ScopeStoreTests : IntegrationTest
{
testApiScope.Name
- });
+ }, _ct);
}
resources.ShouldNotBeNull();
@@ -171,7 +173,7 @@ public class ScopeStoreTests : IntegrationTest(), new NoneCancellationTokenProvider());
- resources = await store.FindApiResourcesByScopeNameAsync(new[] { testApiScope.Name });
+ resources = await store.FindApiResourcesByScopeNameAsync(new[] { testApiScope.Name }, _ct);
}
resources.ShouldNotBeNull();
@@ -197,7 +199,7 @@ public class ScopeStoreTests : IntegrationTest
{
resource.Name
- })).ToList();
+ }, _ct)).ToList();
}
resources.ShouldNotBeNull();
@@ -228,7 +230,7 @@ public class ScopeStoreTests : IntegrationTest
{
resource.Name
- })).ToList();
+ }, _ct)).ToList();
}
resources.ShouldNotBeNull();
@@ -254,7 +256,7 @@ public class ScopeStoreTests : IntegrationTest
{
resource.Name
- })).ToList();
+ }, _ct)).ToList();
}
resources.ShouldNotBeNull();
@@ -285,7 +287,7 @@ public class ScopeStoreTests : IntegrationTest
{
resource.Name
- })).ToList();
+ }, _ct)).ToList();
}
resources.ShouldNotBeNull();
@@ -329,7 +331,7 @@ public class ScopeStoreTests : IntegrationTest(), new NoneCancellationTokenProvider());
- resources = await store.GetAllResourcesAsync();
+ resources = await store.GetAllResourcesAsync(_ct);
}
resources.ShouldNotBeNull();
diff --git a/identity-server/test/IdentityServer.UnitTests/Caches/ResourceStoreCacheTests.cs b/identity-server/test/IdentityServer.UnitTests/Caches/ResourceStoreCacheTests.cs
index a8e96b4f7..7fc077318 100644
--- a/identity-server/test/IdentityServer.UnitTests/Caches/ResourceStoreCacheTests.cs
+++ b/identity-server/test/IdentityServer.UnitTests/Caches/ResourceStoreCacheTests.cs
@@ -13,6 +13,8 @@ namespace IdentityServer.UnitTests.Caches;
public class ResourceStoreCacheTests
{
+ private readonly CT _ct = TestContext.Current.CancellationToken;
+
private List _clients { get; set; } = new List();
private List _identityResources { get; set; } = new List();
private List _resources { get; set; } = new List();
@@ -55,7 +57,7 @@ public class ResourceStoreCacheTests
var store = _provider.GetRequiredService();
cache.CacheItems.Count.ShouldBe(0);
- var results = await store.FindIdentityResourcesByScopeNameAsync(new[] { "profile" });
+ var results = await store.FindIdentityResourcesByScopeNameAsync(new[] { "profile" }, _ct);
cache.CacheItems.Count.ShouldBe(1);
cache.CacheItems.First().Value.Value.Name.ShouldBe("profile");
@@ -69,7 +71,7 @@ public class ResourceStoreCacheTests
var store = _provider.GetRequiredService();
cache.CacheItems.Count.ShouldBe(0);
- var results = await store.FindApiResourcesByScopeNameAsync(new[] { "scope1" });
+ var results = await store.FindApiResourcesByScopeNameAsync(new[] { "scope1" }, _ct);
cache.CacheItems.Count.ShouldBe(1);
cache.CacheItems.First().Value.Value.Names.Single().ShouldBe("urn:api1");
@@ -82,7 +84,7 @@ public class ResourceStoreCacheTests
var store = _provider.GetRequiredService();
cache.CacheItems.Count.ShouldBe(0);
- var results = await store.FindApiScopesByNameAsync(new[] { "scope1" });
+ var results = await store.FindApiScopesByNameAsync(new[] { "scope1" }, _ct);
cache.CacheItems.Count.ShouldBe(1);
cache.CacheItems.First().Value.Value.Name.ShouldBe("scope1");
diff --git a/identity-server/test/IdentityServer.UnitTests/Extensions/IResourceStoreExtensionsTests.cs b/identity-server/test/IdentityServer.UnitTests/Extensions/IResourceStoreExtensionsTests.cs
index 0c183adf4..11671b251 100644
--- a/identity-server/test/IdentityServer.UnitTests/Extensions/IResourceStoreExtensionsTests.cs
+++ b/identity-server/test/IdentityServer.UnitTests/Extensions/IResourceStoreExtensionsTests.cs
@@ -9,6 +9,8 @@ namespace UnitTests.Extensions;
public class IResourceStoreExtensionsTests
{
+ private readonly CT _ct = TestContext.Current.CancellationToken;
+
[Fact]
public async Task GetAllEnabledResourcesAsync_on_duplicate_identity_scopes_should_fail()
{
@@ -19,7 +21,7 @@ public class IResourceStoreExtensionsTests
new IdentityResource { Name = "A" } }
};
- Func a = () => store.GetAllEnabledResourcesAsync();
+ Func a = () => store.GetAllEnabledResourcesAsync(_ct);
var exception = await a.ShouldThrowAsync();
exception.Message.ShouldMatch("Duplicate identity scopes*");
}
@@ -34,7 +36,7 @@ public class IResourceStoreExtensionsTests
new IdentityResource { Name = "B" } }
};
- await store.GetAllEnabledResourcesAsync();
+ await store.GetAllEnabledResourcesAsync(_ct);
}
[Fact]
@@ -45,7 +47,7 @@ public class IResourceStoreExtensionsTests
ApiResources = { new ApiResource { Name = "a" }, new ApiResource { Name = "a" } }
};
- Func a = () => store.GetAllEnabledResourcesAsync();
+ Func a = () => store.GetAllEnabledResourcesAsync(_ct);
var exception = await a.ShouldThrowAsync();
exception.Message.ShouldMatch("Duplicate api resources*");
}
@@ -58,7 +60,7 @@ public class IResourceStoreExtensionsTests
ApiResources = { new ApiResource("A"), new ApiResource("B") }
};
- await store.GetAllEnabledResourcesAsync();
+ await store.GetAllEnabledResourcesAsync(_ct);
}
[Fact]
@@ -71,7 +73,7 @@ public class IResourceStoreExtensionsTests
new IdentityResource { Name = "A" } }
};
- Func a = () => store.FindResourcesByScopeAsync(new string[] { "A" });
+ Func a = () => store.FindResourcesByScopeAsync(new string[] { "A" }, _ct);
var exception = await a.ShouldThrowAsync();
exception.Message.ShouldMatch("Duplicate identity scopes*");
}
@@ -86,7 +88,7 @@ public class IResourceStoreExtensionsTests
new IdentityResource { Name = "B" } }
};
- await store.FindResourcesByScopeAsync(new string[] { "A" });
+ await store.FindResourcesByScopeAsync(new string[] { "A" }, _ct);
}
[Fact]
@@ -103,7 +105,7 @@ public class IResourceStoreExtensionsTests
}
};
- var result = await store.FindResourcesByScopeAsync(new string[] { "a" });
+ var result = await store.FindResourcesByScopeAsync(new string[] { "a" }, _ct);
result.ApiResources.Count.ShouldBe(2);
result.ApiScopes.Count.ShouldBe(1);
result.ApiResources.Select(x => x.Name).ShouldBe(["api1", "api2"]);
@@ -118,7 +120,7 @@ public class IResourceStoreExtensionsTests
ApiResources = { new ApiResource("A"), new ApiResource("B") }
};
- await store.FindResourcesByScopeAsync(new string[] { "A" });
+ await store.FindResourcesByScopeAsync(new string[] { "A" }, _ct);
}
[Fact]
@@ -136,7 +138,7 @@ public class IResourceStoreExtensionsTests
}
};
- var result = await store.FindResourcesByScopeAsync(new string[] { "a" });
+ var result = await store.FindResourcesByScopeAsync(new string[] { "a" }, _ct);
result.ApiResources.Count.ShouldBe(1);
}
@@ -146,7 +148,7 @@ public class IResourceStoreExtensionsTests
public List ApiResources { get; set; } = new List();
public List ApiScopes { get; set; } = new List();
- public Task> FindApiResourcesByNameAsync(IEnumerable names)
+ public Task> FindApiResourcesByNameAsync(IEnumerable names, CT ct)
{
var apis = from a in ApiResources
where names.Contains(a.Name)
@@ -154,7 +156,7 @@ public class IResourceStoreExtensionsTests
return Task.FromResult(apis);
}
- public Task> FindApiResourcesByScopeNameAsync(IEnumerable names)
+ public Task> FindApiResourcesByScopeNameAsync(IEnumerable names, CT ct)
{
ArgumentNullException.ThrowIfNull(names);
@@ -165,7 +167,7 @@ public class IResourceStoreExtensionsTests
return Task.FromResult(api);
}
- public Task> FindIdentityResourcesByScopeNameAsync(IEnumerable names)
+ public Task> FindIdentityResourcesByScopeNameAsync(IEnumerable names, CT ct)
{
ArgumentNullException.ThrowIfNull(names);
@@ -176,7 +178,7 @@ public class IResourceStoreExtensionsTests
return Task.FromResult(identity);
}
- public Task> FindApiScopesByNameAsync(IEnumerable scopeNames)
+ public Task> FindApiScopesByNameAsync(IEnumerable scopeNames, CT ct)
{
var q = from x in ApiScopes
where scopeNames.Contains(x.Name)
@@ -184,7 +186,7 @@ public class IResourceStoreExtensionsTests
return Task.FromResult(q);
}
- public Task GetAllResourcesAsync()
+ public Task GetAllResourcesAsync(CT ct)
{
var result = new Resources(IdentityResources, ApiResources, ApiScopes);
return Task.FromResult(result);
diff --git a/identity-server/test/IdentityServer.UnitTests/Extensions/IdentityServerBuilderExtensionsCacheStoreTests.cs b/identity-server/test/IdentityServer.UnitTests/Extensions/IdentityServerBuilderExtensionsCacheStoreTests.cs
index 9a7c45117..1b873cfe0 100644
--- a/identity-server/test/IdentityServer.UnitTests/Extensions/IdentityServerBuilderExtensionsCacheStoreTests.cs
+++ b/identity-server/test/IdentityServer.UnitTests/Extensions/IdentityServerBuilderExtensionsCacheStoreTests.cs
@@ -22,15 +22,15 @@ public class IdentityServerBuilderExtensionsCacheStoreTests
private class CustomResourceStore : IResourceStore
{
- public Task> FindIdentityResourcesByScopeNameAsync(IEnumerable scopeNames) => throw new System.NotImplementedException();
+ public Task> FindIdentityResourcesByScopeNameAsync(IEnumerable scopeNames, CT ct) => throw new System.NotImplementedException();
- public Task> FindApiResourcesByScopeNameAsync(IEnumerable scopeNames) => throw new System.NotImplementedException();
+ public Task> FindApiResourcesByScopeNameAsync(IEnumerable scopeNames, CT ct) => throw new System.NotImplementedException();
- public Task> FindApiResourcesByNameAsync(IEnumerable names) => throw new System.NotImplementedException();
+ public Task> FindApiResourcesByNameAsync(IEnumerable names, CT ct) => throw new System.NotImplementedException();
- public Task GetAllResourcesAsync() => throw new System.NotImplementedException();
+ public Task GetAllResourcesAsync(CT ct) => throw new System.NotImplementedException();
- public Task> FindApiScopesByNameAsync(IEnumerable scopeNames) => throw new System.NotImplementedException();
+ public Task> FindApiScopesByNameAsync(IEnumerable scopeNames, CT ct) => throw new System.NotImplementedException();
}
[Fact]
diff --git a/identity-server/test/IdentityServer.UnitTests/Stores/Default/CachingResourceStoreTests.cs b/identity-server/test/IdentityServer.UnitTests/Stores/Default/CachingResourceStoreTests.cs
index c71f44d43..6916ab087 100644
--- a/identity-server/test/IdentityServer.UnitTests/Stores/Default/CachingResourceStoreTests.cs
+++ b/identity-server/test/IdentityServer.UnitTests/Stores/Default/CachingResourceStoreTests.cs
@@ -11,6 +11,8 @@ namespace UnitTests.Stores.Default;
public class CachingResourceStoreTests
{
+ private readonly CT _ct = TestContext.Current.CancellationToken;
+
private List _identityResources = new List();
private List _apiResources = new List();
private List _apiScopes = new List();
@@ -48,7 +50,7 @@ public class CachingResourceStoreTests
_scopeCache.Items.Count.ShouldBe(0);
- var items = await _subject.FindApiScopesByNameAsync(new[] { "scope3", "scope1", "scope2", "invalid" });
+ var items = await _subject.FindApiScopesByNameAsync(new[] { "scope3", "scope1", "scope2", "invalid" }, _ct);
items.Count().ShouldBe(3);
_scopeCache.Items.Count.ShouldBe(3);
@@ -64,23 +66,23 @@ public class CachingResourceStoreTests
_scopeCache.Items.Count.ShouldBe(0);
- var items = await _subject.FindApiScopesByNameAsync(new[] { "scope1" });
+ var items = await _subject.FindApiScopesByNameAsync(new[] { "scope1" }, _ct);
items.Count().ShouldBe(1);
_scopeCache.Items.Count.ShouldBe(1);
_apiScopes.Remove(_apiScopes.Single(x => x.Name == "scope1"));
- items = await _subject.FindApiScopesByNameAsync(new[] { "scope1", "scope2" });
+ items = await _subject.FindApiScopesByNameAsync(new[] { "scope1", "scope2" }, _ct);
items.Count().ShouldBe(2);
_scopeCache.Items.Count.ShouldBe(2);
_apiScopes.Remove(_apiScopes.Single(x => x.Name == "scope2"));
- items = await _subject.FindApiScopesByNameAsync(new[] { "scope3", "scope2", "scope4" });
+ items = await _subject.FindApiScopesByNameAsync(new[] { "scope3", "scope2", "scope4" }, _ct);
items.Count().ShouldBe(3);
_scopeCache.Items.Count.ShouldBe(4);
// this shows we will find it in the cache, even if removed from the DB
_apiScopes.Remove(_apiScopes.Single(x => x.Name == "scope3"));
- items = await _subject.FindApiScopesByNameAsync(new[] { "scope3", "scope1", "scope2" });
+ items = await _subject.FindApiScopesByNameAsync(new[] { "scope3", "scope1", "scope2" }, _ct);
items.Count().ShouldBe(3);
_scopeCache.Items.Count.ShouldBe(4);
}
@@ -98,7 +100,7 @@ public class CachingResourceStoreTests
{
_apiCache.Items.Count.ShouldBe(0);
_apiResourceNamesCache.Items.Count.ShouldBe(0);
- var items = await _subject.FindApiResourcesByScopeNameAsync(new[] { "invalid" });
+ var items = await _subject.FindApiResourcesByScopeNameAsync(new[] { "invalid" }, _ct);
items.Count().ShouldBe(0);
_apiCache.Items.Count.ShouldBe(0);
_apiResourceNamesCache.Items.Count.ShouldBe(1);
@@ -111,7 +113,7 @@ public class CachingResourceStoreTests
_apiCache.Items.Count.ShouldBe(0);
_apiResourceNamesCache.Items.Count.ShouldBe(0);
- var items = await _subject.FindApiResourcesByScopeNameAsync(new[] { "foo1" });
+ var items = await _subject.FindApiResourcesByScopeNameAsync(new[] { "foo1" }, _ct);
items.Count().ShouldBe(1);
items.Select(x => x.Name).ShouldBe(new[] { "foo" });
_apiCache.Items.Count.ShouldBe(1);
@@ -119,7 +121,7 @@ public class CachingResourceStoreTests
}
{
- var items = await _subject.FindApiResourcesByScopeNameAsync(new[] { "foo2" });
+ var items = await _subject.FindApiResourcesByScopeNameAsync(new[] { "foo2" }, _ct);
items.Count().ShouldBe(1);
items.Select(x => x.Name).ShouldBe(["foo"]);
_apiCache.Items.Count.ShouldBe(1);
@@ -127,7 +129,7 @@ public class CachingResourceStoreTests
}
{
- var items = await _subject.FindApiResourcesByScopeNameAsync(new[] { "foo1", "bar1" });
+ var items = await _subject.FindApiResourcesByScopeNameAsync(new[] { "foo1", "bar1" }, _ct);
items.Count().ShouldBe(2);
items.Select(x => x.Name).ShouldBe(["foo", "bar"]);
_apiCache.Items.Count.ShouldBe(2);
@@ -135,7 +137,7 @@ public class CachingResourceStoreTests
}
{
- var items = await _subject.FindApiResourcesByScopeNameAsync(new[] { "foo2", "foo1", "bar2", "bar1" });
+ var items = await _subject.FindApiResourcesByScopeNameAsync(new[] { "foo2", "foo1", "bar2", "bar1" }, _ct);
items.Count().ShouldBe(2);
items.Select(x => x.Name).ShouldBe(["foo", "bar"]);
_apiCache.Items.Count.ShouldBe(2);
@@ -147,7 +149,7 @@ public class CachingResourceStoreTests
_apiResourceNamesCache.Items.Clear();
_resourceCache.Items.Clear();
- var items = await _subject.FindApiResourcesByScopeNameAsync(new[] { "foo2", "foo1", "bar2", "bar1" });
+ var items = await _subject.FindApiResourcesByScopeNameAsync(new[] { "foo2", "foo1", "bar2", "bar1" }, _ct);
items.Count().ShouldBe(2);
items.Select(x => x.Name).ShouldBe(["foo", "bar"]);
_apiCache.Items.Count.ShouldBe(2);
@@ -160,7 +162,7 @@ public class CachingResourceStoreTests
_apiScopes.Clear();
_identityResources.Clear();
- var items = await _subject.FindApiResourcesByScopeNameAsync(new[] { "foo2", "foo1", "bar2", "bar1" });
+ var items = await _subject.FindApiResourcesByScopeNameAsync(new[] { "foo2", "foo1", "bar2", "bar1" }, _ct);
items.Count().ShouldBe(2);
items.Select(x => x.Name).ShouldBe(["foo", "bar"]);
_apiCache.Items.Count.ShouldBe(2);
@@ -179,12 +181,12 @@ public class CachingResourceStoreTests
_apiScopes.Add(new ApiScope("bar1"));
{
- var items = await _subject.FindApiResourcesByScopeNameAsync(new[] { "foo", "foo1", "bar", "bar1" });
+ var items = await _subject.FindApiResourcesByScopeNameAsync(new[] { "foo", "foo1", "bar", "bar1" }, _ct);
items.Count().ShouldBe(2);
items.Select(x => x.Name).ShouldBe(["foo", "bar"], true);
}
{
- var items = await _subject.FindApiResourcesByScopeNameAsync(new[] { "foo", "foo1", "bar", "bar1" });
+ var items = await _subject.FindApiResourcesByScopeNameAsync(new[] { "foo", "foo1", "bar", "bar1" }, _ct);
items.Count().ShouldBe(2);
items.Select(x => x.Name).ShouldBe(["foo", "bar"]);
}