From 058c1157134fc1913481958516fc3d2806301008 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Chalet?= Date: Sun, 23 Aug 2026 15:11:31 +0200 Subject: [PATCH] Convert all the scoped event handlers to singleton services --- .../OpenIddictClientHandlers.Protection.cs | 101 ++-- .../OpenIddictClientHandlers.cs | 17 +- ...OpenIddictServerHandlers.Authentication.cs | 422 +++++------------ .../OpenIddictServerHandlers.Device.cs | 79 +-- .../OpenIddictServerHandlers.Exchange.cs | 152 ++---- .../OpenIddictServerHandlers.Introspection.cs | 33 +- .../OpenIddictServerHandlers.Protection.cs | 168 +++---- .../OpenIddictServerHandlers.Revocation.cs | 33 +- .../OpenIddictServerHandlers.Session.cs | 130 ++--- .../OpenIddictServerHandlers.cs | 448 +++++------------- ...OpenIddictValidationHandlers.Protection.cs | 83 ++-- 11 files changed, 542 insertions(+), 1124 deletions(-) diff --git a/src/OpenIddict.Client/OpenIddictClientHandlers.Protection.cs b/src/OpenIddict.Client/OpenIddictClientHandlers.Protection.cs index 66e3951a..525491d9 100644 --- a/src/OpenIddict.Client/OpenIddictClientHandlers.Protection.cs +++ b/src/OpenIddict.Client/OpenIddictClientHandlers.Protection.cs @@ -10,6 +10,7 @@ using System.Diagnostics; using System.Globalization; using System.Security.Claims; using System.Security.Cryptography; +using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Microsoft.IdentityModel.JsonWebTokens; using Microsoft.IdentityModel.Tokens; @@ -238,20 +239,13 @@ public static partial class OpenIddictClientHandlers /// public sealed class ValidateReferenceTokenIdentifier : IOpenIddictClientHandler { - private readonly IOpenIddictTokenManager _tokenManager; - - public ValidateReferenceTokenIdentifier() => throw new InvalidOperationException(SR.GetResourceString(SR.ID0318)); - - public ValidateReferenceTokenIdentifier(IOpenIddictTokenManager tokenManager) - => _tokenManager = tokenManager ?? throw new ArgumentNullException(nameof(tokenManager)); - /// /// Gets the default descriptor definition assigned to this handler. /// public static OpenIddictClientHandlerDescriptor Descriptor { get; } = OpenIddictClientHandlerDescriptor.CreateBuilder() .AddFilter() - .UseScopedHandler() + .UseSingletonHandler() .SetOrder(RemoveDisallowedCharacters.Descriptor.Order + 1_000) .SetType(OpenIddictClientHandlerType.BuiltIn) .Build(); @@ -273,8 +267,11 @@ public static partial class OpenIddictClientHandlers return; } + var manager = context.ServiceProvider.GetService() + ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0318)); + // If the reference token cannot be found, don't return an error to allow another handler to validate it. - var token = await _tokenManager.FindByReferenceIdAsync(context.Token, context.CancellationToken); + var token = await manager.FindByReferenceIdAsync(context.Token, context.CancellationToken); if (token is null) { return; @@ -284,8 +281,8 @@ public static partial class OpenIddictClientHandlers if (!(context.ValidTokenTypes.Count switch { 0 => true, // If no specific token type is expected, accept all token types at this stage. - 1 => await _tokenManager.HasTypeAsync(token, context.ValidTokenTypes.ElementAt(0), context.CancellationToken), - _ => await _tokenManager.HasTypeAsync(token, [.. context.ValidTokenTypes], context.CancellationToken) + 1 => await manager.HasTypeAsync(token, context.ValidTokenTypes.ElementAt(0), context.CancellationToken), + _ => await manager.HasTypeAsync(token, [.. context.ValidTokenTypes], context.CancellationToken) })) { context.Reject( @@ -296,7 +293,7 @@ public static partial class OpenIddictClientHandlers return; } - var payload = await _tokenManager.GetPayloadAsync(token, context.CancellationToken); + var payload = await manager.GetPayloadAsync(token, context.CancellationToken); if (string.IsNullOrEmpty(payload)) { throw new InvalidOperationException(SR.GetResourceString(SR.ID0026)); @@ -307,7 +304,7 @@ public static partial class OpenIddictClientHandlers // used to restore the properties associated with the token. context.IsReferenceToken = true; context.Token = payload; - context.TokenId = await _tokenManager.GetIdAsync(token, context.CancellationToken); + context.TokenId = await manager.GetIdAsync(token, context.CancellationToken); } } @@ -530,20 +527,13 @@ public static partial class OpenIddictClientHandlers /// public sealed class RestoreTokenEntryProperties : IOpenIddictClientHandler { - private readonly IOpenIddictTokenManager _tokenManager; - - public RestoreTokenEntryProperties() => throw new InvalidOperationException(SR.GetResourceString(SR.ID0318)); - - public RestoreTokenEntryProperties(IOpenIddictTokenManager tokenManager) - => _tokenManager = tokenManager ?? throw new ArgumentNullException(nameof(tokenManager)); - /// /// Gets the default descriptor definition assigned to this handler. /// public static OpenIddictClientHandlerDescriptor Descriptor { get; } = OpenIddictClientHandlerDescriptor.CreateBuilder() .AddFilter() - .UseScopedHandler() + .UseSingletonHandler() .SetOrder(MapInternalClaims.Descriptor.Order + 1_000) .SetType(OpenIddictClientHandlerType.BuiltIn) .Build(); @@ -574,8 +564,11 @@ public static partial class OpenIddictClientHandlers return; } + var manager = context.ServiceProvider.GetService() + ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0318)); + // If the token entry cannot be found, return a generic error. - var token = await _tokenManager.FindByIdAsync(identifier, context.CancellationToken); + var token = await manager.FindByIdAsync(identifier, context.CancellationToken); if (token is null) { context.Reject( @@ -589,9 +582,9 @@ public static partial class OpenIddictClientHandlers // If the token was not validated as a reference token but has a reference identifier attached, this // may indicate that the payload stored in the database has leaked and is being used as a regular, // non-reference token. To prevent this, reject the token if the reference identifier is not null. - if (!context.IsReferenceToken && !string.IsNullOrEmpty(await _tokenManager.GetReferenceIdAsync(token, context.CancellationToken))) + if (!context.IsReferenceToken && !string.IsNullOrEmpty(await manager.GetReferenceIdAsync(token, context.CancellationToken))) { - context.Logger.LogWarning(6292, SR.GetResourceString(SR.ID6292), await _tokenManager.GetIdAsync(token, context.CancellationToken)); + context.Logger.LogWarning(6292, SR.GetResourceString(SR.ID6292), await manager.GetIdAsync(token, context.CancellationToken)); context.Reject( error: Errors.InvalidToken, @@ -603,10 +596,10 @@ public static partial class OpenIddictClientHandlers // Restore the creation/expiration dates/identifiers from the token entry metadata. context.Principal - .SetCreationDate(await _tokenManager.GetCreationDateAsync(token, context.CancellationToken)) - .SetExpirationDate(await _tokenManager.GetExpirationDateAsync(token, context.CancellationToken)) - .SetTokenId(context.TokenId = await _tokenManager.GetIdAsync(token, context.CancellationToken)) - .SetTokenType(await _tokenManager.GetTypeAsync(token, context.CancellationToken)); + .SetCreationDate(await manager.GetCreationDateAsync(token, context.CancellationToken)) + .SetExpirationDate(await manager.GetExpirationDateAsync(token, context.CancellationToken)) + .SetTokenId(context.TokenId = await manager.GetIdAsync(token, context.CancellationToken)) + .SetTokenType(await manager.GetTypeAsync(token, context.CancellationToken)); } } @@ -824,13 +817,6 @@ public static partial class OpenIddictClientHandlers /// public sealed class ValidateTokenEntry : IOpenIddictClientHandler { - private readonly IOpenIddictTokenManager _tokenManager; - - public ValidateTokenEntry() => throw new InvalidOperationException(SR.GetResourceString(SR.ID0139)); - - public ValidateTokenEntry(IOpenIddictTokenManager tokenManager) - => _tokenManager = tokenManager ?? throw new ArgumentNullException(nameof(tokenManager)); - /// /// Gets the default descriptor definition assigned to this handler. /// @@ -838,7 +824,7 @@ public static partial class OpenIddictClientHandlers = OpenIddictClientHandlerDescriptor.CreateBuilder() .AddFilter() .AddFilter() - .UseScopedHandler() + .UseSingletonHandler() .SetOrder(ValidateAudiences.Descriptor.Order + 1_000) .SetType(OpenIddictClientHandlerType.BuiltIn) .Build(); @@ -851,10 +837,13 @@ public static partial class OpenIddictClientHandlers Debug.Assert(context.Principal is { Identity: ClaimsIdentity }, SR.GetResourceString(SR.ID4006)); Debug.Assert(!string.IsNullOrEmpty(context.TokenId), SR.GetResourceString(SR.ID4017)); - var token = await _tokenManager.FindByIdAsync(context.TokenId, context.CancellationToken) + var manager = context.ServiceProvider.GetService() + ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0318)); + + var token = await manager.FindByIdAsync(context.TokenId, context.CancellationToken) ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0021)); - if (await _tokenManager.HasStatusAsync(token, Statuses.Redeemed, context.CancellationToken)) + if (await manager.HasStatusAsync(token, Statuses.Redeemed, context.CancellationToken)) { context.Logger.LogInformation(6002, SR.GetResourceString(SR.ID6002), context.TokenId); @@ -876,7 +865,7 @@ public static partial class OpenIddictClientHandlers return; } - if (!await _tokenManager.HasStatusAsync(token, Statuses.Valid, context.CancellationToken)) + if (!await manager.HasStatusAsync(token, Statuses.Valid, context.CancellationToken)) { context.Logger.LogInformation(6005, SR.GetResourceString(SR.ID6005), context.TokenId); @@ -943,13 +932,6 @@ public static partial class OpenIddictClientHandlers /// public sealed class CreateTokenEntry : IOpenIddictClientHandler { - private readonly IOpenIddictTokenManager _tokenManager; - - public CreateTokenEntry() => throw new InvalidOperationException(SR.GetResourceString(SR.ID0318)); - - public CreateTokenEntry(IOpenIddictTokenManager tokenManager) - => _tokenManager = tokenManager ?? throw new ArgumentNullException(nameof(tokenManager)); - /// /// Gets the default descriptor definition assigned to this handler. /// @@ -957,7 +939,7 @@ public static partial class OpenIddictClientHandlers = OpenIddictClientHandlerDescriptor.CreateBuilder() .AddFilter() .AddFilter() - .UseScopedHandler() + .UseSingletonHandler() .SetOrder(AttachSecurityCredentials.Descriptor.Order + 1_000) .SetType(OpenIddictClientHandlerType.BuiltIn) .Build(); @@ -980,10 +962,13 @@ public static partial class OpenIddictClientHandlers // Tokens produced by the client stack cannot have an application attached. - var token = await _tokenManager.CreateAsync(descriptor, context.CancellationToken) + var manager = context.ServiceProvider.GetService() + ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0318)); + + var token = await manager.CreateAsync(descriptor, context.CancellationToken) ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0019)); - var identifier = await _tokenManager.GetIdAsync(token, context.CancellationToken); + var identifier = await manager.GetIdAsync(token, context.CancellationToken); // Attach the token identifier to the principal so that it can be stored in the token. context.Principal.SetTokenId(identifier); @@ -1142,13 +1127,6 @@ public static partial class OpenIddictClientHandlers /// public sealed class AttachTokenPayload : IOpenIddictClientHandler { - private readonly IOpenIddictTokenManager _tokenManager; - - public AttachTokenPayload() => throw new InvalidOperationException(SR.GetResourceString(SR.ID0318)); - - public AttachTokenPayload(IOpenIddictTokenManager tokenManager) - => _tokenManager = tokenManager ?? throw new ArgumentNullException(nameof(tokenManager)); - /// /// Gets the default descriptor definition assigned to this handler. /// @@ -1156,7 +1134,7 @@ public static partial class OpenIddictClientHandlers = OpenIddictClientHandlerDescriptor.CreateBuilder() .AddFilter() .AddFilter() - .UseScopedHandler() + .UseSingletonHandler() .SetOrder(GenerateIdentityModelToken.Descriptor.Order + 1_000) .SetType(OpenIddictClientHandlerType.BuiltIn) .Build(); @@ -1172,11 +1150,14 @@ public static partial class OpenIddictClientHandlers throw new InvalidOperationException(SR.GetResourceString(SR.ID0009)); } - var token = await _tokenManager.FindByIdAsync(identifier, context.CancellationToken) + var manager = context.ServiceProvider.GetService() + ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0318)); + + var token = await manager.FindByIdAsync(identifier, context.CancellationToken) ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0021)); var descriptor = new OpenIddictTokenDescriptor(); - await _tokenManager.PopulateAsync(descriptor, token, context.CancellationToken); + await manager.PopulateAsync(descriptor, token, context.CancellationToken); // Attach the generated token to the token entry. descriptor.Payload = context.Token; @@ -1187,7 +1168,7 @@ public static partial class OpenIddictClientHandlers descriptor.ReferenceId = Base64Url.EncodeToString(RandomNumberGenerator.GetBytes(count: 256 / 8)); } - await _tokenManager.UpdateAsync(token, descriptor, context.CancellationToken); + await manager.UpdateAsync(token, descriptor, context.CancellationToken); context.Logger.LogTrace(6014, SR.GetResourceString(SR.ID6014), context.Token, identifier, context.TokenType); diff --git a/src/OpenIddict.Client/OpenIddictClientHandlers.cs b/src/OpenIddict.Client/OpenIddictClientHandlers.cs index acacdc4b..ea6f5186 100644 --- a/src/OpenIddict.Client/OpenIddictClientHandlers.cs +++ b/src/OpenIddict.Client/OpenIddictClientHandlers.cs @@ -15,6 +15,7 @@ using System.Security.Cryptography; using System.Security.Cryptography.X509Certificates; using System.Text; using System.Text.Json; +using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Primitives; using Microsoft.IdentityModel.JsonWebTokens; @@ -817,13 +818,6 @@ public static partial class OpenIddictClientHandlers /// public sealed class RedeemStateTokenEntry : IOpenIddictClientHandler { - private readonly IOpenIddictTokenManager _tokenManager; - - public RedeemStateTokenEntry() => throw new InvalidOperationException(SR.GetResourceString(SR.ID0318)); - - public RedeemStateTokenEntry(IOpenIddictTokenManager tokenManager) - => _tokenManager = tokenManager ?? throw new ArgumentNullException(nameof(tokenManager)); - /// /// Gets the default descriptor definition assigned to this handler. /// @@ -833,7 +827,7 @@ public static partial class OpenIddictClientHandlers .AddFilter() .AddFilter() .AddFilter() - .UseScopedHandler() + .UseSingletonHandler() // Note: this handler is deliberately executed early in the pipeline to ensure that // the state token entry is always marked as redeemed even if the authentication // demand is rejected later in the pipeline (e.g because an error was returned). @@ -856,9 +850,12 @@ public static partial class OpenIddictClientHandlers return; } + var manager = context.ServiceProvider.GetService() + ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0318)); + // Mark the token as redeemed to prevent future reuses. - var token = await _tokenManager.FindByIdAsync(identifier, context.CancellationToken); - if (token is not null && !await _tokenManager.TryRedeemAsync(token, context.CancellationToken)) + var token = await manager.FindByIdAsync(identifier, context.CancellationToken); + if (token is not null && !await manager.TryRedeemAsync(token, context.CancellationToken)) { context.Reject( error: Errors.InvalidToken, diff --git a/src/OpenIddict.Server/OpenIddictServerHandlers.Authentication.cs b/src/OpenIddict.Server/OpenIddictServerHandlers.Authentication.cs index 76b7513f..26738742 100644 --- a/src/OpenIddict.Server/OpenIddictServerHandlers.Authentication.cs +++ b/src/OpenIddict.Server/OpenIddictServerHandlers.Authentication.cs @@ -1330,27 +1330,12 @@ public static partial class OpenIddictServerHandlers /// public sealed class ValidateResponseType : IOpenIddictServerHandler { - private readonly IOpenIddictApplicationManager? _applicationManager; - - public ValidateResponseType(IOpenIddictApplicationManager? applicationManager = null) - => _applicationManager = applicationManager; - /// /// Gets the default descriptor definition assigned to this handler. /// public static OpenIddictServerHandlerDescriptor Descriptor { get; } = OpenIddictServerHandlerDescriptor.CreateBuilder() - .UseScopedHandler(static provider => - { - // Note: the application manager is only resolved if the degraded mode was not enabled to ensure - // invalid core configuration exceptions are not thrown even if the managers were registered. - var options = provider.GetRequiredService>().CurrentValue; - - return options.EnableDegradedMode - ? new ValidateResponseType(applicationManager: null) - : new ValidateResponseType(provider.GetService() - ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0016))); - }) + .UseSingletonHandler() .SetOrder(ValidateProofKeyForCodeExchangeParameters.Descriptor.Order + 1_000) .SetType(OpenIddictServerHandlerType.BuiltIn) .Build(); @@ -1391,19 +1376,17 @@ public static partial class OpenIddictServerHandlers if (!context.Options.EnableDegradedMode) { - if (_applicationManager is null) - { - throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); - } + var manager = context.ServiceProvider.GetService() + ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); - var application = await _applicationManager.FindByClientIdAsync(context.ClientId, context.CancellationToken) + var application = await manager.FindByClientIdAsync(context.ClientId, context.CancellationToken) ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0032)); // To prevent downgrade attacks, ensure that authorization requests returning // an access token directly from the authorization endpoint are rejected if // the client_id corresponds to a confidential application. if (context.Request.HasResponseType(ResponseTypes.Token) && - await _applicationManager.HasClientTypeAsync(application, ClientTypes.Confidential, context.CancellationToken)) + await manager.HasClientTypeAsync(application, ClientTypes.Confidential, context.CancellationToken)) { context.Logger.LogInformation(6045, SR.GetResourceString(SR.ID6045), context.ClientId); @@ -1424,20 +1407,13 @@ public static partial class OpenIddictServerHandlers /// public sealed class ValidateClientRedirectUri : IOpenIddictServerHandler { - private readonly IOpenIddictApplicationManager _applicationManager; - - public ValidateClientRedirectUri() => throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); - - public ValidateClientRedirectUri(IOpenIddictApplicationManager applicationManager) - => _applicationManager = applicationManager ?? throw new ArgumentNullException(nameof(applicationManager)); - /// /// Gets the default descriptor definition assigned to this handler. /// public static OpenIddictServerHandlerDescriptor Descriptor { get; } = OpenIddictServerHandlerDescriptor.CreateBuilder() .AddFilter() - .UseScopedHandler() + .UseSingletonHandler() .SetOrder(ValidateResponseType.Descriptor.Order + 1_000) .SetType(OpenIddictServerHandlerType.BuiltIn) .Build(); @@ -1449,14 +1425,17 @@ public static partial class OpenIddictServerHandlers Debug.Assert(!string.IsNullOrEmpty(context.ClientId), SR.FormatID4000(Parameters.ClientId)); - var application = await _applicationManager.FindByClientIdAsync(context.ClientId, context.CancellationToken) + var manager = context.ServiceProvider.GetService() + ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); + + var application = await manager.FindByClientIdAsync(context.ClientId, context.CancellationToken) ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0032)); // If no explicit redirect_uri was specified, retrieve the URI associated with the // client and ensure exactly one redirect_uri was attached to the client definition. if (string.IsNullOrEmpty(context.RedirectUri)) { - var uris = await _applicationManager.GetRedirectUrisAsync(application, context.CancellationToken); + var uris = await manager.GetRedirectUrisAsync(application, context.CancellationToken); if (uris.Length is not 1) { context.Logger.LogInformation(6033, SR.GetResourceString(SR.ID6033), Parameters.RedirectUri); @@ -1475,7 +1454,7 @@ public static partial class OpenIddictServerHandlers } // Otherwise, ensure that the specified redirect_uri is valid and is associated with the client application. - if (!await _applicationManager.ValidateRedirectUriAsync(application, context.RedirectUri, context.CancellationToken)) + if (!await manager.ValidateRedirectUriAsync(application, context.RedirectUri, context.CancellationToken)) { context.Logger.LogInformation(6046, SR.GetResourceString(SR.ID6046), context.RedirectUri); @@ -1495,28 +1474,13 @@ public static partial class OpenIddictServerHandlers /// public sealed class ValidateScopes : IOpenIddictServerHandler { - private readonly IOpenIddictScopeManager? _scopeManager; - - public ValidateScopes(IOpenIddictScopeManager? scopeManager = null) - => _scopeManager = scopeManager; - /// /// Gets the default descriptor definition assigned to this handler. /// public static OpenIddictServerHandlerDescriptor Descriptor { get; } = OpenIddictServerHandlerDescriptor.CreateBuilder() .AddFilter() - .UseScopedHandler(static provider => - { - // Note: the scope manager is only resolved if the degraded mode was not enabled to ensure - // invalid core configuration exceptions are not thrown even if the managers were registered. - var options = provider.GetRequiredService>().CurrentValue; - - return options.EnableDegradedMode - ? new ValidateScopes() - : new ValidateScopes(provider.GetService() - ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0016))); - }) + .UseSingletonHandler() .SetOrder(ValidateClientRedirectUri.Descriptor.Order + 1_000) .SetType(OpenIddictServerHandlerType.BuiltIn) .Build(); @@ -1535,14 +1499,12 @@ public static partial class OpenIddictServerHandlers // even if the service was registered and resolved from the dependency injection container. if (scopes.Count is not 0 && !context.Options.EnableDegradedMode) { - if (_scopeManager is null) - { - throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); - } + var manager = context.ServiceProvider.GetService() + ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); - await foreach (var scope in _scopeManager.FindByNamesAsync([.. scopes], context.CancellationToken)) + await foreach (var scope in manager.FindByNamesAsync([.. scopes], context.CancellationToken)) { - var name = await _scopeManager.GetNameAsync(scope, context.CancellationToken); + var name = await manager.GetNameAsync(scope, context.CancellationToken); if (!string.IsNullOrEmpty(name)) { scopes.Remove(name); @@ -1570,28 +1532,13 @@ public static partial class OpenIddictServerHandlers /// public sealed class ValidateResources : IOpenIddictServerHandler { - private readonly IOpenIddictResourceManager? _resourceManager; - - public ValidateResources(IOpenIddictResourceManager? resourceManager = null) - => _resourceManager = resourceManager; - /// /// Gets the default descriptor definition assigned to this handler. /// public static OpenIddictServerHandlerDescriptor Descriptor { get; } = OpenIddictServerHandlerDescriptor.CreateBuilder() .AddFilter() - .UseScopedHandler(static provider => - { - // Note: the resource manager is only resolved if the degraded mode was not enabled to ensure - // invalid core configuration exceptions are not thrown even if the managers were registered. - var options = provider.GetRequiredService>().CurrentValue; - - return options.EnableDegradedMode - ? new ValidateResources() - : new ValidateResources(provider.GetService() - ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0016))); - }) + .UseSingletonHandler() .SetOrder(ValidateScopes.Descriptor.Order + 1_000) .SetType(OpenIddictServerHandlerType.BuiltIn) .Build(); @@ -1610,14 +1557,12 @@ public static partial class OpenIddictServerHandlers // even if the service was registered and resolved from the dependency injection container. if (resources.Count is not 0 && !context.Options.EnableDegradedMode) { - if (_resourceManager is null) - { - throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); - } + var manager = context.ServiceProvider.GetService() + ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); - await foreach (var resource in _resourceManager.FindByNamesAsync([.. resources], context.CancellationToken)) + await foreach (var resource in manager.FindByNamesAsync([.. resources], context.CancellationToken)) { - var name = await _resourceManager.GetNameAsync(resource, context.CancellationToken); + var name = await manager.GetNameAsync(resource, context.CancellationToken); if (!string.IsNullOrEmpty(name)) { resources.Remove(name); @@ -1646,13 +1591,6 @@ public static partial class OpenIddictServerHandlers /// public sealed class ValidateEndpointPermissions : IOpenIddictServerHandler { - private readonly IOpenIddictApplicationManager _applicationManager; - - public ValidateEndpointPermissions() => throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); - - public ValidateEndpointPermissions(IOpenIddictApplicationManager applicationManager) - => _applicationManager = applicationManager ?? throw new ArgumentNullException(nameof(applicationManager)); - /// /// Gets the default descriptor definition assigned to this handler. /// @@ -1660,7 +1598,7 @@ public static partial class OpenIddictServerHandlers = OpenIddictServerHandlerDescriptor.CreateBuilder() .AddFilter() .AddFilter() - .UseScopedHandler() + .UseSingletonHandler() .SetOrder(ValidateResources.Descriptor.Order + 1_000) .SetType(OpenIddictServerHandlerType.BuiltIn) .Build(); @@ -1672,11 +1610,14 @@ public static partial class OpenIddictServerHandlers Debug.Assert(!string.IsNullOrEmpty(context.ClientId), SR.FormatID4000(Parameters.ClientId)); - var application = await _applicationManager.FindByClientIdAsync(context.ClientId, context.CancellationToken) + var manager = context.ServiceProvider.GetService() + ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); + + var application = await manager.FindByClientIdAsync(context.ClientId, context.CancellationToken) ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0032)); // Reject the request if the application is not allowed to use the authorization endpoint. - if (!await _applicationManager.HasPermissionAsync(application, Permissions.Endpoints.Authorization, context.CancellationToken)) + if (!await manager.HasPermissionAsync(application, Permissions.Endpoints.Authorization, context.CancellationToken)) { context.Logger.LogInformation(6048, SR.GetResourceString(SR.ID6048), context.ClientId); @@ -1696,13 +1637,6 @@ public static partial class OpenIddictServerHandlers /// public sealed class ValidateGrantTypePermissions : IOpenIddictServerHandler { - private readonly IOpenIddictApplicationManager _applicationManager; - - public ValidateGrantTypePermissions() => throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); - - public ValidateGrantTypePermissions(IOpenIddictApplicationManager applicationManager) - => _applicationManager = applicationManager ?? throw new ArgumentNullException(nameof(applicationManager)); - /// /// Gets the default descriptor definition assigned to this handler. /// @@ -1710,7 +1644,7 @@ public static partial class OpenIddictServerHandlers = OpenIddictServerHandlerDescriptor.CreateBuilder() .AddFilter() .AddFilter() - .UseScopedHandler() + .UseSingletonHandler() .SetOrder(ValidateEndpointPermissions.Descriptor.Order + 1_000) .SetType(OpenIddictServerHandlerType.BuiltIn) .Build(); @@ -1722,12 +1656,15 @@ public static partial class OpenIddictServerHandlers Debug.Assert(!string.IsNullOrEmpty(context.ClientId), SR.FormatID4000(Parameters.ClientId)); - var application = await _applicationManager.FindByClientIdAsync(context.ClientId, context.CancellationToken) + var manager = context.ServiceProvider.GetService() + ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); + + var application = await manager.FindByClientIdAsync(context.ClientId, context.CancellationToken) ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0032)); // Reject the request if the application is not allowed to use the authorization code grant. if (context.Request.IsAuthorizationCodeFlow() && - !await _applicationManager.HasPermissionAsync(application, Permissions.GrantTypes.AuthorizationCode, context.CancellationToken)) + !await manager.HasPermissionAsync(application, Permissions.GrantTypes.AuthorizationCode, context.CancellationToken)) { context.Logger.LogInformation(6049, SR.GetResourceString(SR.ID6049), context.ClientId); @@ -1741,7 +1678,7 @@ public static partial class OpenIddictServerHandlers // Reject the request if the application is not allowed to use the implicit grant. if (context.Request.IsImplicitFlow() && - !await _applicationManager.HasPermissionAsync(application, Permissions.GrantTypes.Implicit, context.CancellationToken)) + !await manager.HasPermissionAsync(application, Permissions.GrantTypes.Implicit, context.CancellationToken)) { context.Logger.LogInformation(6050, SR.GetResourceString(SR.ID6050), context.ClientId); @@ -1755,8 +1692,8 @@ public static partial class OpenIddictServerHandlers // Reject the request if the application is not allowed to use the authorization code/implicit grants. if (context.Request.IsHybridFlow() && - (!await _applicationManager.HasPermissionAsync(application, Permissions.GrantTypes.AuthorizationCode, context.CancellationToken) || - !await _applicationManager.HasPermissionAsync(application, Permissions.GrantTypes.Implicit, context.CancellationToken))) + (!await manager.HasPermissionAsync(application, Permissions.GrantTypes.AuthorizationCode, context.CancellationToken) || + !await manager.HasPermissionAsync(application, Permissions.GrantTypes.Implicit, context.CancellationToken))) { context.Logger.LogInformation(6051, SR.GetResourceString(SR.ID6051), context.ClientId); @@ -1771,7 +1708,7 @@ public static partial class OpenIddictServerHandlers // Reject the request if the offline_access scope was request and // if the application is not allowed to use the refresh token grant. if (context.Request.HasScope(Scopes.OfflineAccess) && - !await _applicationManager.HasPermissionAsync(application, Permissions.GrantTypes.RefreshToken, context.CancellationToken)) + !await manager.HasPermissionAsync(application, Permissions.GrantTypes.RefreshToken, context.CancellationToken)) { context.Logger.LogInformation(6052, SR.GetResourceString(SR.ID6052), context.ClientId, Scopes.OfflineAccess); @@ -1791,13 +1728,6 @@ public static partial class OpenIddictServerHandlers /// public sealed class ValidateResponseTypePermissions : IOpenIddictServerHandler { - private readonly IOpenIddictApplicationManager _applicationManager; - - public ValidateResponseTypePermissions() => throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); - - public ValidateResponseTypePermissions(IOpenIddictApplicationManager applicationManager) - => _applicationManager = applicationManager ?? throw new ArgumentNullException(nameof(applicationManager)); - /// /// Gets the default descriptor definition assigned to this handler. /// @@ -1805,7 +1735,7 @@ public static partial class OpenIddictServerHandlers = OpenIddictServerHandlerDescriptor.CreateBuilder() .AddFilter() .AddFilter() - .UseScopedHandler() + .UseSingletonHandler() .SetOrder(ValidateGrantTypePermissions.Descriptor.Order + 1_000) .SetType(OpenIddictServerHandlerType.BuiltIn) .Build(); @@ -1817,7 +1747,10 @@ public static partial class OpenIddictServerHandlers Debug.Assert(!string.IsNullOrEmpty(context.ClientId), SR.FormatID4000(Parameters.ClientId)); - var application = await _applicationManager.FindByClientIdAsync(context.ClientId, context.CancellationToken) + var manager = context.ServiceProvider.GetService() + ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); + + var application = await manager.FindByClientIdAsync(context.ClientId, context.CancellationToken) ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0032)); // Reject requests that specify a response_type for which no permission was granted. @@ -1838,7 +1771,7 @@ public static partial class OpenIddictServerHandlers // Note: response type permissions are always prefixed with "rst:". const string prefix = Permissions.Prefixes.ResponseType; - foreach (var permission in await _applicationManager.GetPermissionsAsync(application, context.CancellationToken)) + foreach (var permission in await manager.GetPermissionsAsync(application, context.CancellationToken)) { // Ignore permissions that are not response type permissions. if (!permission.StartsWith(prefix, StringComparison.Ordinal)) @@ -1866,13 +1799,6 @@ public static partial class OpenIddictServerHandlers /// public sealed class ValidateScopePermissions : IOpenIddictServerHandler { - private readonly IOpenIddictApplicationManager _applicationManager; - - public ValidateScopePermissions() => throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); - - public ValidateScopePermissions(IOpenIddictApplicationManager applicationManager) - => _applicationManager = applicationManager ?? throw new ArgumentNullException(nameof(applicationManager)); - /// /// Gets the default descriptor definition assigned to this handler. /// @@ -1880,7 +1806,7 @@ public static partial class OpenIddictServerHandlers = OpenIddictServerHandlerDescriptor.CreateBuilder() .AddFilter() .AddFilter() - .UseScopedHandler() + .UseSingletonHandler() .SetOrder(ValidateResponseTypePermissions.Descriptor.Order + 1_000) .SetType(OpenIddictServerHandlerType.BuiltIn) .Build(); @@ -1892,7 +1818,10 @@ public static partial class OpenIddictServerHandlers Debug.Assert(!string.IsNullOrEmpty(context.ClientId), SR.FormatID4000(Parameters.ClientId)); - var application = await _applicationManager.FindByClientIdAsync(context.ClientId, context.CancellationToken) + var manager = context.ServiceProvider.GetService() + ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); + + var application = await manager.FindByClientIdAsync(context.ClientId, context.CancellationToken) ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0032)); foreach (var scope in context.Request.GetScopes()) @@ -1905,7 +1834,7 @@ public static partial class OpenIddictServerHandlers } // Reject the request if the application is not allowed to use the iterated scope. - if (!await _applicationManager.HasPermissionAsync(application, Permissions.Prefixes.Scope + scope, context.CancellationToken)) + if (!await manager.HasPermissionAsync(application, Permissions.Prefixes.Scope + scope, context.CancellationToken)) { context.Logger.LogInformation(6052, SR.GetResourceString(SR.ID6052), context.ClientId, scope); @@ -1927,13 +1856,6 @@ public static partial class OpenIddictServerHandlers /// public sealed class ValidateResourcePermissions : IOpenIddictServerHandler { - private readonly IOpenIddictApplicationManager _applicationManager; - - public ValidateResourcePermissions() => throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); - - public ValidateResourcePermissions(IOpenIddictApplicationManager applicationManager) - => _applicationManager = applicationManager ?? throw new ArgumentNullException(nameof(applicationManager)); - /// /// Gets the default descriptor definition assigned to this handler. /// @@ -1941,7 +1863,7 @@ public static partial class OpenIddictServerHandlers = OpenIddictServerHandlerDescriptor.CreateBuilder() .AddFilter() .AddFilter() - .UseScopedHandler() + .UseSingletonHandler() .SetOrder(ValidateScopePermissions.Descriptor.Order + 1_000) .SetType(OpenIddictServerHandlerType.BuiltIn) .Build(); @@ -1953,13 +1875,16 @@ public static partial class OpenIddictServerHandlers Debug.Assert(!string.IsNullOrEmpty(context.ClientId), SR.FormatID4000(Parameters.ClientId)); - var application = await _applicationManager.FindByClientIdAsync(context.ClientId, context.CancellationToken) + var manager = context.ServiceProvider.GetService() + ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); + + var application = await manager.FindByClientIdAsync(context.ClientId, context.CancellationToken) ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0032)); foreach (var resource in context.Request.GetResources()) { // Reject the request if the application is not allowed to use the iterated resource. - if (!await _applicationManager.HasPermissionAsync(application, Permissions.Prefixes.Resource + resource, context.CancellationToken)) + if (!await manager.HasPermissionAsync(application, Permissions.Prefixes.Resource + resource, context.CancellationToken)) { context.Logger.LogInformation(6281, SR.GetResourceString(SR.ID6278), context.ClientId, resource); @@ -1981,20 +1906,13 @@ public static partial class OpenIddictServerHandlers /// public sealed class ValidatePushedAuthorizationRequestsRequirement : IOpenIddictServerHandler { - private readonly IOpenIddictApplicationManager _applicationManager; - - public ValidatePushedAuthorizationRequestsRequirement() => throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); - - public ValidatePushedAuthorizationRequestsRequirement(IOpenIddictApplicationManager applicationManager) - => _applicationManager = applicationManager ?? throw new ArgumentNullException(nameof(applicationManager)); - /// /// Gets the default descriptor definition assigned to this handler. /// public static OpenIddictServerHandlerDescriptor Descriptor { get; } = OpenIddictServerHandlerDescriptor.CreateBuilder() .AddFilter() - .UseScopedHandler() + .UseSingletonHandler() .SetOrder(ValidateResourcePermissions.Descriptor.Order + 1_000) .SetType(OpenIddictServerHandlerType.BuiltIn) .Build(); @@ -2014,10 +1932,13 @@ public static partial class OpenIddictServerHandlers return; } - var application = await _applicationManager.FindByClientIdAsync(context.ClientId, context.CancellationToken) + var manager = context.ServiceProvider.GetService() + ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); + + var application = await manager.FindByClientIdAsync(context.ClientId, context.CancellationToken) ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0032)); - if (await _applicationManager.HasRequirementAsync(application, Requirements.Features.PushedAuthorizationRequests, context.CancellationToken)) + if (await manager.HasRequirementAsync(application, Requirements.Features.PushedAuthorizationRequests, context.CancellationToken)) { if (string.IsNullOrEmpty(context.Request.RequestUri)) { @@ -2048,20 +1969,13 @@ public static partial class OpenIddictServerHandlers /// public sealed class ValidateProofKeyForCodeExchangeRequirement : IOpenIddictServerHandler { - private readonly IOpenIddictApplicationManager _applicationManager; - - public ValidateProofKeyForCodeExchangeRequirement() => throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); - - public ValidateProofKeyForCodeExchangeRequirement(IOpenIddictApplicationManager applicationManager) - => _applicationManager = applicationManager ?? throw new ArgumentNullException(nameof(applicationManager)); - /// /// Gets the default descriptor definition assigned to this handler. /// public static OpenIddictServerHandlerDescriptor Descriptor { get; } = OpenIddictServerHandlerDescriptor.CreateBuilder() .AddFilter() - .UseScopedHandler() + .UseSingletonHandler() .SetOrder(ValidatePushedAuthorizationRequestsRequirement.Descriptor.Order + 1_000) .SetType(OpenIddictServerHandlerType.BuiltIn) .Build(); @@ -2080,10 +1994,13 @@ public static partial class OpenIddictServerHandlers return; } - var application = await _applicationManager.FindByClientIdAsync(context.ClientId, context.CancellationToken) + var manager = context.ServiceProvider.GetService() + ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); + + var application = await manager.FindByClientIdAsync(context.ClientId, context.CancellationToken) ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0032)); - if (await _applicationManager.HasRequirementAsync(application, Requirements.Features.ProofKeyForCodeExchange, context.CancellationToken)) + if (await manager.HasRequirementAsync(application, Requirements.Features.ProofKeyForCodeExchange, context.CancellationToken)) { context.Logger.LogInformation(6033, SR.GetResourceString(SR.ID6033), Parameters.CodeChallenge); @@ -3417,27 +3334,12 @@ public static partial class OpenIddictServerHandlers /// public sealed class ValidatePushedResponseType : IOpenIddictServerHandler { - private readonly IOpenIddictApplicationManager? _applicationManager; - - public ValidatePushedResponseType(IOpenIddictApplicationManager? applicationManager = null) - => _applicationManager = applicationManager; - /// /// Gets the default descriptor definition assigned to this handler. /// public static OpenIddictServerHandlerDescriptor Descriptor { get; } = OpenIddictServerHandlerDescriptor.CreateBuilder() - .UseScopedHandler(static provider => - { - // Note: the application manager is only resolved if the degraded mode was not enabled to ensure - // invalid core configuration exceptions are not thrown even if the managers were registered. - var options = provider.GetRequiredService>().CurrentValue; - - return options.EnableDegradedMode - ? new ValidatePushedResponseType(applicationManager: null) - : new ValidatePushedResponseType(provider.GetService() - ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0016))); - }) + .UseSingletonHandler() .SetOrder(ValidatePushedAuthentication.Descriptor.Order + 1_000) .SetType(OpenIddictServerHandlerType.BuiltIn) .Build(); @@ -3478,19 +3380,17 @@ public static partial class OpenIddictServerHandlers if (!context.Options.EnableDegradedMode) { - if (_applicationManager is null) - { - throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); - } + var manager = context.ServiceProvider.GetService() + ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); - var application = await _applicationManager.FindByClientIdAsync(context.ClientId, context.CancellationToken) + var application = await manager.FindByClientIdAsync(context.ClientId, context.CancellationToken) ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0032)); // To prevent downgrade attacks, ensure that pushed authorization requests returning // an access token directly from the authorization endpoint are rejected if // the client_id corresponds to a confidential application. if (context.Request.HasResponseType(ResponseTypes.Token) && - await _applicationManager.HasClientTypeAsync(application, ClientTypes.Confidential, context.CancellationToken)) + await manager.HasClientTypeAsync(application, ClientTypes.Confidential, context.CancellationToken)) { context.Logger.LogInformation(6251, SR.GetResourceString(SR.ID6251), context.ClientId); @@ -3511,20 +3411,13 @@ public static partial class OpenIddictServerHandlers /// public sealed class ValidatePushedClientRedirectUri : IOpenIddictServerHandler { - private readonly IOpenIddictApplicationManager _applicationManager; - - public ValidatePushedClientRedirectUri() => throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); - - public ValidatePushedClientRedirectUri(IOpenIddictApplicationManager applicationManager) - => _applicationManager = applicationManager ?? throw new ArgumentNullException(nameof(applicationManager)); - /// /// Gets the default descriptor definition assigned to this handler. /// public static OpenIddictServerHandlerDescriptor Descriptor { get; } = OpenIddictServerHandlerDescriptor.CreateBuilder() .AddFilter() - .UseScopedHandler() + .UseSingletonHandler() .SetOrder(ValidatePushedResponseType.Descriptor.Order + 1_000) .SetType(OpenIddictServerHandlerType.BuiltIn) .Build(); @@ -3536,14 +3429,17 @@ public static partial class OpenIddictServerHandlers Debug.Assert(!string.IsNullOrEmpty(context.ClientId), SR.FormatID4000(Parameters.ClientId)); - var application = await _applicationManager.FindByClientIdAsync(context.ClientId, context.CancellationToken) + var manager = context.ServiceProvider.GetService() + ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); + + var application = await manager.FindByClientIdAsync(context.ClientId, context.CancellationToken) ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0032)); // If no explicit redirect_uri was specified, retrieve the URI associated with the // client and ensure exactly one redirect_uri was attached to the client definition. if (string.IsNullOrEmpty(context.RedirectUri)) { - var uris = await _applicationManager.GetRedirectUrisAsync(application, context.CancellationToken); + var uris = await manager.GetRedirectUrisAsync(application, context.CancellationToken); if (uris.Length is not 1) { context.Logger.LogInformation(6240, SR.GetResourceString(SR.ID6240), Parameters.RedirectUri); @@ -3562,7 +3458,7 @@ public static partial class OpenIddictServerHandlers } // Otherwise, ensure that the specified redirect_uri is valid and is associated with the client application. - if (!await _applicationManager.ValidateRedirectUriAsync(application, context.RedirectUri, context.CancellationToken)) + if (!await manager.ValidateRedirectUriAsync(application, context.RedirectUri, context.CancellationToken)) { context.Logger.LogInformation(6252, SR.GetResourceString(SR.ID6252), context.RedirectUri); @@ -3582,28 +3478,13 @@ public static partial class OpenIddictServerHandlers /// public sealed class ValidatePushedScopes : IOpenIddictServerHandler { - private readonly IOpenIddictScopeManager? _scopeManager; - - public ValidatePushedScopes(IOpenIddictScopeManager? scopeManager = null) - => _scopeManager = scopeManager; - /// /// Gets the default descriptor definition assigned to this handler. /// public static OpenIddictServerHandlerDescriptor Descriptor { get; } = OpenIddictServerHandlerDescriptor.CreateBuilder() .AddFilter() - .UseScopedHandler(static provider => - { - // Note: the scope manager is only resolved if the degraded mode was not enabled to ensure - // invalid core configuration exceptions are not thrown even if the managers were registered. - var options = provider.GetRequiredService>().CurrentValue; - - return options.EnableDegradedMode - ? new ValidatePushedScopes() - : new ValidatePushedScopes(provider.GetService() - ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0016))); - }) + .UseSingletonHandler() .SetOrder(ValidatePushedClientRedirectUri.Descriptor.Order + 1_000) .SetType(OpenIddictServerHandlerType.BuiltIn) .Build(); @@ -3622,14 +3503,12 @@ public static partial class OpenIddictServerHandlers // even if the service was registered and resolved from the dependency injection container. if (scopes.Count is not 0 && !context.Options.EnableDegradedMode) { - if (_scopeManager is null) - { - throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); - } + var manager = context.ServiceProvider.GetService() + ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); - await foreach (var scope in _scopeManager.FindByNamesAsync([.. scopes], context.CancellationToken)) + await foreach (var scope in manager.FindByNamesAsync([.. scopes], context.CancellationToken)) { - var name = await _scopeManager.GetNameAsync(scope, context.CancellationToken); + var name = await manager.GetNameAsync(scope, context.CancellationToken); if (!string.IsNullOrEmpty(name)) { scopes.Remove(name); @@ -3657,28 +3536,13 @@ public static partial class OpenIddictServerHandlers /// public sealed class ValidatePushedResources : IOpenIddictServerHandler { - private readonly IOpenIddictResourceManager? _resourceManager; - - public ValidatePushedResources(IOpenIddictResourceManager? resourceManager = null) - => _resourceManager = resourceManager; - /// /// Gets the default descriptor definition assigned to this handler. /// public static OpenIddictServerHandlerDescriptor Descriptor { get; } = OpenIddictServerHandlerDescriptor.CreateBuilder() .AddFilter() - .UseScopedHandler(static provider => - { - // Note: the resource manager is only resolved if the degraded mode was not enabled to ensure - // invalid core configuration exceptions are not thrown even if the managers were registered. - var options = provider.GetRequiredService>().CurrentValue; - - return options.EnableDegradedMode - ? new ValidatePushedResources() - : new ValidatePushedResources(provider.GetService() - ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0016))); - }) + .UseSingletonHandler() .SetOrder(ValidatePushedScopes.Descriptor.Order + 1_000) .SetType(OpenIddictServerHandlerType.BuiltIn) .Build(); @@ -3697,14 +3561,12 @@ public static partial class OpenIddictServerHandlers // even if the service was registered and resolved from the dependency injection container. if (resources.Count is not 0 && !context.Options.EnableDegradedMode) { - if (_resourceManager is null) - { - throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); - } + var manager = context.ServiceProvider.GetService() + ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); - await foreach (var resource in _resourceManager.FindByNamesAsync([.. resources], context.CancellationToken)) + await foreach (var resource in manager.FindByNamesAsync([.. resources], context.CancellationToken)) { - var name = await _resourceManager.GetNameAsync(resource, context.CancellationToken); + var name = await manager.GetNameAsync(resource, context.CancellationToken); if (!string.IsNullOrEmpty(name)) { resources.Remove(name); @@ -3733,13 +3595,6 @@ public static partial class OpenIddictServerHandlers /// public sealed class ValidatePushedEndpointPermissions : IOpenIddictServerHandler { - private readonly IOpenIddictApplicationManager _applicationManager; - - public ValidatePushedEndpointPermissions() => throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); - - public ValidatePushedEndpointPermissions(IOpenIddictApplicationManager applicationManager) - => _applicationManager = applicationManager ?? throw new ArgumentNullException(nameof(applicationManager)); - /// /// Gets the default descriptor definition assigned to this handler. /// @@ -3747,7 +3602,7 @@ public static partial class OpenIddictServerHandlers = OpenIddictServerHandlerDescriptor.CreateBuilder() .AddFilter() .AddFilter() - .UseScopedHandler() + .UseSingletonHandler() .SetOrder(ValidatePushedResources.Descriptor.Order + 1_000) .SetType(OpenIddictServerHandlerType.BuiltIn) .Build(); @@ -3759,11 +3614,14 @@ public static partial class OpenIddictServerHandlers Debug.Assert(!string.IsNullOrEmpty(context.ClientId), SR.FormatID4000(Parameters.ClientId)); - var application = await _applicationManager.FindByClientIdAsync(context.ClientId, context.CancellationToken) + var manager = context.ServiceProvider.GetService() + ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); + + var application = await manager.FindByClientIdAsync(context.ClientId, context.CancellationToken) ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0032)); // Reject the request if the application is not allowed to use the pushed authorization endpoint. - if (!await _applicationManager.HasPermissionAsync(application, Permissions.Endpoints.PushedAuthorization, context.CancellationToken)) + if (!await manager.HasPermissionAsync(application, Permissions.Endpoints.PushedAuthorization, context.CancellationToken)) { context.Logger.LogInformation(6254, SR.GetResourceString(SR.ID6254), context.ClientId); @@ -3783,13 +3641,6 @@ public static partial class OpenIddictServerHandlers /// public sealed class ValidatePushedGrantTypePermissions : IOpenIddictServerHandler { - private readonly IOpenIddictApplicationManager _applicationManager; - - public ValidatePushedGrantTypePermissions() => throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); - - public ValidatePushedGrantTypePermissions(IOpenIddictApplicationManager applicationManager) - => _applicationManager = applicationManager ?? throw new ArgumentNullException(nameof(applicationManager)); - /// /// Gets the default descriptor definition assigned to this handler. /// @@ -3797,7 +3648,7 @@ public static partial class OpenIddictServerHandlers = OpenIddictServerHandlerDescriptor.CreateBuilder() .AddFilter() .AddFilter() - .UseScopedHandler() + .UseSingletonHandler() .SetOrder(ValidatePushedEndpointPermissions.Descriptor.Order + 1_000) .SetType(OpenIddictServerHandlerType.BuiltIn) .Build(); @@ -3809,12 +3660,15 @@ public static partial class OpenIddictServerHandlers Debug.Assert(!string.IsNullOrEmpty(context.ClientId), SR.FormatID4000(Parameters.ClientId)); - var application = await _applicationManager.FindByClientIdAsync(context.ClientId, context.CancellationToken) + var manager = context.ServiceProvider.GetService() + ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); + + var application = await manager.FindByClientIdAsync(context.ClientId, context.CancellationToken) ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0032)); // Reject the request if the application is not allowed to use the authorization code grant. if (context.Request.IsAuthorizationCodeFlow() && - !await _applicationManager.HasPermissionAsync(application, Permissions.GrantTypes.AuthorizationCode, context.CancellationToken)) + !await manager.HasPermissionAsync(application, Permissions.GrantTypes.AuthorizationCode, context.CancellationToken)) { context.Logger.LogInformation(6255, SR.GetResourceString(SR.ID6255), context.ClientId); @@ -3828,7 +3682,7 @@ public static partial class OpenIddictServerHandlers // Reject the request if the application is not allowed to use the implicit grant. if (context.Request.IsImplicitFlow() && - !await _applicationManager.HasPermissionAsync(application, Permissions.GrantTypes.Implicit, context.CancellationToken)) + !await manager.HasPermissionAsync(application, Permissions.GrantTypes.Implicit, context.CancellationToken)) { context.Logger.LogInformation(6256, SR.GetResourceString(SR.ID6256), context.ClientId); @@ -3842,8 +3696,8 @@ public static partial class OpenIddictServerHandlers // Reject the request if the application is not allowed to use the authorization code/implicit grants. if (context.Request.IsHybridFlow() && - (!await _applicationManager.HasPermissionAsync(application, Permissions.GrantTypes.AuthorizationCode, context.CancellationToken) || - !await _applicationManager.HasPermissionAsync(application, Permissions.GrantTypes.Implicit, context.CancellationToken))) + (!await manager.HasPermissionAsync(application, Permissions.GrantTypes.AuthorizationCode, context.CancellationToken) || + !await manager.HasPermissionAsync(application, Permissions.GrantTypes.Implicit, context.CancellationToken))) { context.Logger.LogInformation(6257, SR.GetResourceString(SR.ID6257), context.ClientId); @@ -3858,7 +3712,7 @@ public static partial class OpenIddictServerHandlers // Reject the request if the offline_access scope was request and // if the application is not allowed to use the refresh token grant. if (context.Request.HasScope(Scopes.OfflineAccess) && - !await _applicationManager.HasPermissionAsync(application, Permissions.GrantTypes.RefreshToken, context.CancellationToken)) + !await manager.HasPermissionAsync(application, Permissions.GrantTypes.RefreshToken, context.CancellationToken)) { context.Logger.LogInformation(6258, SR.GetResourceString(SR.ID6258), context.ClientId, Scopes.OfflineAccess); @@ -3878,13 +3732,6 @@ public static partial class OpenIddictServerHandlers /// public sealed class ValidatePushedResponseTypePermissions : IOpenIddictServerHandler { - private readonly IOpenIddictApplicationManager _applicationManager; - - public ValidatePushedResponseTypePermissions() => throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); - - public ValidatePushedResponseTypePermissions(IOpenIddictApplicationManager applicationManager) - => _applicationManager = applicationManager ?? throw new ArgumentNullException(nameof(applicationManager)); - /// /// Gets the default descriptor definition assigned to this handler. /// @@ -3892,7 +3739,7 @@ public static partial class OpenIddictServerHandlers = OpenIddictServerHandlerDescriptor.CreateBuilder() .AddFilter() .AddFilter() - .UseScopedHandler() + .UseSingletonHandler() .SetOrder(ValidatePushedGrantTypePermissions.Descriptor.Order + 1_000) .SetType(OpenIddictServerHandlerType.BuiltIn) .Build(); @@ -3904,7 +3751,10 @@ public static partial class OpenIddictServerHandlers Debug.Assert(!string.IsNullOrEmpty(context.ClientId), SR.FormatID4000(Parameters.ClientId)); - var application = await _applicationManager.FindByClientIdAsync(context.ClientId, context.CancellationToken) + var manager = context.ServiceProvider.GetService() + ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); + + var application = await manager.FindByClientIdAsync(context.ClientId, context.CancellationToken) ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0032)); // Reject requests that specify a response_type for which no permission was granted. @@ -3925,7 +3775,7 @@ public static partial class OpenIddictServerHandlers // Note: response type permissions are always prefixed with "rst:". const string prefix = Permissions.Prefixes.ResponseType; - foreach (var permission in await _applicationManager.GetPermissionsAsync(application, context.CancellationToken)) + foreach (var permission in await manager.GetPermissionsAsync(application, context.CancellationToken)) { // Ignore permissions that are not response type permissions. if (!permission.StartsWith(prefix, StringComparison.Ordinal)) @@ -3953,13 +3803,6 @@ public static partial class OpenIddictServerHandlers /// public sealed class ValidatePushedScopePermissions : IOpenIddictServerHandler { - private readonly IOpenIddictApplicationManager _applicationManager; - - public ValidatePushedScopePermissions() => throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); - - public ValidatePushedScopePermissions(IOpenIddictApplicationManager applicationManager) - => _applicationManager = applicationManager ?? throw new ArgumentNullException(nameof(applicationManager)); - /// /// Gets the default descriptor definition assigned to this handler. /// @@ -3967,7 +3810,7 @@ public static partial class OpenIddictServerHandlers = OpenIddictServerHandlerDescriptor.CreateBuilder() .AddFilter() .AddFilter() - .UseScopedHandler() + .UseSingletonHandler() .SetOrder(ValidatePushedResponseTypePermissions.Descriptor.Order + 1_000) .SetType(OpenIddictServerHandlerType.BuiltIn) .Build(); @@ -3979,7 +3822,10 @@ public static partial class OpenIddictServerHandlers Debug.Assert(!string.IsNullOrEmpty(context.ClientId), SR.FormatID4000(Parameters.ClientId)); - var application = await _applicationManager.FindByClientIdAsync(context.ClientId, context.CancellationToken) + var manager = context.ServiceProvider.GetService() + ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); + + var application = await manager.FindByClientIdAsync(context.ClientId, context.CancellationToken) ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0032)); foreach (var scope in context.Request.GetScopes()) @@ -3992,7 +3838,7 @@ public static partial class OpenIddictServerHandlers } // Reject the request if the application is not allowed to use the iterated scope. - if (!await _applicationManager.HasPermissionAsync(application, Permissions.Prefixes.Scope + scope, context.CancellationToken)) + if (!await manager.HasPermissionAsync(application, Permissions.Prefixes.Scope + scope, context.CancellationToken)) { context.Logger.LogInformation(6258, SR.GetResourceString(SR.ID6258), context.ClientId, scope); @@ -4014,13 +3860,6 @@ public static partial class OpenIddictServerHandlers /// public sealed class ValidatePushedResourcePermissions : IOpenIddictServerHandler { - private readonly IOpenIddictApplicationManager _applicationManager; - - public ValidatePushedResourcePermissions() => throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); - - public ValidatePushedResourcePermissions(IOpenIddictApplicationManager applicationManager) - => _applicationManager = applicationManager ?? throw new ArgumentNullException(nameof(applicationManager)); - /// /// Gets the default descriptor definition assigned to this handler. /// @@ -4028,7 +3867,7 @@ public static partial class OpenIddictServerHandlers = OpenIddictServerHandlerDescriptor.CreateBuilder() .AddFilter() .AddFilter() - .UseScopedHandler() + .UseSingletonHandler() .SetOrder(ValidatePushedScopePermissions.Descriptor.Order + 1_000) .SetType(OpenIddictServerHandlerType.BuiltIn) .Build(); @@ -4040,13 +3879,16 @@ public static partial class OpenIddictServerHandlers Debug.Assert(!string.IsNullOrEmpty(context.ClientId), SR.FormatID4000(Parameters.ClientId)); - var application = await _applicationManager.FindByClientIdAsync(context.ClientId, context.CancellationToken) + var manager = context.ServiceProvider.GetService() + ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); + + var application = await manager.FindByClientIdAsync(context.ClientId, context.CancellationToken) ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0032)); foreach (var resource in context.Request.GetResources()) { // Reject the request if the application is not allowed to use the iterated resource. - if (!await _applicationManager.HasPermissionAsync(application, Permissions.Prefixes.Resource + resource, context.CancellationToken)) + if (!await manager.HasPermissionAsync(application, Permissions.Prefixes.Resource + resource, context.CancellationToken)) { context.Logger.LogInformation(6283, SR.GetResourceString(SR.ID6279), context.ClientId, resource); @@ -4068,20 +3910,13 @@ public static partial class OpenIddictServerHandlers /// public sealed class ValidatePushedProofKeyForCodeExchangeRequirement : IOpenIddictServerHandler { - private readonly IOpenIddictApplicationManager _applicationManager; - - public ValidatePushedProofKeyForCodeExchangeRequirement() => throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); - - public ValidatePushedProofKeyForCodeExchangeRequirement(IOpenIddictApplicationManager applicationManager) - => _applicationManager = applicationManager ?? throw new ArgumentNullException(nameof(applicationManager)); - /// /// Gets the default descriptor definition assigned to this handler. /// public static OpenIddictServerHandlerDescriptor Descriptor { get; } = OpenIddictServerHandlerDescriptor.CreateBuilder() .AddFilter() - .UseScopedHandler() + .UseSingletonHandler() .SetOrder(ValidatePushedResourcePermissions.Descriptor.Order + 1_000) .SetType(OpenIddictServerHandlerType.BuiltIn) .Build(); @@ -4100,10 +3935,13 @@ public static partial class OpenIddictServerHandlers return; } - var application = await _applicationManager.FindByClientIdAsync(context.ClientId, context.CancellationToken) + var manager = context.ServiceProvider.GetService() + ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); + + var application = await manager.FindByClientIdAsync(context.ClientId, context.CancellationToken) ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0032)); - if (await _applicationManager.HasRequirementAsync(application, Requirements.Features.ProofKeyForCodeExchange, context.CancellationToken)) + if (await manager.HasRequirementAsync(application, Requirements.Features.ProofKeyForCodeExchange, context.CancellationToken)) { context.Logger.LogInformation(6240, SR.GetResourceString(SR.ID6240), Parameters.CodeChallenge); diff --git a/src/OpenIddict.Server/OpenIddictServerHandlers.Device.cs b/src/OpenIddict.Server/OpenIddictServerHandlers.Device.cs index 5d3a0ffa..a3481f33 100644 --- a/src/OpenIddict.Server/OpenIddictServerHandlers.Device.cs +++ b/src/OpenIddict.Server/OpenIddictServerHandlers.Device.cs @@ -436,28 +436,13 @@ public static partial class OpenIddictServerHandlers /// public sealed class ValidateScopes : IOpenIddictServerHandler { - private readonly IOpenIddictScopeManager? _scopeManager; - - public ValidateScopes(IOpenIddictScopeManager? scopeManager = null) - => _scopeManager = scopeManager; - /// /// Gets the default descriptor definition assigned to this handler. /// public static OpenIddictServerHandlerDescriptor Descriptor { get; } = OpenIddictServerHandlerDescriptor.CreateBuilder() .AddFilter() - .UseScopedHandler(static provider => - { - // Note: the scope manager is only resolved if the degraded mode was not enabled to ensure - // invalid core configuration exceptions are not thrown even if the managers were registered. - var options = provider.GetRequiredService>().CurrentValue; - - return options.EnableDegradedMode - ? new ValidateScopes() - : new ValidateScopes(provider.GetService() - ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0016))); - }) + .UseSingletonHandler() .SetOrder(ValidateClientCredentialsParameters.Descriptor.Order + 1_000) .SetType(OpenIddictServerHandlerType.BuiltIn) .Build(); @@ -476,14 +461,12 @@ public static partial class OpenIddictServerHandlers // even if the service was registered and resolved from the dependency injection container. if (scopes.Count is not 0 && !context.Options.EnableDegradedMode) { - if (_scopeManager is null) - { - throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); - } + var manager = context.ServiceProvider.GetService() + ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); - await foreach (var scope in _scopeManager.FindByNamesAsync([.. scopes], context.CancellationToken)) + await foreach (var scope in manager.FindByNamesAsync([.. scopes], context.CancellationToken)) { - var name = await _scopeManager.GetNameAsync(scope, context.CancellationToken); + var name = await manager.GetNameAsync(scope, context.CancellationToken); if (!string.IsNullOrEmpty(name)) { scopes.Remove(name); @@ -568,13 +551,6 @@ public static partial class OpenIddictServerHandlers /// public sealed class ValidateEndpointPermissions : IOpenIddictServerHandler { - private readonly IOpenIddictApplicationManager _applicationManager; - - public ValidateEndpointPermissions() => throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); - - public ValidateEndpointPermissions(IOpenIddictApplicationManager applicationManager) - => _applicationManager = applicationManager ?? throw new ArgumentNullException(nameof(applicationManager)); - /// /// Gets the default descriptor definition assigned to this handler. /// @@ -583,7 +559,7 @@ public static partial class OpenIddictServerHandlers .AddFilter() .AddFilter() .AddFilter() - .UseScopedHandler() + .UseSingletonHandler() .SetOrder(ValidateDeviceAuthentication.Descriptor.Order + 1_000) .SetType(OpenIddictServerHandlerType.BuiltIn) .Build(); @@ -595,14 +571,17 @@ public static partial class OpenIddictServerHandlers Debug.Assert(!string.IsNullOrEmpty(context.ClientId), SR.FormatID4000(Parameters.ClientId)); - var application = await _applicationManager.FindByClientIdAsync(context.ClientId, context.CancellationToken) + var manager = context.ServiceProvider.GetService() + ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); + + var application = await manager.FindByClientIdAsync(context.ClientId, context.CancellationToken) ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0032)); // Reject the request if the application is not allowed to use the device authorization endpoint. // // Note: the legacy "ept:device" permission is still allowed for backward compatibility. - if (!await _applicationManager.HasPermissionAsync(application, Permissions.Endpoints.DeviceAuthorization, context.CancellationToken) && - !await _applicationManager.HasPermissionAsync(application, "ept:device", context.CancellationToken)) + if (!await manager.HasPermissionAsync(application, Permissions.Endpoints.DeviceAuthorization, context.CancellationToken) && + !await manager.HasPermissionAsync(application, "ept:device", context.CancellationToken)) { context.Logger.LogInformation(6062, SR.GetResourceString(SR.ID6062), context.ClientId); @@ -622,13 +601,6 @@ public static partial class OpenIddictServerHandlers /// public sealed class ValidateGrantTypePermissions : IOpenIddictServerHandler { - private readonly IOpenIddictApplicationManager _applicationManager; - - public ValidateGrantTypePermissions() => throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); - - public ValidateGrantTypePermissions(IOpenIddictApplicationManager applicationManager) - => _applicationManager = applicationManager ?? throw new ArgumentNullException(nameof(applicationManager)); - /// /// Gets the default descriptor definition assigned to this handler. /// @@ -636,7 +608,7 @@ public static partial class OpenIddictServerHandlers = OpenIddictServerHandlerDescriptor.CreateBuilder() .AddFilter() .AddFilter() - .UseScopedHandler() + .UseSingletonHandler() .SetOrder(ValidateEndpointPermissions.Descriptor.Order + 1_000) .SetType(OpenIddictServerHandlerType.BuiltIn) .Build(); @@ -648,11 +620,14 @@ public static partial class OpenIddictServerHandlers Debug.Assert(!string.IsNullOrEmpty(context.ClientId), SR.FormatID4000(Parameters.ClientId)); - var application = await _applicationManager.FindByClientIdAsync(context.ClientId, context.CancellationToken) + var manager = context.ServiceProvider.GetService() + ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); + + var application = await manager.FindByClientIdAsync(context.ClientId, context.CancellationToken) ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0032)); // Reject the request if the application is not allowed to use the device code grant. - if (!await _applicationManager.HasPermissionAsync(application, Permissions.GrantTypes.DeviceCode, context.CancellationToken)) + if (!await manager.HasPermissionAsync(application, Permissions.GrantTypes.DeviceCode, context.CancellationToken)) { context.Logger.LogInformation(6118, SR.GetResourceString(SR.ID6118), context.ClientId); @@ -667,7 +642,7 @@ public static partial class OpenIddictServerHandlers // Reject the request if the offline_access scope was request and // if the application is not allowed to use the refresh token grant. if (context.Request.HasScope(Scopes.OfflineAccess) && - !await _applicationManager.HasPermissionAsync(application, Permissions.GrantTypes.RefreshToken, context.CancellationToken)) + !await manager.HasPermissionAsync(application, Permissions.GrantTypes.RefreshToken, context.CancellationToken)) { context.Logger.LogInformation(6120, SR.GetResourceString(SR.ID6120), context.ClientId, Scopes.OfflineAccess); @@ -688,13 +663,6 @@ public static partial class OpenIddictServerHandlers /// public sealed class ValidateScopePermissions : IOpenIddictServerHandler { - private readonly IOpenIddictApplicationManager _applicationManager; - - public ValidateScopePermissions() => throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); - - public ValidateScopePermissions(IOpenIddictApplicationManager applicationManager) - => _applicationManager = applicationManager ?? throw new ArgumentNullException(nameof(applicationManager)); - /// /// Gets the default descriptor definition assigned to this handler. /// @@ -703,7 +671,7 @@ public static partial class OpenIddictServerHandlers .AddFilter() .AddFilter() .AddFilter() - .UseScopedHandler() + .UseSingletonHandler() .SetOrder(ValidateGrantTypePermissions.Descriptor.Order + 1_000) .SetType(OpenIddictServerHandlerType.BuiltIn) .Build(); @@ -715,7 +683,10 @@ public static partial class OpenIddictServerHandlers Debug.Assert(!string.IsNullOrEmpty(context.ClientId), SR.FormatID4000(Parameters.ClientId)); - var application = await _applicationManager.FindByClientIdAsync(context.ClientId, context.CancellationToken) + var manager = context.ServiceProvider.GetService() + ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); + + var application = await manager.FindByClientIdAsync(context.ClientId, context.CancellationToken) ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0032)); foreach (var scope in context.Request.GetScopes()) @@ -728,7 +699,7 @@ public static partial class OpenIddictServerHandlers } // Reject the request if the application is not allowed to use the iterated scope. - if (!await _applicationManager.HasPermissionAsync(application, Permissions.Prefixes.Scope + scope, context.CancellationToken)) + if (!await manager.HasPermissionAsync(application, Permissions.Prefixes.Scope + scope, context.CancellationToken)) { context.Logger.LogInformation(6063, SR.GetResourceString(SR.ID6063), context.ClientId, scope); diff --git a/src/OpenIddict.Server/OpenIddictServerHandlers.Exchange.cs b/src/OpenIddict.Server/OpenIddictServerHandlers.Exchange.cs index 296dfdc8..d2387136 100644 --- a/src/OpenIddict.Server/OpenIddictServerHandlers.Exchange.cs +++ b/src/OpenIddict.Server/OpenIddictServerHandlers.Exchange.cs @@ -1002,28 +1002,13 @@ public static partial class OpenIddictServerHandlers /// public sealed class ValidateScopes : IOpenIddictServerHandler { - private readonly IOpenIddictScopeManager? _scopeManager; - - public ValidateScopes(IOpenIddictScopeManager? scopeManager = null) - => _scopeManager = scopeManager; - /// /// Gets the default descriptor definition assigned to this handler. /// public static OpenIddictServerHandlerDescriptor Descriptor { get; } = OpenIddictServerHandlerDescriptor.CreateBuilder() .AddFilter() - .UseScopedHandler(static provider => - { - // Note: the scope manager is only resolved if the degraded mode was not enabled to ensure - // invalid core configuration exceptions are not thrown even if the managers were registered. - var options = provider.GetRequiredService>().CurrentValue; - - return options.EnableDegradedMode - ? new ValidateScopes() - : new ValidateScopes(provider.GetService() - ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0016))); - }) + .UseSingletonHandler() .SetOrder(ValidateResourceParameter.Descriptor.Order + 1_000) .SetType(OpenIddictServerHandlerType.BuiltIn) .Build(); @@ -1042,14 +1027,12 @@ public static partial class OpenIddictServerHandlers // even if the service was registered and resolved from the dependency injection container. if (scopes.Count is not 0 && !context.Options.EnableDegradedMode) { - if (_scopeManager is null) - { - throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); - } + var manager = context.ServiceProvider.GetService() + ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); - await foreach (var scope in _scopeManager.FindByNamesAsync([.. scopes], context.CancellationToken)) + await foreach (var scope in manager.FindByNamesAsync([.. scopes], context.CancellationToken)) { - var name = await _scopeManager.GetNameAsync(scope, context.CancellationToken); + var name = await manager.GetNameAsync(scope, context.CancellationToken); if (!string.IsNullOrEmpty(name)) { scopes.Remove(name); @@ -1118,28 +1101,13 @@ public static partial class OpenIddictServerHandlers /// public sealed class ValidateResources : IOpenIddictServerHandler { - private readonly IOpenIddictResourceManager? _resourceManager; - - public ValidateResources(IOpenIddictResourceManager? resourceManager = null) - => _resourceManager = resourceManager; - /// /// Gets the default descriptor definition assigned to this handler. /// public static OpenIddictServerHandlerDescriptor Descriptor { get; } = OpenIddictServerHandlerDescriptor.CreateBuilder() .AddFilter() - .UseScopedHandler(static provider => - { - // Note: the resource manager is only resolved if the degraded mode was not enabled to ensure - // invalid core configuration exceptions are not thrown even if the managers were registered. - var options = provider.GetRequiredService>().CurrentValue; - - return options.EnableDegradedMode - ? new ValidateResources() - : new ValidateResources(provider.GetService() - ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0016))); - }) + .UseSingletonHandler() .SetOrder(ValidateAudiences.Descriptor.Order + 1_000) .SetType(OpenIddictServerHandlerType.BuiltIn) .Build(); @@ -1158,14 +1126,12 @@ public static partial class OpenIddictServerHandlers // even if the service was registered and resolved from the dependency injection container. if (resources.Count is not 0 && !context.Options.EnableDegradedMode) { - if (_resourceManager is null) - { - throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); - } + var manager = context.ServiceProvider.GetService() + ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); - await foreach (var resource in _resourceManager.FindByNamesAsync([.. resources], context.CancellationToken)) + await foreach (var resource in manager.FindByNamesAsync([.. resources], context.CancellationToken)) { - var name = await _resourceManager.GetNameAsync(resource, context.CancellationToken); + var name = await manager.GetNameAsync(resource, context.CancellationToken); if (!string.IsNullOrEmpty(name)) { resources.Remove(name); @@ -1257,13 +1223,6 @@ public static partial class OpenIddictServerHandlers /// public sealed class ValidateEndpointPermissions : IOpenIddictServerHandler { - private readonly IOpenIddictApplicationManager _applicationManager; - - public ValidateEndpointPermissions() => throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); - - public ValidateEndpointPermissions(IOpenIddictApplicationManager applicationManager) - => _applicationManager = applicationManager ?? throw new ArgumentNullException(nameof(applicationManager)); - /// /// Gets the default descriptor definition assigned to this handler. /// @@ -1272,7 +1231,7 @@ public static partial class OpenIddictServerHandlers .AddFilter() .AddFilter() .AddFilter() - .UseScopedHandler() + .UseSingletonHandler() .SetOrder(ValidateAuthentication.Descriptor.Order + 1_000) .SetType(OpenIddictServerHandlerType.BuiltIn) .Build(); @@ -1284,11 +1243,14 @@ public static partial class OpenIddictServerHandlers Debug.Assert(!string.IsNullOrEmpty(context.ClientId), SR.FormatID4000(Parameters.ClientId)); - var application = await _applicationManager.FindByClientIdAsync(context.ClientId, context.CancellationToken) + var manager = context.ServiceProvider.GetService() + ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); + + var application = await manager.FindByClientIdAsync(context.ClientId, context.CancellationToken) ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0032)); // Reject the request if the application is not allowed to use the token endpoint. - if (!await _applicationManager.HasPermissionAsync(application, Permissions.Endpoints.Token, context.CancellationToken)) + if (!await manager.HasPermissionAsync(application, Permissions.Endpoints.Token, context.CancellationToken)) { context.Logger.LogInformation(6086, SR.GetResourceString(SR.ID6086), context.ClientId); @@ -1309,13 +1271,6 @@ public static partial class OpenIddictServerHandlers /// public sealed class ValidateGrantTypePermissions : IOpenIddictServerHandler { - private readonly IOpenIddictApplicationManager _applicationManager; - - public ValidateGrantTypePermissions() => throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); - - public ValidateGrantTypePermissions(IOpenIddictApplicationManager applicationManager) - => _applicationManager = applicationManager ?? throw new ArgumentNullException(nameof(applicationManager)); - /// /// Gets the default descriptor definition assigned to this handler. /// @@ -1324,7 +1279,7 @@ public static partial class OpenIddictServerHandlers .AddFilter() .AddFilter() .AddFilter() - .UseScopedHandler() + .UseSingletonHandler() .SetOrder(ValidateEndpointPermissions.Descriptor.Order + 1_000) .SetType(OpenIddictServerHandlerType.BuiltIn) .Build(); @@ -1336,11 +1291,14 @@ public static partial class OpenIddictServerHandlers Debug.Assert(!string.IsNullOrEmpty(context.ClientId), SR.FormatID4000(Parameters.ClientId)); - var application = await _applicationManager.FindByClientIdAsync(context.ClientId, context.CancellationToken) + var manager = context.ServiceProvider.GetService() + ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); + + var application = await manager.FindByClientIdAsync(context.ClientId, context.CancellationToken) ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0032)); // Reject the request if the application is not allowed to use the specified grant type. - if (!await _applicationManager.HasPermissionAsync(application, Permissions.Prefixes.GrantType + context.Request.GrantType, context.CancellationToken)) + if (!await manager.HasPermissionAsync(application, Permissions.Prefixes.GrantType + context.Request.GrantType, context.CancellationToken)) { context.Logger.LogInformation(6087, SR.GetResourceString(SR.ID6087), context.ClientId, context.Request.GrantType); @@ -1355,7 +1313,7 @@ public static partial class OpenIddictServerHandlers // Reject the request if the offline_access scope was request and if // the application is not allowed to use the refresh token grant type. if (context.Request.HasScope(Scopes.OfflineAccess) && - !await _applicationManager.HasPermissionAsync(application, Permissions.GrantTypes.RefreshToken, context.CancellationToken)) + !await manager.HasPermissionAsync(application, Permissions.GrantTypes.RefreshToken, context.CancellationToken)) { context.Logger.LogInformation(6088, SR.GetResourceString(SR.ID6088), context.ClientId, Scopes.OfflineAccess); @@ -1376,13 +1334,6 @@ public static partial class OpenIddictServerHandlers /// public sealed class ValidateScopePermissions : IOpenIddictServerHandler { - private readonly IOpenIddictApplicationManager _applicationManager; - - public ValidateScopePermissions() => throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); - - public ValidateScopePermissions(IOpenIddictApplicationManager applicationManager) - => _applicationManager = applicationManager ?? throw new ArgumentNullException(nameof(applicationManager)); - /// /// Gets the default descriptor definition assigned to this handler. /// @@ -1391,7 +1342,7 @@ public static partial class OpenIddictServerHandlers .AddFilter() .AddFilter() .AddFilter() - .UseScopedHandler() + .UseSingletonHandler() .SetOrder(ValidateGrantTypePermissions.Descriptor.Order + 1_000) .SetType(OpenIddictServerHandlerType.BuiltIn) .Build(); @@ -1403,7 +1354,10 @@ public static partial class OpenIddictServerHandlers Debug.Assert(!string.IsNullOrEmpty(context.ClientId), SR.FormatID4000(Parameters.ClientId)); - var application = await _applicationManager.FindByClientIdAsync(context.ClientId, context.CancellationToken) + var manager = context.ServiceProvider.GetService() + ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); + + var application = await manager.FindByClientIdAsync(context.ClientId, context.CancellationToken) ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0032)); foreach (var scope in context.Request.GetScopes()) @@ -1416,7 +1370,7 @@ public static partial class OpenIddictServerHandlers } // Reject the request if the application is not allowed to use the iterated scope. - if (!await _applicationManager.HasPermissionAsync(application, Permissions.Prefixes.Scope + scope, context.CancellationToken)) + if (!await manager.HasPermissionAsync(application, Permissions.Prefixes.Scope + scope, context.CancellationToken)) { context.Logger.LogInformation(6089, SR.GetResourceString(SR.ID6089), context.ClientId, scope); @@ -1438,13 +1392,6 @@ public static partial class OpenIddictServerHandlers /// public sealed class ValidateAudiencePermissions : IOpenIddictServerHandler { - private readonly IOpenIddictApplicationManager _applicationManager; - - public ValidateAudiencePermissions() => throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); - - public ValidateAudiencePermissions(IOpenIddictApplicationManager applicationManager) - => _applicationManager = applicationManager ?? throw new ArgumentNullException(nameof(applicationManager)); - /// /// Gets the default descriptor definition assigned to this handler. /// @@ -1453,7 +1400,7 @@ public static partial class OpenIddictServerHandlers .AddFilter() .AddFilter() .AddFilter() - .UseScopedHandler() + .UseSingletonHandler() .SetOrder(ValidateGrantTypePermissions.Descriptor.Order + 1_000) .SetType(OpenIddictServerHandlerType.BuiltIn) .Build(); @@ -1465,13 +1412,16 @@ public static partial class OpenIddictServerHandlers Debug.Assert(!string.IsNullOrEmpty(context.ClientId), SR.FormatID4000(Parameters.ClientId)); - var application = await _applicationManager.FindByClientIdAsync(context.ClientId, context.CancellationToken) + var manager = context.ServiceProvider.GetService() + ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); + + var application = await manager.FindByClientIdAsync(context.ClientId, context.CancellationToken) ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0032)); foreach (var audience in context.Request.GetAudiences()) { // Reject the request if the application is not allowed to use the iterated audience. - if (!await _applicationManager.HasPermissionAsync(application, Permissions.Prefixes.Audience + audience, context.CancellationToken)) + if (!await manager.HasPermissionAsync(application, Permissions.Prefixes.Audience + audience, context.CancellationToken)) { context.Logger.LogInformation(6278, SR.GetResourceString(SR.ID6276), context.ClientId, audience); @@ -1493,13 +1443,6 @@ public static partial class OpenIddictServerHandlers /// public sealed class ValidateResourcePermissions : IOpenIddictServerHandler { - private readonly IOpenIddictApplicationManager _applicationManager; - - public ValidateResourcePermissions() => throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); - - public ValidateResourcePermissions(IOpenIddictApplicationManager applicationManager) - => _applicationManager = applicationManager ?? throw new ArgumentNullException(nameof(applicationManager)); - /// /// Gets the default descriptor definition assigned to this handler. /// @@ -1508,7 +1451,7 @@ public static partial class OpenIddictServerHandlers .AddFilter() .AddFilter() .AddFilter() - .UseScopedHandler() + .UseSingletonHandler() .SetOrder(ValidateAudiencePermissions.Descriptor.Order + 1_000) .SetType(OpenIddictServerHandlerType.BuiltIn) .Build(); @@ -1520,13 +1463,16 @@ public static partial class OpenIddictServerHandlers Debug.Assert(!string.IsNullOrEmpty(context.ClientId), SR.FormatID4000(Parameters.ClientId)); - var application = await _applicationManager.FindByClientIdAsync(context.ClientId, context.CancellationToken) + var manager = context.ServiceProvider.GetService() + ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); + + var application = await manager.FindByClientIdAsync(context.ClientId, context.CancellationToken) ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0032)); foreach (var resource in context.Request.GetResources()) { // Reject the request if the application is not allowed to use the iterated resource. - if (!await _applicationManager.HasPermissionAsync(application, Permissions.Prefixes.Resource + resource, context.CancellationToken)) + if (!await manager.HasPermissionAsync(application, Permissions.Prefixes.Resource + resource, context.CancellationToken)) { context.Logger.LogInformation(6279, SR.GetResourceString(SR.ID6277), context.ClientId, resource); @@ -1548,13 +1494,6 @@ public static partial class OpenIddictServerHandlers /// public sealed class ValidateProofKeyForCodeExchangeRequirement : IOpenIddictServerHandler { - private readonly IOpenIddictApplicationManager _applicationManager; - - public ValidateProofKeyForCodeExchangeRequirement() => throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); - - public ValidateProofKeyForCodeExchangeRequirement(IOpenIddictApplicationManager applicationManager) - => _applicationManager = applicationManager ?? throw new ArgumentNullException(nameof(applicationManager)); - /// /// Gets the default descriptor definition assigned to this handler. /// @@ -1562,7 +1501,7 @@ public static partial class OpenIddictServerHandlers = OpenIddictServerHandlerDescriptor.CreateBuilder() .AddFilter() .AddFilter() - .UseScopedHandler() + .UseSingletonHandler() .SetOrder(ValidateResourcePermissions.Descriptor.Order + 1_000) .SetType(OpenIddictServerHandlerType.BuiltIn) .Build(); @@ -1586,10 +1525,13 @@ public static partial class OpenIddictServerHandlers Debug.Assert(!string.IsNullOrEmpty(context.ClientId), SR.FormatID4000(Parameters.ClientId)); - var application = await _applicationManager.FindByClientIdAsync(context.ClientId, context.CancellationToken) + var manager = context.ServiceProvider.GetService() + ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); + + var application = await manager.FindByClientIdAsync(context.ClientId, context.CancellationToken) ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0032)); - if (await _applicationManager.HasRequirementAsync(application, Requirements.Features.ProofKeyForCodeExchange, context.CancellationToken)) + if (await manager.HasRequirementAsync(application, Requirements.Features.ProofKeyForCodeExchange, context.CancellationToken)) { context.Logger.LogInformation(6077, SR.GetResourceString(SR.ID6077), Parameters.CodeVerifier); diff --git a/src/OpenIddict.Server/OpenIddictServerHandlers.Introspection.cs b/src/OpenIddict.Server/OpenIddictServerHandlers.Introspection.cs index 8724b048..ac1ee416 100644 --- a/src/OpenIddict.Server/OpenIddictServerHandlers.Introspection.cs +++ b/src/OpenIddict.Server/OpenIddictServerHandlers.Introspection.cs @@ -12,6 +12,7 @@ using System.Text; using System.Text.Encodings.Web; using System.Text.Json; using System.Text.Json.Nodes; +using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Microsoft.IdentityModel.JsonWebTokens; using Microsoft.IdentityModel.Tokens; @@ -501,13 +502,6 @@ public static partial class OpenIddictServerHandlers /// public sealed class ValidateEndpointPermissions : IOpenIddictServerHandler { - private readonly IOpenIddictApplicationManager _applicationManager; - - public ValidateEndpointPermissions() => throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); - - public ValidateEndpointPermissions(IOpenIddictApplicationManager applicationManager) - => _applicationManager = applicationManager ?? throw new ArgumentNullException(nameof(applicationManager)); - /// /// Gets the default descriptor definition assigned to this handler. /// @@ -516,7 +510,7 @@ public static partial class OpenIddictServerHandlers .AddFilter() .AddFilter() .AddFilter() - .UseScopedHandler() + .UseSingletonHandler() .SetOrder(ValidateAuthentication.Descriptor.Order + 1_000) .SetType(OpenIddictServerHandlerType.BuiltIn) .Build(); @@ -528,11 +522,14 @@ public static partial class OpenIddictServerHandlers Debug.Assert(!string.IsNullOrEmpty(context.ClientId), SR.FormatID4000(Parameters.ClientId)); - var application = await _applicationManager.FindByClientIdAsync(context.ClientId, context.CancellationToken) + var manager = context.ServiceProvider.GetService() + ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); + + var application = await manager.FindByClientIdAsync(context.ClientId, context.CancellationToken) ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0032)); // Reject the request if the application is not allowed to use the introspection endpoint. - if (!await _applicationManager.HasPermissionAsync(application, Permissions.Endpoints.Introspection, context.CancellationToken)) + if (!await manager.HasPermissionAsync(application, Permissions.Endpoints.Introspection, context.CancellationToken)) { context.Logger.LogInformation(6103, SR.GetResourceString(SR.ID6103), context.ClientId); @@ -774,13 +771,6 @@ public static partial class OpenIddictServerHandlers /// public sealed class AttachApplicationClaims : IOpenIddictServerHandler { - private readonly IOpenIddictApplicationManager _applicationManager; - - public AttachApplicationClaims() => throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); - - public AttachApplicationClaims(IOpenIddictApplicationManager applicationManager) - => _applicationManager = applicationManager ?? throw new ArgumentNullException(nameof(applicationManager)); - /// /// Gets the default descriptor definition assigned to this handler. /// @@ -788,7 +778,7 @@ public static partial class OpenIddictServerHandlers = OpenIddictServerHandlerDescriptor.CreateBuilder() .AddFilter() .AddFilter() - .UseScopedHandler() + .UseSingletonHandler() .SetOrder(AttachMetadataClaims.Descriptor.Order + 1_000) .SetType(OpenIddictServerHandlerType.BuiltIn) .Build(); @@ -816,11 +806,14 @@ public static partial class OpenIddictServerHandlers return; } - var application = await _applicationManager.FindByClientIdAsync(context.Request.ClientId, context.CancellationToken) + var manager = context.ServiceProvider.GetService() + ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); + + var application = await manager.FindByClientIdAsync(context.Request.ClientId, context.CancellationToken) ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0032)); // Public clients are not allowed to access sensitive claims as authentication cannot be enforced. - if (await _applicationManager.HasClientTypeAsync(application, ClientTypes.Public, context.CancellationToken)) + if (await manager.HasClientTypeAsync(application, ClientTypes.Public, context.CancellationToken)) { context.Logger.LogInformation(6107, SR.GetResourceString(SR.ID6107), context.Request.ClientId); diff --git a/src/OpenIddict.Server/OpenIddictServerHandlers.Protection.cs b/src/OpenIddict.Server/OpenIddictServerHandlers.Protection.cs index 595bc070..b82adb43 100644 --- a/src/OpenIddict.Server/OpenIddictServerHandlers.Protection.cs +++ b/src/OpenIddict.Server/OpenIddictServerHandlers.Protection.cs @@ -62,27 +62,12 @@ public static partial class OpenIddictServerHandlers /// public sealed class ResolveTokenValidationParameters : IOpenIddictServerHandler { - private readonly IOpenIddictApplicationManager? _applicationManager; - - public ResolveTokenValidationParameters(IOpenIddictApplicationManager? applicationManager = null) - => _applicationManager = applicationManager; - /// /// Gets the default descriptor definition assigned to this handler. /// public static OpenIddictServerHandlerDescriptor Descriptor { get; } = OpenIddictServerHandlerDescriptor.CreateBuilder() - .UseScopedHandler(static provider => - { - // Note: the application manager is only resolved if the degraded mode was not enabled to ensure - // invalid core configuration exceptions are not thrown even if the managers were registered. - var options = provider.GetRequiredService>().CurrentValue; - - return options.EnableDegradedMode - ? new ResolveTokenValidationParameters() - : new ResolveTokenValidationParameters(provider.GetService() - ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0016))); - }) + .UseSingletonHandler() .SetOrder(int.MinValue + 100_000) .SetType(OpenIddictServerHandlerType.BuiltIn) .Build(); @@ -162,10 +147,8 @@ public static partial class OpenIddictServerHandlers // to implement a custom event handler that attaches an issuer signing key resolver. if (!context.Options.EnableDegradedMode) { - if (_applicationManager is null) - { - throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); - } + var manager = context.ServiceProvider.GetService() + ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); parameters.IssuerSigningKeyResolver = (_, token, _, _) => Task.Run(async () => { @@ -173,8 +156,8 @@ public static partial class OpenIddictServerHandlers // the signing keys from the JSON Web Key set attached to the client application. // // Important: at this stage, the issuer isn't guaranteed to be valid or legitimate. - var application = await _applicationManager.FindByClientIdAsync(token.Issuer, context.CancellationToken); - if (application is not null && await _applicationManager.GetJsonWebKeySetAsync(application, context.CancellationToken) + var application = await manager.FindByClientIdAsync(token.Issuer, context.CancellationToken); + if (application is not null && await manager.GetJsonWebKeySetAsync(application, context.CancellationToken) is JsonWebKeySet set) { return set.GetSigningKeys(); @@ -322,13 +305,6 @@ public static partial class OpenIddictServerHandlers /// public sealed class ValidateReferenceTokenIdentifier : IOpenIddictServerHandler { - private readonly IOpenIddictTokenManager _tokenManager; - - public ValidateReferenceTokenIdentifier() => throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); - - public ValidateReferenceTokenIdentifier(IOpenIddictTokenManager tokenManager) - => _tokenManager = tokenManager ?? throw new ArgumentNullException(nameof(tokenManager)); - /// /// Gets the default descriptor definition assigned to this handler. /// @@ -336,7 +312,7 @@ public static partial class OpenIddictServerHandlers = OpenIddictServerHandlerDescriptor.CreateBuilder() .AddFilter() .AddFilter() - .UseScopedHandler() + .UseSingletonHandler() .SetOrder(RemoveDisallowedCharacters.Descriptor.Order + 1_000) .SetType(OpenIddictServerHandlerType.BuiltIn) .Build(); @@ -358,8 +334,11 @@ public static partial class OpenIddictServerHandlers return; } + var manager = context.ServiceProvider.GetService() + ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); + // If the reference token cannot be found, don't return an error to allow another handler to validate it. - var token = await _tokenManager.FindByReferenceIdAsync(context.Token, context.CancellationToken); + var token = await manager.FindByReferenceIdAsync(context.Token, context.CancellationToken); if (token is null) { return; @@ -369,8 +348,8 @@ public static partial class OpenIddictServerHandlers if (!(context.ValidTokenTypes.Count switch { 0 => true, // If no specific token type is expected, accept all token types at this stage. - 1 => await _tokenManager.HasTypeAsync(token, context.ValidTokenTypes.ElementAt(0), context.CancellationToken), - _ => await _tokenManager.HasTypeAsync(token, [.. context.ValidTokenTypes], context.CancellationToken) + 1 => await manager.HasTypeAsync(token, context.ValidTokenTypes.ElementAt(0), context.CancellationToken), + _ => await manager.HasTypeAsync(token, [.. context.ValidTokenTypes], context.CancellationToken) })) { context.Reject( @@ -407,7 +386,7 @@ public static partial class OpenIddictServerHandlers return; } - var payload = await _tokenManager.GetPayloadAsync(token, context.CancellationToken); + var payload = await manager.GetPayloadAsync(token, context.CancellationToken); if (string.IsNullOrEmpty(payload)) { throw new InvalidOperationException(SR.GetResourceString(SR.ID0026)); @@ -418,7 +397,7 @@ public static partial class OpenIddictServerHandlers // used to restore the properties associated with the token. context.IsReferenceToken = true; context.Token = payload; - context.TokenId = await _tokenManager.GetIdAsync(token, context.CancellationToken); + context.TokenId = await manager.GetIdAsync(token, context.CancellationToken); } } @@ -753,13 +732,6 @@ public static partial class OpenIddictServerHandlers /// public sealed class RestoreTokenEntryProperties : IOpenIddictServerHandler { - private readonly IOpenIddictTokenManager _tokenManager; - - public RestoreTokenEntryProperties() => throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); - - public RestoreTokenEntryProperties(IOpenIddictTokenManager tokenManager) - => _tokenManager = tokenManager ?? throw new ArgumentNullException(nameof(tokenManager)); - /// /// Gets the default descriptor definition assigned to this handler. /// @@ -767,7 +739,7 @@ public static partial class OpenIddictServerHandlers = OpenIddictServerHandlerDescriptor.CreateBuilder() .AddFilter() .AddFilter() - .UseScopedHandler() + .UseSingletonHandler() .SetOrder(MapInternalClaims.Descriptor.Order + 1_000) .SetType(OpenIddictServerHandlerType.BuiltIn) .Build(); @@ -798,8 +770,11 @@ public static partial class OpenIddictServerHandlers return; } + var manager = context.ServiceProvider.GetService() + ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); + // If the token entry cannot be found, return a generic error. - var token = await _tokenManager.FindByIdAsync(identifier, context.CancellationToken); + var token = await manager.FindByIdAsync(identifier, context.CancellationToken); if (token is null) { context.Reject( @@ -827,9 +802,9 @@ public static partial class OpenIddictServerHandlers // If the token was not validated as a reference token but has a reference identifier attached, this // may indicate that the payload stored in the database has leaked and is being used as a regular, // non-reference token. To prevent this, reject the token if the reference identifier is not null. - if (!context.IsReferenceToken && !string.IsNullOrEmpty(await _tokenManager.GetReferenceIdAsync(token, context.CancellationToken))) + if (!context.IsReferenceToken && !string.IsNullOrEmpty(await manager.GetReferenceIdAsync(token, context.CancellationToken))) { - context.Logger.LogWarning(6292, SR.GetResourceString(SR.ID6292), await _tokenManager.GetIdAsync(token, context.CancellationToken)); + context.Logger.LogWarning(6292, SR.GetResourceString(SR.ID6292), await manager.GetIdAsync(token, context.CancellationToken)); context.Reject( error: Errors.InvalidToken, @@ -855,11 +830,11 @@ public static partial class OpenIddictServerHandlers // Restore the creation/expiration dates/identifiers from the token entry metadata. context.Principal - .SetCreationDate(await _tokenManager.GetCreationDateAsync(token, context.CancellationToken)) - .SetExpirationDate(await _tokenManager.GetExpirationDateAsync(token, context.CancellationToken)) - .SetAuthorizationId(context.AuthorizationId = await _tokenManager.GetAuthorizationIdAsync(token, context.CancellationToken)) - .SetTokenId(context.TokenId = await _tokenManager.GetIdAsync(token, context.CancellationToken)) - .SetTokenType(await _tokenManager.GetTypeAsync(token, context.CancellationToken)); + .SetCreationDate(await manager.GetCreationDateAsync(token, context.CancellationToken)) + .SetExpirationDate(await manager.GetExpirationDateAsync(token, context.CancellationToken)) + .SetAuthorizationId(context.AuthorizationId = await manager.GetAuthorizationIdAsync(token, context.CancellationToken)) + .SetTokenId(context.TokenId = await manager.GetIdAsync(token, context.CancellationToken)) + .SetTokenType(await manager.GetTypeAsync(token, context.CancellationToken)); } } @@ -1209,13 +1184,6 @@ public static partial class OpenIddictServerHandlers /// public sealed class ValidateTokenEntry : IOpenIddictServerHandler { - private readonly IOpenIddictTokenManager _tokenManager; - - public ValidateTokenEntry() => throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); - - public ValidateTokenEntry(IOpenIddictTokenManager tokenManager) - => _tokenManager = tokenManager ?? throw new ArgumentNullException(nameof(tokenManager)); - /// /// Gets the default descriptor definition assigned to this handler. /// @@ -1224,7 +1192,7 @@ public static partial class OpenIddictServerHandlers .AddFilter() .AddFilter() .AddFilter() - .UseScopedHandler() + .UseSingletonHandler() .SetOrder(ValidateProofOfPossession.Descriptor.Order + 1_000) .SetType(OpenIddictServerHandlerType.BuiltIn) .Build(); @@ -1236,7 +1204,10 @@ public static partial class OpenIddictServerHandlers Debug.Assert(context.Principal is { Identity: ClaimsIdentity }, SR.GetResourceString(SR.ID4006)); Debug.Assert(!string.IsNullOrEmpty(context.TokenId), SR.GetResourceString(SR.ID4017)); - var token = await _tokenManager.FindByIdAsync(context.TokenId, context.CancellationToken) + var manager = context.ServiceProvider.GetService() + ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); + + var token = await manager.FindByIdAsync(context.TokenId, context.CancellationToken) ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0021)); // If the token is already marked as redeemed, this may indicate that it was compromised. @@ -1245,7 +1216,7 @@ public static partial class OpenIddictServerHandlers // Special logic is used to avoid revoking refresh tokens already marked as redeemed to allow for a small leeway. // Note: the authorization itself is not revoked to allow the legitimate client to start a new flow. // See https://tools.ietf.org/html/rfc6749#section-10.5 for more information. - if (await _tokenManager.HasStatusAsync(token, Statuses.Redeemed, context.CancellationToken)) + if (await manager.HasStatusAsync(token, Statuses.Redeemed, context.CancellationToken)) { if (!context.Principal.HasTokenType(TokenTypeIdentifiers.RefreshToken) || !await IsReusableAsync(token)) { @@ -1255,7 +1226,7 @@ public static partial class OpenIddictServerHandlers try { - count = await _tokenManager.RevokeByAuthorizationIdAsync(context.AuthorizationId, context.CancellationToken); + count = await manager.RevokeByAuthorizationIdAsync(context.AuthorizationId, context.CancellationToken); } catch (Exception exception) when (!OpenIddictHelpers.IsFatal(exception)) @@ -1302,7 +1273,7 @@ public static partial class OpenIddictServerHandlers } // If the token is not marked as valid yet, return an authorization_pending error. - if (await _tokenManager.HasStatusAsync(token, Statuses.Inactive, context.CancellationToken)) + if (await manager.HasStatusAsync(token, Statuses.Inactive, context.CancellationToken)) { context.Logger.LogInformation(6003, SR.GetResourceString(SR.ID6003), context.TokenId); @@ -1315,7 +1286,7 @@ public static partial class OpenIddictServerHandlers } // If the token is marked as rejected, return an access_denied error. - if (await _tokenManager.HasStatusAsync(token, Statuses.Rejected, context.CancellationToken)) + if (await manager.HasStatusAsync(token, Statuses.Rejected, context.CancellationToken)) { context.Logger.LogInformation(6004, SR.GetResourceString(SR.ID6004), context.TokenId); @@ -1327,7 +1298,7 @@ public static partial class OpenIddictServerHandlers return; } - if (!await _tokenManager.HasStatusAsync(token, Statuses.Valid, context.CancellationToken)) + if (!await manager.HasStatusAsync(token, Statuses.Valid, context.CancellationToken)) { context.Logger.LogInformation(6005, SR.GetResourceString(SR.ID6005), context.TokenId); @@ -1367,7 +1338,7 @@ public static partial class OpenIddictServerHandlers return false; } - var date = await _tokenManager.GetRedemptionDateAsync(token, context.CancellationToken); + var date = await manager.GetRedemptionDateAsync(token, context.CancellationToken); if (date is null || context.Options.TimeProvider.GetUtcNow() < date + context.Options.RefreshTokenReuseLeeway) { @@ -1386,13 +1357,6 @@ public static partial class OpenIddictServerHandlers /// public sealed class ValidateAuthorizationEntry : IOpenIddictServerHandler { - private readonly IOpenIddictAuthorizationManager _authorizationManager; - - public ValidateAuthorizationEntry() => throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); - - public ValidateAuthorizationEntry(IOpenIddictAuthorizationManager authorizationManager) - => _authorizationManager = authorizationManager ?? throw new ArgumentNullException(nameof(authorizationManager)); - /// /// Gets the default descriptor definition assigned to this handler. /// @@ -1401,7 +1365,7 @@ public static partial class OpenIddictServerHandlers .AddFilter() .AddFilter() .AddFilter() - .UseScopedHandler() + .UseSingletonHandler() .SetOrder(ValidateTokenEntry.Descriptor.Order + 1_000) .SetType(OpenIddictServerHandlerType.BuiltIn) .Build(); @@ -1413,8 +1377,11 @@ public static partial class OpenIddictServerHandlers Debug.Assert(context.Principal is { Identity: ClaimsIdentity }, SR.GetResourceString(SR.ID4006)); Debug.Assert(!string.IsNullOrEmpty(context.AuthorizationId), SR.GetResourceString(SR.ID4018)); - var authorization = await _authorizationManager.FindByIdAsync(context.AuthorizationId, context.CancellationToken); - if (authorization is null || !await _authorizationManager.HasStatusAsync(authorization, Statuses.Valid, context.CancellationToken)) + var manager = context.ServiceProvider.GetService() + ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); + + var authorization = await manager.FindByIdAsync(context.AuthorizationId, context.CancellationToken); + if (authorization is null || !await manager.HasStatusAsync(authorization, Statuses.Valid, context.CancellationToken)) { context.Logger.LogInformation(6006, SR.GetResourceString(SR.ID6006), context.AuthorizationId); @@ -1498,19 +1465,6 @@ public static partial class OpenIddictServerHandlers /// public sealed class CreateTokenEntry : IOpenIddictServerHandler { - private readonly IOpenIddictApplicationManager _applicationManager; - private readonly IOpenIddictTokenManager _tokenManager; - - public CreateTokenEntry() => throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); - - public CreateTokenEntry( - IOpenIddictApplicationManager applicationManager, - IOpenIddictTokenManager tokenManager) - { - _applicationManager = applicationManager ?? throw new ArgumentNullException(nameof(applicationManager)); - _tokenManager = tokenManager ?? throw new ArgumentNullException(nameof(tokenManager)); - } - /// /// Gets the default descriptor definition assigned to this handler. /// @@ -1519,7 +1473,7 @@ public static partial class OpenIddictServerHandlers .AddFilter() .AddFilter() .AddFilter() - .UseScopedHandler() + .UseSingletonHandler() .SetOrder(AttachSecurityCredentials.Descriptor.Order + 1_000) .SetType(OpenIddictServerHandlerType.BuiltIn) .Build(); @@ -1562,16 +1516,22 @@ public static partial class OpenIddictServerHandlers // If the client application is known, associate it with the token. if (!string.IsNullOrEmpty(context.ClientId)) { - var application = await _applicationManager.FindByClientIdAsync(context.ClientId, context.CancellationToken) + var applicationManager = context.ServiceProvider.GetService() + ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); + + var application = await applicationManager.FindByClientIdAsync(context.ClientId, context.CancellationToken) ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0017)); - descriptor.ApplicationId = await _applicationManager.GetIdAsync(application, context.CancellationToken); + descriptor.ApplicationId = await applicationManager.GetIdAsync(application, context.CancellationToken); } - var token = await _tokenManager.CreateAsync(descriptor, context.CancellationToken) + var tokenManager = context.ServiceProvider.GetService() + ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); + + var token = await tokenManager.CreateAsync(descriptor, context.CancellationToken) ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0019)); - var identifier = await _tokenManager.GetIdAsync(token, context.CancellationToken); + var identifier = await tokenManager.GetIdAsync(token, context.CancellationToken); // Attach the token identifier to the principal so that it can be stored in the token payload. context.Principal.SetTokenId(identifier); @@ -1784,13 +1744,6 @@ public static partial class OpenIddictServerHandlers /// public sealed class AttachTokenPayload : IOpenIddictServerHandler { - private readonly IOpenIddictTokenManager _tokenManager; - - public AttachTokenPayload() => throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); - - public AttachTokenPayload(IOpenIddictTokenManager tokenManager) - => _tokenManager = tokenManager ?? throw new ArgumentNullException(nameof(tokenManager)); - /// /// Gets the default descriptor definition assigned to this handler. /// @@ -1799,7 +1752,7 @@ public static partial class OpenIddictServerHandlers .AddFilter() .AddFilter() .AddFilter() - .UseScopedHandler() + .UseSingletonHandler() .SetOrder(GenerateIdentityModelToken.Descriptor.Order + 1_000) .SetType(OpenIddictServerHandlerType.BuiltIn) .Build(); @@ -1815,11 +1768,14 @@ public static partial class OpenIddictServerHandlers throw new InvalidOperationException(SR.GetResourceString(SR.ID0009)); } - var token = await _tokenManager.FindByIdAsync(identifier, context.CancellationToken) + var manager = context.ServiceProvider.GetService() + ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); + + var token = await manager.FindByIdAsync(identifier, context.CancellationToken) ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0021)); var descriptor = new OpenIddictTokenDescriptor(); - await _tokenManager.PopulateAsync(descriptor, token, context.CancellationToken); + await manager.PopulateAsync(descriptor, token, context.CancellationToken); // Attach the generated token to the token entry. descriptor.Payload = context.Token; @@ -1839,7 +1795,7 @@ public static partial class OpenIddictServerHandlers // User codes are generally short. To help reduce the risks of collisions with // existing entries, a database check is performed here before updating the entry. - while (await _tokenManager.FindByReferenceIdAsync(descriptor.ReferenceId, context.CancellationToken) is not null); + while (await manager.FindByReferenceIdAsync(descriptor.ReferenceId, context.CancellationToken) is not null); } else @@ -1849,7 +1805,7 @@ public static partial class OpenIddictServerHandlers } } - await _tokenManager.UpdateAsync(token, descriptor, context.CancellationToken); + await manager.UpdateAsync(token, descriptor, context.CancellationToken); context.Logger.LogTrace(6014, SR.GetResourceString(SR.ID6014), context.Token, identifier, context.TokenType); diff --git a/src/OpenIddict.Server/OpenIddictServerHandlers.Revocation.cs b/src/OpenIddict.Server/OpenIddictServerHandlers.Revocation.cs index 446693c5..821a7082 100644 --- a/src/OpenIddict.Server/OpenIddictServerHandlers.Revocation.cs +++ b/src/OpenIddict.Server/OpenIddictServerHandlers.Revocation.cs @@ -7,6 +7,7 @@ using System.Collections.Immutable; using System.Diagnostics; using System.Security.Claims; +using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; namespace OpenIddict.Server; @@ -442,13 +443,6 @@ public static partial class OpenIddictServerHandlers /// public sealed class ValidateEndpointPermissions : IOpenIddictServerHandler { - private readonly IOpenIddictApplicationManager _applicationManager; - - public ValidateEndpointPermissions() => throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); - - public ValidateEndpointPermissions(IOpenIddictApplicationManager applicationManager) - => _applicationManager = applicationManager ?? throw new ArgumentNullException(nameof(applicationManager)); - /// /// Gets the default descriptor definition assigned to this handler. /// @@ -457,7 +451,7 @@ public static partial class OpenIddictServerHandlers .AddFilter() .AddFilter() .AddFilter() - .UseScopedHandler() + .UseSingletonHandler() .SetOrder(ValidateAuthentication.Descriptor.Order + 1_000) .SetType(OpenIddictServerHandlerType.BuiltIn) .Build(); @@ -469,11 +463,14 @@ public static partial class OpenIddictServerHandlers Debug.Assert(!string.IsNullOrEmpty(context.ClientId), SR.FormatID4000(Parameters.ClientId)); - var application = await _applicationManager.FindByClientIdAsync(context.ClientId, context.CancellationToken) + var manager = context.ServiceProvider.GetService() + ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); + + var application = await manager.FindByClientIdAsync(context.ClientId, context.CancellationToken) ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0032)); // Reject the request if the application is not allowed to use the revocation endpoint. - if (!await _applicationManager.HasPermissionAsync(application, Permissions.Endpoints.Revocation, context.CancellationToken)) + if (!await manager.HasPermissionAsync(application, Permissions.Endpoints.Revocation, context.CancellationToken)) { context.Logger.LogInformation(6116, SR.GetResourceString(SR.ID6116), context.ClientId); @@ -632,20 +629,13 @@ public static partial class OpenIddictServerHandlers /// public sealed class RevokeToken : IOpenIddictServerHandler { - private readonly IOpenIddictTokenManager _tokenManager; - - public RevokeToken() => throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); - - public RevokeToken(IOpenIddictTokenManager tokenManager) - => _tokenManager = tokenManager ?? throw new ArgumentNullException(nameof(tokenManager)); - /// /// Gets the default descriptor definition assigned to this handler. /// public static OpenIddictServerHandlerDescriptor Descriptor { get; } = OpenIddictServerHandlerDescriptor.CreateBuilder() .AddFilter() - .UseScopedHandler() + .UseSingletonHandler() .SetOrder(AttachPrincipal.Descriptor.Order + 1_000) .SetType(OpenIddictServerHandlerType.BuiltIn) .Build(); @@ -671,7 +661,10 @@ public static partial class OpenIddictServerHandlers return; } - var token = await _tokenManager.FindByIdAsync(identifier, context.CancellationToken); + var manager = context.ServiceProvider.GetService() + ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); + + var token = await manager.FindByIdAsync(identifier, context.CancellationToken); if (token is null) { context.Logger.LogInformation(6123, SR.GetResourceString(SR.ID6123), identifier); @@ -685,7 +678,7 @@ public static partial class OpenIddictServerHandlers } // Try to revoke the token. If an error occurs, return an error. - if (!await _tokenManager.TryRevokeAsync(token, context.CancellationToken)) + if (!await manager.TryRevokeAsync(token, context.CancellationToken)) { context.Reject( error: Errors.UnsupportedTokenType, diff --git a/src/OpenIddict.Server/OpenIddictServerHandlers.Session.cs b/src/OpenIddict.Server/OpenIddictServerHandlers.Session.cs index 57356126..392bf41b 100644 --- a/src/OpenIddict.Server/OpenIddictServerHandlers.Session.cs +++ b/src/OpenIddict.Server/OpenIddictServerHandlers.Session.cs @@ -11,7 +11,6 @@ using System.Security.Claims; using System.Text.Json; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Options; namespace OpenIddict.Server; @@ -555,13 +554,6 @@ public static partial class OpenIddictServerHandlers /// public sealed class ValidateClientPostLogoutRedirectUri : IOpenIddictServerHandler { - private readonly IOpenIddictApplicationManager _applicationManager; - - public ValidateClientPostLogoutRedirectUri() => throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); - - public ValidateClientPostLogoutRedirectUri(IOpenIddictApplicationManager applicationManager) - => _applicationManager = applicationManager ?? throw new ArgumentNullException(nameof(applicationManager)); - /// /// Gets the default descriptor definition assigned to this handler. /// @@ -569,7 +561,7 @@ public static partial class OpenIddictServerHandlers = OpenIddictServerHandlerDescriptor.CreateBuilder() .AddFilter() .AddFilter() - .UseScopedHandler() + .UseSingletonHandler() .SetOrder(RestorePushedAuthorizationRequestParameters.Descriptor.Order + 1_000) .SetType(OpenIddictServerHandlerType.BuiltIn) .Build(); @@ -597,12 +589,15 @@ public static partial class OpenIddictServerHandlers // // Since the first method is more efficient, it's always used if a client_is was specified. + var manager = context.ServiceProvider.GetService() + ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); + if (!string.IsNullOrEmpty(context.ClientId)) { - var application = await _applicationManager.FindByClientIdAsync(context.ClientId, context.CancellationToken) + var application = await manager.FindByClientIdAsync(context.ClientId, context.CancellationToken) ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0032)); - if (!await _applicationManager.ValidatePostLogoutRedirectUriAsync(application, context.PostLogoutRedirectUri, context.CancellationToken)) + if (!await manager.ValidatePostLogoutRedirectUriAsync(application, context.PostLogoutRedirectUri, context.CancellationToken)) { context.Logger.LogInformation(6128, SR.GetResourceString(SR.ID6128), context.PostLogoutRedirectUri); @@ -634,17 +629,17 @@ public static partial class OpenIddictServerHandlers // To be considered valid, a post_logout_redirect_uri must correspond to an existing client application // that was granted the ept:logout permission, unless endpoint permissions checking was explicitly disabled. - await foreach (var application in _applicationManager.FindByPostLogoutRedirectUriAsync(uri, context.CancellationToken)) + await foreach (var application in manager.FindByPostLogoutRedirectUriAsync(uri, context.CancellationToken)) { // Note: the legacy "ept:logout" permission is still allowed for backward compatibility. if (!context.Options.IgnoreEndpointPermissions && - !await _applicationManager.HasPermissionAsync(application, Permissions.Endpoints.EndSession, context.CancellationToken) && - !await _applicationManager.HasPermissionAsync(application, "ept:logout", context.CancellationToken)) + !await manager.HasPermissionAsync(application, Permissions.Endpoints.EndSession, context.CancellationToken) && + !await manager.HasPermissionAsync(application, "ept:logout", context.CancellationToken)) { continue; } - if (await _applicationManager.ValidatePostLogoutRedirectUriAsync(application, uri, context.CancellationToken)) + if (await manager.ValidatePostLogoutRedirectUriAsync(application, uri, context.CancellationToken)) { return true; } @@ -666,19 +661,19 @@ public static partial class OpenIddictServerHandlers (string.Equals(value.Scheme, Uri.UriSchemeHttp, StringComparison.OrdinalIgnoreCase) || string.Equals(value.Scheme, Uri.UriSchemeHttps, StringComparison.OrdinalIgnoreCase))) { - await foreach (var application in _applicationManager.FindByPostLogoutRedirectUriAsync( + await foreach (var application in manager.FindByPostLogoutRedirectUriAsync( uri: new UriBuilder(value) { Port = -1 }.Uri.AbsoluteUri, context.CancellationToken)) { // Note: the legacy "ept:logout" permission is still allowed for backward compatibility. if (!context.Options.IgnoreEndpointPermissions && - !await _applicationManager.HasPermissionAsync(application, Permissions.Endpoints.EndSession, context.CancellationToken) && - !await _applicationManager.HasPermissionAsync(application, "ept:logout", context.CancellationToken)) + !await manager.HasPermissionAsync(application, Permissions.Endpoints.EndSession, context.CancellationToken) && + !await manager.HasPermissionAsync(application, "ept:logout", context.CancellationToken)) { continue; } - if (await _applicationManager.HasApplicationTypeAsync(application, ApplicationTypes.Native, context.CancellationToken) && - await _applicationManager.ValidatePostLogoutRedirectUriAsync(application, uri, context.CancellationToken)) + if (await manager.HasApplicationTypeAsync(application, ApplicationTypes.Native, context.CancellationToken) && + await manager.ValidatePostLogoutRedirectUriAsync(application, uri, context.CancellationToken)) { return true; } @@ -696,13 +691,6 @@ public static partial class OpenIddictServerHandlers /// public sealed class ValidateEndpointPermissions : IOpenIddictServerHandler { - private readonly IOpenIddictApplicationManager _applicationManager; - - public ValidateEndpointPermissions() => throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); - - public ValidateEndpointPermissions(IOpenIddictApplicationManager applicationManager) - => _applicationManager = applicationManager ?? throw new ArgumentNullException(nameof(applicationManager)); - /// /// Gets the default descriptor definition assigned to this handler. /// @@ -717,7 +705,7 @@ public static partial class OpenIddictServerHandlers // Note: if only post_logout_redirect_uri was specified, client permissions are expected to be // enforced by the ValidateClientPostLogoutRedirectUri handler when finding matching clients. .AddFilter() - .UseScopedHandler() + .UseSingletonHandler() .SetOrder(ValidateClientPostLogoutRedirectUri.Descriptor.Order + 1_000) .SetType(OpenIddictServerHandlerType.BuiltIn) .Build(); @@ -729,14 +717,17 @@ public static partial class OpenIddictServerHandlers Debug.Assert(!string.IsNullOrEmpty(context.ClientId), SR.FormatID4000(Parameters.ClientId)); - var application = await _applicationManager.FindByClientIdAsync(context.ClientId, context.CancellationToken) + var manager = context.ServiceProvider.GetService() + ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); + + var application = await manager.FindByClientIdAsync(context.ClientId, context.CancellationToken) ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0032)); // Reject the request if the application is not allowed to use the end session endpoint. // // Note: the legacy "ept:logout" permission is still allowed for backward compatibility. - if (!await _applicationManager.HasPermissionAsync(application, Permissions.Endpoints.EndSession, context.CancellationToken) && - !await _applicationManager.HasPermissionAsync(application, "ept:logout", context.CancellationToken)) + if (!await manager.HasPermissionAsync(application, Permissions.Endpoints.EndSession, context.CancellationToken) && + !await manager.HasPermissionAsync(application, "ept:logout", context.CancellationToken)) { context.Logger.LogInformation(6048, SR.GetResourceString(SR.ID6048), context.ClientId); @@ -756,27 +747,12 @@ public static partial class OpenIddictServerHandlers /// public sealed class ValidateAuthorizedParty : IOpenIddictServerHandler { - private readonly IOpenIddictApplicationManager? _applicationManager; - - public ValidateAuthorizedParty(IOpenIddictApplicationManager? applicationManager = null) - => _applicationManager = applicationManager; - /// /// Gets the default descriptor definition assigned to this handler. /// public static OpenIddictServerHandlerDescriptor Descriptor { get; } = OpenIddictServerHandlerDescriptor.CreateBuilder() - .UseScopedHandler(static provider => - { - // Note: the application manager is only resolved if the degraded mode was not enabled to ensure - // invalid core configuration exceptions are not thrown even if the managers were registered. - var options = provider.GetRequiredService>().CurrentValue; - - return options.EnableDegradedMode - ? new ValidateAuthorizedParty() - : new ValidateAuthorizedParty(provider.GetService() - ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0016))); - }) + .UseSingletonHandler() .SetOrder(ValidateEndpointPermissions.Descriptor.Order + 1_000) .SetType(OpenIddictServerHandlerType.BuiltIn) .Build(); @@ -826,10 +802,8 @@ public static partial class OpenIddictServerHandlers if (!context.Options.EnableDegradedMode && !string.IsNullOrEmpty(context.PostLogoutRedirectUri)) { - if (_applicationManager is null) - { - throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); - } + var manager = context.ServiceProvider.GetService() + ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); if (!await ValidateAuthorizedPartyAsync(context.IdentityTokenHintPrincipal, context.PostLogoutRedirectUri, context.CancellationToken)) @@ -845,41 +819,41 @@ public static partial class OpenIddictServerHandlers } return; - } - async ValueTask ValidateAuthorizedPartyAsync(ClaimsPrincipal principal, - [StringSyntax(StringSyntaxAttribute.Uri)] string uri, CancellationToken cancellationToken) - { - // To be considered valid, the specified post_logout_redirect_uri must - // be considered valid for one of the listed audiences/presenters. + async ValueTask ValidateAuthorizedPartyAsync(ClaimsPrincipal principal, + [StringSyntax(StringSyntaxAttribute.Uri)] string uri, CancellationToken cancellationToken) + { + // To be considered valid, the specified post_logout_redirect_uri must + // be considered valid for one of the listed audiences/presenters. - var identifiers = new HashSet(StringComparer.Ordinal); - identifiers.UnionWith(principal.GetAudiences()); - identifiers.UnionWith(principal.GetPresenters()); + var identifiers = new HashSet(StringComparer.Ordinal); + identifiers.UnionWith(principal.GetAudiences()); + identifiers.UnionWith(principal.GetPresenters()); - foreach (var identifier in identifiers) - { - var application = await _applicationManager.FindByClientIdAsync(identifier, cancellationToken); - if (application is null) + foreach (var identifier in identifiers) { - continue; - } + var application = await manager.FindByClientIdAsync(identifier, cancellationToken); + if (application is null) + { + continue; + } - // Note: the legacy "ept:logout" permission is still allowed for backward compatibility. - if (!context.Options.IgnoreEndpointPermissions && - !await _applicationManager.HasPermissionAsync(application, Permissions.Endpoints.EndSession, cancellationToken) && - !await _applicationManager.HasPermissionAsync(application, "ept:logout", cancellationToken)) - { - continue; - } + // Note: the legacy "ept:logout" permission is still allowed for backward compatibility. + if (!context.Options.IgnoreEndpointPermissions && + !await manager.HasPermissionAsync(application, Permissions.Endpoints.EndSession, cancellationToken) && + !await manager.HasPermissionAsync(application, "ept:logout", cancellationToken)) + { + continue; + } - if (await _applicationManager.ValidatePostLogoutRedirectUriAsync(application, uri, cancellationToken)) - { - return true; + if (await manager.ValidatePostLogoutRedirectUriAsync(application, uri, cancellationToken)) + { + return true; + } } - } - return false; + return false; + } } } } diff --git a/src/OpenIddict.Server/OpenIddictServerHandlers.cs b/src/OpenIddict.Server/OpenIddictServerHandlers.cs index f1399690..4cd5fc28 100644 --- a/src/OpenIddict.Server/OpenIddictServerHandlers.cs +++ b/src/OpenIddict.Server/OpenIddictServerHandlers.cs @@ -962,27 +962,12 @@ public static partial class OpenIddictServerHandlers /// public sealed class ValidateClientId : IOpenIddictServerHandler { - private readonly IOpenIddictApplicationManager? _applicationManager; - - public ValidateClientId(IOpenIddictApplicationManager? applicationManager = null) - => _applicationManager = applicationManager; - /// /// Gets the default descriptor definition assigned to this handler. /// public static OpenIddictServerHandlerDescriptor Descriptor { get; } = OpenIddictServerHandlerDescriptor.CreateBuilder() - .UseScopedHandler(static provider => - { - // Note: the application manager is only resolved if the degraded mode was not enabled to ensure - // invalid core configuration exceptions are not thrown even if the managers were registered. - var options = provider.GetRequiredService>().CurrentValue; - - return options.EnableDegradedMode - ? new ValidateClientId() - : new ValidateClientId(provider.GetService() - ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0016))); - }) + .UseSingletonHandler() .SetOrder(ValidateClientAssertionAudience.Descriptor.Order + 1_000) .SetType(OpenIddictServerHandlerType.BuiltIn) .Build(); @@ -1039,14 +1024,12 @@ public static partial class OpenIddictServerHandlers if (!context.Options.EnableDegradedMode) { - if (_applicationManager is null) - { - throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); - } + var manager = context.ServiceProvider.GetService() + ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); // Retrieve the application details corresponding to the requested client_id. // If no entity can be found, this likely indicates that the client_id is invalid. - var application = await _applicationManager.FindByClientIdAsync(context.ClientId, context.CancellationToken); + var application = await manager.FindByClientIdAsync(context.ClientId, context.CancellationToken); if (application is null) { context.Logger.LogInformation(6221, SR.GetResourceString(SR.ID6221), context.ClientId); @@ -1078,13 +1061,6 @@ public static partial class OpenIddictServerHandlers /// public sealed class ValidateClientType : IOpenIddictServerHandler { - private readonly IOpenIddictApplicationManager _applicationManager; - - public ValidateClientType() => throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); - - public ValidateClientType(IOpenIddictApplicationManager applicationManager) - => _applicationManager = applicationManager ?? throw new ArgumentNullException(nameof(applicationManager)); - /// /// Gets the default descriptor definition assigned to this handler. /// @@ -1092,7 +1068,7 @@ public static partial class OpenIddictServerHandlers = OpenIddictServerHandlerDescriptor.CreateBuilder() .AddFilter() .AddFilter() - .UseScopedHandler() + .UseSingletonHandler() .SetOrder(ValidateClientId.Descriptor.Order + 1_000) .SetType(OpenIddictServerHandlerType.BuiltIn) .Build(); @@ -1113,10 +1089,13 @@ public static partial class OpenIddictServerHandlers return; } - var application = await _applicationManager.FindByClientIdAsync(context.ClientId, context.CancellationToken) + var manager = context.ServiceProvider.GetService() + ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); + + var application = await manager.FindByClientIdAsync(context.ClientId, context.CancellationToken) ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0032)); - if (await _applicationManager.HasClientTypeAsync(application, ClientTypes.Public, context.CancellationToken)) + if (await manager.HasClientTypeAsync(application, ClientTypes.Public, context.CancellationToken)) { // Reject grant_type=client_credentials token requests if the application is a public client. if (context.EndpointType is OpenIddictServerEndpointType.Token && @@ -1187,13 +1166,6 @@ public static partial class OpenIddictServerHandlers /// public sealed class ValidateClientSecret : IOpenIddictServerHandler { - private readonly IOpenIddictApplicationManager _applicationManager; - - public ValidateClientSecret() => throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); - - public ValidateClientSecret(IOpenIddictApplicationManager applicationManager) - => _applicationManager = applicationManager ?? throw new ArgumentNullException(nameof(applicationManager)); - /// /// Gets the default descriptor definition assigned to this handler. /// @@ -1202,7 +1174,7 @@ public static partial class OpenIddictServerHandlers .AddFilter() .AddFilter() .AddFilter() - .UseScopedHandler() + .UseSingletonHandler() .SetOrder(ValidateClientType.Descriptor.Order + 1_000) .SetType(OpenIddictServerHandlerType.BuiltIn) .Build(); @@ -1224,16 +1196,19 @@ public static partial class OpenIddictServerHandlers return; } - var application = await _applicationManager.FindByClientIdAsync(context.ClientId, context.CancellationToken) + var manager = context.ServiceProvider.GetService() + ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); + + var application = await manager.FindByClientIdAsync(context.ClientId, context.CancellationToken) ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0032)); // If the application is a public client, don't validate the client secret. - if (await _applicationManager.HasClientTypeAsync(application, ClientTypes.Public, context.CancellationToken)) + if (await manager.HasClientTypeAsync(application, ClientTypes.Public, context.CancellationToken)) { return; } - if (!await _applicationManager.ValidateClientSecretAsync(application, context.ClientSecret, context.CancellationToken)) + if (!await manager.ValidateClientSecretAsync(application, context.ClientSecret, context.CancellationToken)) { context.Logger.LogInformation(6225, SR.GetResourceString(SR.ID6225), context.ClientId); @@ -1253,31 +1228,13 @@ public static partial class OpenIddictServerHandlers /// public sealed class ValidateClientCertificate : IOpenIddictServerHandler { - private readonly IOpenIddictApplicationManager? _applicationManager; - - public ValidateClientCertificate() { } - - public ValidateClientCertificate(IOpenIddictApplicationManager applicationManager) - => _applicationManager = applicationManager ?? throw new ArgumentNullException(nameof(applicationManager)); - /// /// Gets the default descriptor definition assigned to this handler. /// public static OpenIddictServerHandlerDescriptor Descriptor { get; } = OpenIddictServerHandlerDescriptor.CreateBuilder() .AddFilter() - .UseScopedHandler(static provider => - { - // Note: the application manager is only resolved if the degraded mode was not enabled to ensure - // invalid core configuration exceptions are not thrown even if the managers were registered. - var options = provider.GetRequiredService>().CurrentValue; - - return options.EnableDegradedMode - ? new ValidateClientCertificate() - : new ValidateClientCertificate(provider.GetService() - ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0016))); - }) - .UseScopedHandler() + .UseSingletonHandler() .SetOrder(ValidateClientSecret.Descriptor.Order + 1_000) .SetType(OpenIddictServerHandlerType.BuiltIn) .Build(); @@ -1393,12 +1350,10 @@ public static partial class OpenIddictServerHandlers return; } - if (_applicationManager is null) - { - throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); - } + var manager = context.ServiceProvider.GetService() + ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); - var application = await _applicationManager.FindByClientIdAsync(context.ClientId, context.CancellationToken) + var application = await manager.FindByClientIdAsync(context.ClientId, context.CancellationToken) ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0032)); // Note: to avoid building and introspecting a X.509 certificate chain and reduce the cost @@ -1420,7 +1375,7 @@ public static partial class OpenIddictServerHandlers return; } - if (await _applicationManager.GetSelfSignedTlsClientAuthenticationPolicyAsync( + if (await manager.GetSelfSignedTlsClientAuthenticationPolicyAsync( application, context.Options.SelfSignedTlsClientAuthenticationPolicy, context.CancellationToken) is not X509ChainPolicy policy) { context.Logger.LogInformation(6283, SR.GetResourceString(SR.ID6283), context.ClientId); @@ -1442,7 +1397,7 @@ public static partial class OpenIddictServerHandlers // To allow validating such certificates, the chain policy is amended to consider the specified // self-signed certificate as a trusted root and basically disable chain validation while still // validating the other aspects of the certificate (e.g expiration date, key usage, etc). - if (await _applicationManager.HasClientTypeAsync(application, ClientTypes.Public, context.CancellationToken)) + if (await manager.HasClientTypeAsync(application, ClientTypes.Public, context.CancellationToken)) { // Always clone the X.509 chain policy to ensure the original instance is never mutated. policy = policy.Clone(); @@ -1454,7 +1409,7 @@ public static partial class OpenIddictServerHandlers #endif } - if (!await _applicationManager.ValidateSelfSignedTlsClientCertificateAsync( + if (!await manager.ValidateSelfSignedTlsClientCertificateAsync( application, context.Transaction.RemoteCertificate, policy, context.CancellationToken)) { context.Logger.LogInformation(6283, SR.GetResourceString(SR.ID6283), context.ClientId); @@ -1480,9 +1435,9 @@ public static partial class OpenIddictServerHandlers return; } - if (await _applicationManager.GetPublicKeyInfrastructureTlsClientAuthenticationPolicyAsync( + if (await manager.GetPublicKeyInfrastructureTlsClientAuthenticationPolicyAsync( application, context.Options.PublicKeyInfrastructureTlsClientAuthenticationPolicy, context.CancellationToken) is not X509ChainPolicy policy || - !await _applicationManager.ValidatePublicKeyInfrastructureTlsClientCertificateAsync( + !await manager.ValidatePublicKeyInfrastructureTlsClientCertificateAsync( application, context.Transaction.RemoteCertificate, policy, context.CancellationToken)) { context.Logger.LogInformation(6284, SR.GetResourceString(SR.ID6284), context.ClientId); @@ -2621,13 +2576,6 @@ public static partial class OpenIddictServerHandlers /// public sealed class RejectDeviceCodeEntry : IOpenIddictServerHandler { - private readonly IOpenIddictTokenManager _tokenManager; - - public RejectDeviceCodeEntry() => throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); - - public RejectDeviceCodeEntry(IOpenIddictTokenManager tokenManager) - => _tokenManager = tokenManager ?? throw new ArgumentNullException(nameof(tokenManager)); - /// /// Gets the default descriptor definition assigned to this handler. /// @@ -2635,7 +2583,7 @@ public static partial class OpenIddictServerHandlers = OpenIddictServerHandlerDescriptor.CreateBuilder() .AddFilter() .AddFilter() - .UseScopedHandler() + .UseSingletonHandler() .SetOrder(AttachDefaultChallengeError.Descriptor.Order + 1_000) .SetType(OpenIddictServerHandlerType.BuiltIn) .Build(); @@ -2663,10 +2611,13 @@ public static partial class OpenIddictServerHandlers throw new InvalidOperationException(SR.GetResourceString(SR.ID0008)); } - var token = await _tokenManager.FindByIdAsync(identifier, context.CancellationToken); + var manager = context.ServiceProvider.GetService() + ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); + + var token = await manager.FindByIdAsync(identifier, context.CancellationToken); if (token is not null) { - await _tokenManager.TryRejectAsync(token, context.CancellationToken); + await manager.TryRejectAsync(token, context.CancellationToken); } } } @@ -2677,13 +2628,6 @@ public static partial class OpenIddictServerHandlers /// public sealed class RejectUserCodeEntry : IOpenIddictServerHandler { - private readonly IOpenIddictTokenManager _tokenManager; - - public RejectUserCodeEntry() => throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); - - public RejectUserCodeEntry(IOpenIddictTokenManager tokenManager) - => _tokenManager = tokenManager ?? throw new ArgumentNullException(nameof(tokenManager)); - /// /// Gets the default descriptor definition assigned to this handler. /// @@ -2691,7 +2635,7 @@ public static partial class OpenIddictServerHandlers = OpenIddictServerHandlerDescriptor.CreateBuilder() .AddFilter() .AddFilter() - .UseScopedHandler() + .UseSingletonHandler() .SetOrder(RejectDeviceCodeEntry.Descriptor.Order + 1_000) .SetType(OpenIddictServerHandlerType.BuiltIn) .Build(); @@ -2719,10 +2663,13 @@ public static partial class OpenIddictServerHandlers throw new InvalidOperationException(SR.GetResourceString(SR.ID0009)); } - var token = await _tokenManager.FindByIdAsync(identifier, context.CancellationToken); + var manager = context.ServiceProvider.GetService() + ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); + + var token = await manager.FindByIdAsync(identifier, context.CancellationToken); if (token is not null) { - await _tokenManager.TryRejectAsync(token, context.CancellationToken); + await manager.TryRejectAsync(token, context.CancellationToken); } } } @@ -2913,13 +2860,6 @@ public static partial class OpenIddictServerHandlers /// public sealed class RedeemTokenEntry : IOpenIddictServerHandler { - private readonly IOpenIddictTokenManager _tokenManager; - - public RedeemTokenEntry() => throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); - - public RedeemTokenEntry(IOpenIddictTokenManager tokenManager) - => _tokenManager = tokenManager ?? throw new ArgumentNullException(nameof(tokenManager)); - /// /// Gets the default descriptor definition assigned to this handler. /// @@ -2927,7 +2867,7 @@ public static partial class OpenIddictServerHandlers = OpenIddictServerHandlerDescriptor.CreateBuilder() .AddFilter() .AddFilter() - .UseScopedHandler() + .UseSingletonHandler() // Note: this handler is deliberately executed early in the pipeline to ensure // that the token database entry is always marked as redeemed even if the sign-in // demand is rejected later in the pipeline (e.g because an error was returned). @@ -2988,7 +2928,10 @@ public static partial class OpenIddictServerHandlers return; } - var token = await _tokenManager.FindByIdAsync(identifier, context.CancellationToken); + var manager = context.ServiceProvider.GetService() + ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); + + var token = await manager.FindByIdAsync(identifier, context.CancellationToken); if (token is null) { return; @@ -2998,10 +2941,10 @@ public static partial class OpenIddictServerHandlers // errors returned while trying to mark the entry as redeemed (that may be caused by concurrent requests). if (context.EndpointType is OpenIddictServerEndpointType.Token && context.Request.IsRefreshTokenGrantType()) { - await _tokenManager.TryRedeemAsync(token, context.CancellationToken); + await manager.TryRedeemAsync(token, context.CancellationToken); } - else if (!await _tokenManager.TryRedeemAsync(token, context.CancellationToken)) + else if (!await manager.TryRedeemAsync(token, context.CancellationToken)) { context.Reject( error: Errors.InvalidToken, @@ -3423,19 +3366,6 @@ public static partial class OpenIddictServerHandlers /// public sealed class AttachAuthorization : IOpenIddictServerHandler { - private readonly IOpenIddictApplicationManager _applicationManager; - private readonly IOpenIddictAuthorizationManager _authorizationManager; - - public AttachAuthorization() => throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); - - public AttachAuthorization( - IOpenIddictApplicationManager applicationManager, - IOpenIddictAuthorizationManager authorizationManager) - { - _applicationManager = applicationManager ?? throw new ArgumentNullException(nameof(applicationManager)); - _authorizationManager = authorizationManager ?? throw new ArgumentNullException(nameof(authorizationManager)); - } - /// /// Gets the default descriptor definition assigned to this handler. /// @@ -3443,7 +3373,7 @@ public static partial class OpenIddictServerHandlers = OpenIddictServerHandlerDescriptor.CreateBuilder() .AddFilter() .AddFilter() - .UseScopedHandler() + .UseSingletonHandler() .SetOrder(EvaluateGeneratedTokens.Descriptor.Order + 1_000) .SetType(OpenIddictServerHandlerType.BuiltIn) .Build(); @@ -3483,16 +3413,22 @@ public static partial class OpenIddictServerHandlers // If the client application is known, associate it to the authorization. if (!string.IsNullOrEmpty(context.Request.ClientId)) { - var application = await _applicationManager.FindByClientIdAsync(context.Request.ClientId, context.CancellationToken) + var applicationManager = context.ServiceProvider.GetService() + ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); + + var application = await applicationManager.FindByClientIdAsync(context.Request.ClientId, context.CancellationToken) ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0017)); - descriptor.ApplicationId = await _applicationManager.GetIdAsync(application, context.CancellationToken); + descriptor.ApplicationId = await applicationManager.GetIdAsync(application, context.CancellationToken); } - var authorization = await _authorizationManager.CreateAsync(descriptor, context.CancellationToken) + var authorizationManager = context.ServiceProvider.GetService() + ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); + + var authorization = await authorizationManager.CreateAsync(descriptor, context.CancellationToken) ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0018)); - var identifier = await _authorizationManager.GetIdAsync(authorization, context.CancellationToken); + var identifier = await authorizationManager.GetIdAsync(authorization, context.CancellationToken); if (string.IsNullOrEmpty(context.Request.ClientId)) { @@ -3516,28 +3452,13 @@ public static partial class OpenIddictServerHandlers /// public sealed class PrepareAccessTokenPrincipal : IOpenIddictServerHandler { - private readonly IOpenIddictApplicationManager? _applicationManager; - - public PrepareAccessTokenPrincipal(IOpenIddictApplicationManager? applicationManager = null) - => _applicationManager = applicationManager; - /// /// Gets the default descriptor definition assigned to this handler. /// public static OpenIddictServerHandlerDescriptor Descriptor { get; } = OpenIddictServerHandlerDescriptor.CreateBuilder() .AddFilter() - .UseScopedHandler(static provider => - { - // Note: the application manager is only resolved if the degraded mode was not enabled to ensure - // invalid core configuration exceptions are not thrown even if the managers were registered. - var options = provider.GetRequiredService>().CurrentValue; - - return options.EnableDegradedMode - ? new PrepareAccessTokenPrincipal() - : new PrepareAccessTokenPrincipal(provider.GetService() - ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0016))); - }) + .UseSingletonHandler() .SetOrder(AttachAuthorization.Descriptor.Order + 1_000) .SetType(OpenIddictServerHandlerType.BuiltIn) .Build(); @@ -3606,15 +3527,13 @@ public static partial class OpenIddictServerHandlers // If the client to which the token is returned is known, use the attached setting if available. if (lifetime is null && !context.Options.EnableDegradedMode && !string.IsNullOrEmpty(context.ClientId)) { - if (_applicationManager is null) - { - throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); - } + var manager = context.ServiceProvider.GetService() + ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); - var application = await _applicationManager.FindByClientIdAsync(context.ClientId, context.CancellationToken) + var application = await manager.FindByClientIdAsync(context.ClientId, context.CancellationToken) ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0017)); - var settings = await _applicationManager.GetSettingsAsync(application, context.CancellationToken); + var settings = await manager.GetSettingsAsync(application, context.CancellationToken); if (settings.TryGetValue(Settings.TokenLifetimes.AccessToken, out string? setting) && TimeSpan.TryParse(setting, CultureInfo.InvariantCulture, out var value)) { @@ -3680,28 +3599,13 @@ public static partial class OpenIddictServerHandlers /// public sealed class PrepareAuthorizationCodePrincipal : IOpenIddictServerHandler { - private readonly IOpenIddictApplicationManager? _applicationManager; - - public PrepareAuthorizationCodePrincipal(IOpenIddictApplicationManager? applicationManager = null) - => _applicationManager = applicationManager; - /// /// Gets the default descriptor definition assigned to this handler. /// public static OpenIddictServerHandlerDescriptor Descriptor { get; } = OpenIddictServerHandlerDescriptor.CreateBuilder() .AddFilter() - .UseScopedHandler(static provider => - { - // Note: the application manager is only resolved if the degraded mode was not enabled to ensure - // invalid core configuration exceptions are not thrown even if the managers were registered. - var options = provider.GetRequiredService>().CurrentValue; - - return options.EnableDegradedMode - ? new PrepareAuthorizationCodePrincipal() - : new PrepareAuthorizationCodePrincipal(provider.GetService() - ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0016))); - }) + .UseSingletonHandler() .SetOrder(PrepareAccessTokenPrincipal.Descriptor.Order + 1_000) .SetType(OpenIddictServerHandlerType.BuiltIn) .Build(); @@ -3740,15 +3644,13 @@ public static partial class OpenIddictServerHandlers // If the client to which the token is returned is known, use the attached setting if available. if (lifetime is null && !context.Options.EnableDegradedMode && !string.IsNullOrEmpty(context.ClientId)) { - if (_applicationManager is null) - { - throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); - } + var manager = context.ServiceProvider.GetService() + ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); - var application = await _applicationManager.FindByClientIdAsync(context.ClientId, context.CancellationToken) + var application = await manager.FindByClientIdAsync(context.ClientId, context.CancellationToken) ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0017)); - var settings = await _applicationManager.GetSettingsAsync(application, context.CancellationToken); + var settings = await manager.GetSettingsAsync(application, context.CancellationToken); if (settings.TryGetValue(Settings.TokenLifetimes.AuthorizationCode, out string? setting) && TimeSpan.TryParse(setting, CultureInfo.InvariantCulture, out var value)) { @@ -3804,28 +3706,13 @@ public static partial class OpenIddictServerHandlers /// public sealed class PrepareDeviceCodePrincipal : IOpenIddictServerHandler { - private readonly IOpenIddictApplicationManager? _applicationManager; - - public PrepareDeviceCodePrincipal(IOpenIddictApplicationManager? applicationManager = null) - => _applicationManager = applicationManager; - /// /// Gets the default descriptor definition assigned to this handler. /// public static OpenIddictServerHandlerDescriptor Descriptor { get; } = OpenIddictServerHandlerDescriptor.CreateBuilder() .AddFilter() - .UseScopedHandler(static provider => - { - // Note: the application manager is only resolved if the degraded mode was not enabled to ensure - // invalid core configuration exceptions are not thrown even if the managers were registered. - var options = provider.GetRequiredService>().CurrentValue; - - return options.EnableDegradedMode - ? new PrepareDeviceCodePrincipal() - : new PrepareDeviceCodePrincipal(provider.GetService() - ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0016))); - }) + .UseSingletonHandler() .SetOrder(PrepareAuthorizationCodePrincipal.Descriptor.Order + 1_000) .SetType(OpenIddictServerHandlerType.BuiltIn) .Build(); @@ -3864,15 +3751,13 @@ public static partial class OpenIddictServerHandlers // If the client to which the token is returned is known, use the attached setting if available. if (lifetime is null && !context.Options.EnableDegradedMode && !string.IsNullOrEmpty(context.ClientId)) { - if (_applicationManager is null) - { - throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); - } + var manager = context.ServiceProvider.GetService() + ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); - var application = await _applicationManager.FindByClientIdAsync(context.ClientId, context.CancellationToken) + var application = await manager.FindByClientIdAsync(context.ClientId, context.CancellationToken) ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0017)); - var settings = await _applicationManager.GetSettingsAsync(application, context.CancellationToken); + var settings = await manager.GetSettingsAsync(application, context.CancellationToken); if (settings.TryGetValue(Settings.TokenLifetimes.DeviceCode, out string? setting) && TimeSpan.TryParse(setting, CultureInfo.InvariantCulture, out var value)) { @@ -3914,28 +3799,13 @@ public static partial class OpenIddictServerHandlers /// public sealed class PrepareIssuedTokenPrincipal : IOpenIddictServerHandler { - private readonly IOpenIddictApplicationManager? _applicationManager; - - public PrepareIssuedTokenPrincipal(IOpenIddictApplicationManager? applicationManager = null) - => _applicationManager = applicationManager; - /// /// Gets the default descriptor definition assigned to this handler. /// public static OpenIddictServerHandlerDescriptor Descriptor { get; } = OpenIddictServerHandlerDescriptor.CreateBuilder() .AddFilter() - .UseScopedHandler(static provider => - { - // Note: the application manager is only resolved if the degraded mode was not enabled to ensure - // invalid core configuration exceptions are not thrown even if the managers were registered. - var options = provider.GetRequiredService>().CurrentValue; - - return options.EnableDegradedMode - ? new PrepareIssuedTokenPrincipal() - : new PrepareIssuedTokenPrincipal(provider.GetService() - ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0016))); - }) + .UseSingletonHandler() .SetOrder(PrepareDeviceCodePrincipal.Descriptor.Order + 1_000) .SetType(OpenIddictServerHandlerType.BuiltIn) .Build(); @@ -4082,12 +3952,10 @@ public static partial class OpenIddictServerHandlers // If the client to which the token is returned is known, use the attached setting if available. if (lifetime is null && !context.Options.EnableDegradedMode && !string.IsNullOrEmpty(context.ClientId)) { - if (_applicationManager is null) - { - throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); - } + var manager = context.ServiceProvider.GetService() + ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); - var application = await _applicationManager.FindByClientIdAsync(context.ClientId, context.CancellationToken) + var application = await manager.FindByClientIdAsync(context.ClientId, context.CancellationToken) ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0017)); var name = context.IssuedTokenType switch @@ -4099,7 +3967,7 @@ public static partial class OpenIddictServerHandlers _ => Settings.TokenLifetimes.IssuedToken }; - var settings = await _applicationManager.GetSettingsAsync(application, context.CancellationToken); + var settings = await manager.GetSettingsAsync(application, context.CancellationToken); if (settings.TryGetValue(name, out string? setting) && TimeSpan.TryParse(setting, CultureInfo.InvariantCulture, out var value)) { @@ -4176,12 +4044,10 @@ public static partial class OpenIddictServerHandlers else { - if (_applicationManager is null) - { - throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); - } + var manager = context.ServiceProvider.GetService() + ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); - var application = await _applicationManager.FindByClientIdAsync(context.ClientId, context.CancellationToken) + var application = await manager.FindByClientIdAsync(context.ClientId, context.CancellationToken) ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0017)); // Note: refresh tokens are only bound to the provided certificate when the client @@ -4189,7 +4055,7 @@ public static partial class OpenIddictServerHandlers // are already sender-constrained via standard client authentication, which is more // flexible than certificate-based token binding, as rotating client credentials is // easier in that case (specially when using PKI-based mTLS client authentication). - if (await _applicationManager.HasClientTypeAsync(application, ClientTypes.Public, context.CancellationToken)) + if (await manager.HasClientTypeAsync(application, ClientTypes.Public, context.CancellationToken)) { principal.SetClaim(Claims.Confirmation, CreateConfirmationClaim(certificate)); } @@ -4212,28 +4078,13 @@ public static partial class OpenIddictServerHandlers /// public sealed class PrepareRequestTokenPrincipal : IOpenIddictServerHandler { - private readonly IOpenIddictApplicationManager? _applicationManager; - - public PrepareRequestTokenPrincipal(IOpenIddictApplicationManager? applicationManager = null) - => _applicationManager = applicationManager; - /// /// Gets the default descriptor definition assigned to this handler. /// public static OpenIddictServerHandlerDescriptor Descriptor { get; } = OpenIddictServerHandlerDescriptor.CreateBuilder() .AddFilter() - .UseScopedHandler(static provider => - { - // Note: the application manager is only resolved if the degraded mode was not enabled to ensure - // invalid core configuration exceptions are not thrown even if the managers were registered. - var options = provider.GetRequiredService>().CurrentValue; - - return options.EnableDegradedMode - ? new PrepareRequestTokenPrincipal() - : new PrepareRequestTokenPrincipal(provider.GetService() - ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0016))); - }) + .UseSingletonHandler() .SetOrder(PrepareDeviceCodePrincipal.Descriptor.Order + 1_000) .SetType(OpenIddictServerHandlerType.BuiltIn) .Build(); @@ -4272,15 +4123,13 @@ public static partial class OpenIddictServerHandlers // If the client to which the token is returned is known, use the attached setting if available. if (lifetime is null && !context.Options.EnableDegradedMode && !string.IsNullOrEmpty(context.ClientId)) { - if (_applicationManager is null) - { - throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); - } + var manager = context.ServiceProvider.GetService() + ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); - var application = await _applicationManager.FindByClientIdAsync(context.ClientId, context.CancellationToken) + var application = await manager.FindByClientIdAsync(context.ClientId, context.CancellationToken) ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0017)); - var settings = await _applicationManager.GetSettingsAsync(application, context.CancellationToken); + var settings = await manager.GetSettingsAsync(application, context.CancellationToken); if (settings.TryGetValue(Settings.TokenLifetimes.RequestToken, out string? setting) && TimeSpan.TryParse(setting, CultureInfo.InvariantCulture, out var value)) { @@ -4340,28 +4189,13 @@ public static partial class OpenIddictServerHandlers /// public sealed class PrepareRefreshTokenPrincipal : IOpenIddictServerHandler { - private readonly IOpenIddictApplicationManager? _applicationManager; - - public PrepareRefreshTokenPrincipal(IOpenIddictApplicationManager? applicationManager = null) - => _applicationManager = applicationManager; - /// /// Gets the default descriptor definition assigned to this handler. /// public static OpenIddictServerHandlerDescriptor Descriptor { get; } = OpenIddictServerHandlerDescriptor.CreateBuilder() .AddFilter() - .UseScopedHandler(static provider => - { - // Note: the application manager is only resolved if the degraded mode was not enabled to ensure - // invalid core configuration exceptions are not thrown even if the managers were registered. - var options = provider.GetRequiredService>().CurrentValue; - - return options.EnableDegradedMode - ? new PrepareRefreshTokenPrincipal() - : new PrepareRefreshTokenPrincipal(provider.GetService() - ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0016))); - }) + .UseSingletonHandler() .SetOrder(PrepareRequestTokenPrincipal.Descriptor.Order + 1_000) .SetType(OpenIddictServerHandlerType.BuiltIn) .Build(); @@ -4417,15 +4251,13 @@ public static partial class OpenIddictServerHandlers // If the client to which the token is returned is known, use the attached setting if available. if (lifetime is null && !context.Options.EnableDegradedMode && !string.IsNullOrEmpty(context.ClientId)) { - if (_applicationManager is null) - { - throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); - } + var manager = context.ServiceProvider.GetService() + ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); - var application = await _applicationManager.FindByClientIdAsync(context.ClientId, context.CancellationToken) + var application = await manager.FindByClientIdAsync(context.ClientId, context.CancellationToken) ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0017)); - var settings = await _applicationManager.GetSettingsAsync(application, context.CancellationToken); + var settings = await manager.GetSettingsAsync(application, context.CancellationToken); if (settings.TryGetValue(Settings.TokenLifetimes.RefreshToken, out string? setting) && TimeSpan.TryParse(setting, CultureInfo.InvariantCulture, out var value)) { @@ -4470,12 +4302,10 @@ public static partial class OpenIddictServerHandlers else { - if (_applicationManager is null) - { - throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); - } + var manager = context.ServiceProvider.GetService() + ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); - var application = await _applicationManager.FindByClientIdAsync(context.ClientId, context.CancellationToken) + var application = await manager.FindByClientIdAsync(context.ClientId, context.CancellationToken) ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0017)); // Note: refresh tokens are only bound to the provided certificate when the client @@ -4483,7 +4313,7 @@ public static partial class OpenIddictServerHandlers // are already sender-constrained via standard client authentication, which is more // flexible than certificate-based token binding, as rotating client credentials is // easier in that case (specially when using PKI-based mTLS client authentication). - if (await _applicationManager.HasClientTypeAsync(application, ClientTypes.Public, context.CancellationToken)) + if (await manager.HasClientTypeAsync(application, ClientTypes.Public, context.CancellationToken)) { principal.SetClaim(Claims.Confirmation, CreateConfirmationClaim(certificate)); } @@ -4505,28 +4335,13 @@ public static partial class OpenIddictServerHandlers /// public sealed class PrepareIdentityTokenPrincipal : IOpenIddictServerHandler { - private readonly IOpenIddictApplicationManager? _applicationManager; - - public PrepareIdentityTokenPrincipal(IOpenIddictApplicationManager? applicationManager = null) - => _applicationManager = applicationManager; - /// /// Gets the default descriptor definition assigned to this handler. /// public static OpenIddictServerHandlerDescriptor Descriptor { get; } = OpenIddictServerHandlerDescriptor.CreateBuilder() .AddFilter() - .UseScopedHandler(static provider => - { - // Note: the application manager is only resolved if the degraded mode was not enabled to ensure - // invalid core configuration exceptions are not thrown even if the managers were registered. - var options = provider.GetRequiredService>().CurrentValue; - - return options.EnableDegradedMode - ? new PrepareIdentityTokenPrincipal() - : new PrepareIdentityTokenPrincipal(provider.GetService() - ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0016))); - }) + .UseSingletonHandler() .SetOrder(PrepareRefreshTokenPrincipal.Descriptor.Order + 1_000) .SetType(OpenIddictServerHandlerType.BuiltIn) .Build(); @@ -4593,15 +4408,13 @@ public static partial class OpenIddictServerHandlers // If the client to which the token is returned is known, use the attached setting if available. if (lifetime is null && !context.Options.EnableDegradedMode && !string.IsNullOrEmpty(context.ClientId)) { - if (_applicationManager is null) - { - throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); - } + var manager = context.ServiceProvider.GetService() + ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); - var application = await _applicationManager.FindByClientIdAsync(context.ClientId, context.CancellationToken) + var application = await manager.FindByClientIdAsync(context.ClientId, context.CancellationToken) ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0017)); - var settings = await _applicationManager.GetSettingsAsync(application, context.CancellationToken); + var settings = await manager.GetSettingsAsync(application, context.CancellationToken); if (settings.TryGetValue(Settings.TokenLifetimes.IdentityToken, out string? setting) && TimeSpan.TryParse(setting, CultureInfo.InvariantCulture, out var value)) { @@ -4660,28 +4473,13 @@ public static partial class OpenIddictServerHandlers /// public sealed class PrepareUserCodePrincipal : IOpenIddictServerHandler { - private readonly IOpenIddictApplicationManager? _applicationManager; - - public PrepareUserCodePrincipal(IOpenIddictApplicationManager? applicationManager = null) - => _applicationManager = applicationManager; - /// /// Gets the default descriptor definition assigned to this handler. /// public static OpenIddictServerHandlerDescriptor Descriptor { get; } = OpenIddictServerHandlerDescriptor.CreateBuilder() .AddFilter() - .UseScopedHandler(static provider => - { - // Note: the application manager is only resolved if the degraded mode was not enabled to ensure - // invalid core configuration exceptions are not thrown even if the managers were registered. - var options = provider.GetRequiredService>().CurrentValue; - - return options.EnableDegradedMode - ? new PrepareUserCodePrincipal() - : new PrepareUserCodePrincipal(provider.GetService() - ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0016))); - }) + .UseSingletonHandler() .SetOrder(PrepareIdentityTokenPrincipal.Descriptor.Order + 1_000) .SetType(OpenIddictServerHandlerType.BuiltIn) .Build(); @@ -4720,15 +4518,13 @@ public static partial class OpenIddictServerHandlers // If the client to which the token is returned is known, use the attached setting if available. if (lifetime is null && !context.Options.EnableDegradedMode && !string.IsNullOrEmpty(context.ClientId)) { - if (_applicationManager is null) - { - throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); - } + var manager = context.ServiceProvider.GetService() + ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); - var application = await _applicationManager.FindByClientIdAsync(context.ClientId, context.CancellationToken) + var application = await manager.FindByClientIdAsync(context.ClientId, context.CancellationToken) ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0017)); - var settings = await _applicationManager.GetSettingsAsync(application, context.CancellationToken); + var settings = await manager.GetSettingsAsync(application, context.CancellationToken); if (settings.TryGetValue(Settings.TokenLifetimes.UserCode, out string? setting) && TimeSpan.TryParse(setting, CultureInfo.InvariantCulture, out var value)) { @@ -5217,13 +5013,6 @@ public static partial class OpenIddictServerHandlers /// public sealed class UpdateReferenceDeviceCodeEntry : IOpenIddictServerHandler { - private readonly IOpenIddictTokenManager _tokenManager; - - public UpdateReferenceDeviceCodeEntry() => throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); - - public UpdateReferenceDeviceCodeEntry(IOpenIddictTokenManager tokenManager) - => _tokenManager = tokenManager ?? throw new ArgumentNullException(nameof(tokenManager)); - /// /// Gets the default descriptor definition assigned to this handler. /// @@ -5232,7 +5021,7 @@ public static partial class OpenIddictServerHandlers .AddFilter() .AddFilter() .AddFilter() - .UseScopedHandler() + .UseSingletonHandler() .SetOrder(AttachDeviceCodeIdentifier.Descriptor.Order + 1_000) .SetType(OpenIddictServerHandlerType.BuiltIn) .Build(); @@ -5262,13 +5051,16 @@ public static partial class OpenIddictServerHandlers throw new InvalidOperationException(SR.GetResourceString(SR.ID0008)); } - var token = await _tokenManager.FindByIdAsync(identifier, context.CancellationToken) + var manager = context.ServiceProvider.GetService() + ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); + + var token = await manager.FindByIdAsync(identifier, context.CancellationToken) ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0265)); // Replace the device code details by the payload derived from the new device code principal, // that includes all the user claims populated by the application after authenticating the user. var descriptor = new OpenIddictTokenDescriptor(); - await _tokenManager.PopulateAsync(descriptor, token, context.CancellationToken); + await manager.PopulateAsync(descriptor, token, context.CancellationToken); // Note: the lifetime is deliberately extended to give more time to the client to redeem the code. descriptor.ExpirationDate = context.DeviceCodePrincipal.GetExpirationDate(); @@ -5277,9 +5069,9 @@ public static partial class OpenIddictServerHandlers descriptor.Status = Statuses.Valid; descriptor.Subject = context.DeviceCodePrincipal.GetClaim(Claims.Subject); - await _tokenManager.UpdateAsync(token, descriptor, context.CancellationToken); + await manager.UpdateAsync(token, descriptor, context.CancellationToken); - context.Logger.LogTrace(6021, SR.GetResourceString(SR.ID6021), await _tokenManager.GetIdAsync(token, context.CancellationToken)); + context.Logger.LogTrace(6021, SR.GetResourceString(SR.ID6021), await manager.GetIdAsync(token, context.CancellationToken)); } } @@ -5811,13 +5603,6 @@ public static partial class OpenIddictServerHandlers /// public sealed class RedeemLogoutTokenEntry : IOpenIddictServerHandler { - private readonly IOpenIddictTokenManager _tokenManager; - - public RedeemLogoutTokenEntry() => throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); - - public RedeemLogoutTokenEntry(IOpenIddictTokenManager tokenManager) - => _tokenManager = tokenManager ?? throw new ArgumentNullException(nameof(tokenManager)); - /// /// Gets the default descriptor definition assigned to this handler. /// @@ -5826,7 +5611,7 @@ public static partial class OpenIddictServerHandlers .AddFilter() .AddFilter() .AddFilter() - .UseScopedHandler() + .UseSingletonHandler() // Note: this handler is deliberately executed early in the pipeline to ensure // that the token database entry is always marked as redeemed even if the sign-out // demand is rejected later in the pipeline (e.g because an error was returned). @@ -5857,14 +5642,17 @@ public static partial class OpenIddictServerHandlers return; } - var token = await _tokenManager.FindByIdAsync(identifier, context.CancellationToken); + var manager = context.ServiceProvider.GetService() + ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)); + + var token = await manager.FindByIdAsync(identifier, context.CancellationToken); if (token is null) { return; } // Mark the token as redeemed to prevent future reuses. - await _tokenManager.TryRedeemAsync(token, context.CancellationToken); + await manager.TryRedeemAsync(token, context.CancellationToken); } } diff --git a/src/OpenIddict.Validation/OpenIddictValidationHandlers.Protection.cs b/src/OpenIddict.Validation/OpenIddictValidationHandlers.Protection.cs index 04170aaf..b5c15cc6 100644 --- a/src/OpenIddict.Validation/OpenIddictValidationHandlers.Protection.cs +++ b/src/OpenIddict.Validation/OpenIddictValidationHandlers.Protection.cs @@ -13,6 +13,7 @@ using System.Security.Claims; using System.Security.Cryptography; using System.Security.Cryptography.X509Certificates; using System.Text.Json.Nodes; +using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Microsoft.IdentityModel.Tokens; @@ -190,20 +191,13 @@ public static partial class OpenIddictValidationHandlers /// public sealed class ValidateReferenceTokenIdentifier : IOpenIddictValidationHandler { - private readonly IOpenIddictTokenManager _tokenManager; - - public ValidateReferenceTokenIdentifier() => throw new InvalidOperationException(SR.GetResourceString(SR.ID0139)); - - public ValidateReferenceTokenIdentifier(IOpenIddictTokenManager tokenManager) - => _tokenManager = tokenManager ?? throw new ArgumentNullException(nameof(tokenManager)); - /// /// Gets the default descriptor definition assigned to this handler. /// public static OpenIddictValidationHandlerDescriptor Descriptor { get; } = OpenIddictValidationHandlerDescriptor.CreateBuilder() .AddFilter() - .UseScopedHandler() + .UseSingletonHandler() .SetOrder(RemoveDisallowedCharacters.Descriptor.Order + 1_000) .SetType(OpenIddictValidationHandlerType.BuiltIn) .Build(); @@ -219,8 +213,11 @@ public static partial class OpenIddictValidationHandlers return; } + var manager = context.ServiceProvider.GetService() + ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0139)); + // If the reference token cannot be found, don't return an error to allow another handler to validate it. - var token = await _tokenManager.FindByReferenceIdAsync(context.Token, context.CancellationToken); + var token = await manager.FindByReferenceIdAsync(context.Token, context.CancellationToken); if (token is null) { return; @@ -230,8 +227,8 @@ public static partial class OpenIddictValidationHandlers if (!(context.ValidTokenTypes.Count switch { 0 => true, // If no specific token type is expected, accept all token types at this stage. - 1 => await _tokenManager.HasTypeAsync(token, context.ValidTokenTypes.ElementAt(0), context.CancellationToken), - _ => await _tokenManager.HasTypeAsync(token, [.. context.ValidTokenTypes], context.CancellationToken) + 1 => await manager.HasTypeAsync(token, context.ValidTokenTypes.ElementAt(0), context.CancellationToken), + _ => await manager.HasTypeAsync(token, [.. context.ValidTokenTypes], context.CancellationToken) })) { context.Reject( @@ -242,7 +239,7 @@ public static partial class OpenIddictValidationHandlers return; } - var payload = await _tokenManager.GetPayloadAsync(token, context.CancellationToken); + var payload = await manager.GetPayloadAsync(token, context.CancellationToken); if (string.IsNullOrEmpty(payload)) { throw new InvalidOperationException(SR.GetResourceString(SR.ID0026)); @@ -253,7 +250,7 @@ public static partial class OpenIddictValidationHandlers // used to restore the properties associated with the token. context.IsReferenceToken = true; context.Token = payload; - context.TokenId = await _tokenManager.GetIdAsync(token, context.CancellationToken); + context.TokenId = await manager.GetIdAsync(token, context.CancellationToken); } } @@ -523,20 +520,13 @@ public static partial class OpenIddictValidationHandlers /// public sealed class RestoreTokenEntryProperties : IOpenIddictValidationHandler { - private readonly IOpenIddictTokenManager _tokenManager; - - public RestoreTokenEntryProperties() => throw new InvalidOperationException(SR.GetResourceString(SR.ID0139)); - - public RestoreTokenEntryProperties(IOpenIddictTokenManager tokenManager) - => _tokenManager = tokenManager ?? throw new ArgumentNullException(nameof(tokenManager)); - /// /// Gets the default descriptor definition assigned to this handler. /// public static OpenIddictValidationHandlerDescriptor Descriptor { get; } = OpenIddictValidationHandlerDescriptor.CreateBuilder() .AddFilter() - .UseScopedHandler() + .UseSingletonHandler() .SetOrder(MapInternalClaims.Descriptor.Order + 1_000) .SetType(OpenIddictValidationHandlerType.BuiltIn) .Build(); @@ -561,8 +551,11 @@ public static partial class OpenIddictValidationHandlers return; } + var manager = context.ServiceProvider.GetService() + ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0139)); + // If the token entry cannot be found, return a generic error. - var token = await _tokenManager.FindByIdAsync(identifier, context.CancellationToken); + var token = await manager.FindByIdAsync(identifier, context.CancellationToken); if (token is null) { context.Reject( @@ -576,9 +569,9 @@ public static partial class OpenIddictValidationHandlers // If the token was not validated as a reference token but has a reference identifier attached, this // may indicate that the payload stored in the database has leaked and is being used as a regular, // non-reference token. To prevent this, reject the token if the reference identifier is not null. - if (!context.IsReferenceToken && !string.IsNullOrEmpty(await _tokenManager.GetReferenceIdAsync(token, context.CancellationToken))) + if (!context.IsReferenceToken && !string.IsNullOrEmpty(await manager.GetReferenceIdAsync(token, context.CancellationToken))) { - context.Logger.LogWarning(6292, SR.GetResourceString(SR.ID6292), await _tokenManager.GetIdAsync(token, context.CancellationToken)); + context.Logger.LogWarning(6292, SR.GetResourceString(SR.ID6292), await manager.GetIdAsync(token, context.CancellationToken)); context.Reject( error: Errors.InvalidToken, @@ -590,11 +583,11 @@ public static partial class OpenIddictValidationHandlers // Restore the creation/expiration dates/identifiers from the token entry metadata. context.Principal - .SetCreationDate(await _tokenManager.GetCreationDateAsync(token, context.CancellationToken)) - .SetExpirationDate(await _tokenManager.GetExpirationDateAsync(token, context.CancellationToken)) - .SetAuthorizationId(context.AuthorizationId = await _tokenManager.GetAuthorizationIdAsync(token, context.CancellationToken)) - .SetTokenId(context.TokenId = await _tokenManager.GetIdAsync(token, context.CancellationToken)) - .SetTokenType(await _tokenManager.GetTypeAsync(token, context.CancellationToken)); + .SetCreationDate(await manager.GetCreationDateAsync(token, context.CancellationToken)) + .SetExpirationDate(await manager.GetExpirationDateAsync(token, context.CancellationToken)) + .SetAuthorizationId(context.AuthorizationId = await manager.GetAuthorizationIdAsync(token, context.CancellationToken)) + .SetTokenId(context.TokenId = await manager.GetIdAsync(token, context.CancellationToken)) + .SetTokenType(await manager.GetTypeAsync(token, context.CancellationToken)); } } @@ -895,13 +888,6 @@ public static partial class OpenIddictValidationHandlers /// public sealed class ValidateTokenEntry : IOpenIddictValidationHandler { - private readonly IOpenIddictTokenManager _tokenManager; - - public ValidateTokenEntry() => throw new InvalidOperationException(SR.GetResourceString(SR.ID0139)); - - public ValidateTokenEntry(IOpenIddictTokenManager tokenManager) - => _tokenManager = tokenManager ?? throw new ArgumentNullException(nameof(tokenManager)); - /// /// Gets the default descriptor definition assigned to this handler. /// @@ -909,7 +895,7 @@ public static partial class OpenIddictValidationHandlers = OpenIddictValidationHandlerDescriptor.CreateBuilder() .AddFilter() .AddFilter() - .UseScopedHandler() + .UseSingletonHandler() .SetOrder(ValidateProofOfPossession.Descriptor.Order + 1_000) .SetType(OpenIddictValidationHandlerType.BuiltIn) .Build(); @@ -922,10 +908,13 @@ public static partial class OpenIddictValidationHandlers Debug.Assert(context.Principal is { Identity: ClaimsIdentity }, SR.GetResourceString(SR.ID4006)); Debug.Assert(!string.IsNullOrEmpty(context.TokenId), SR.GetResourceString(SR.ID4017)); - var token = await _tokenManager.FindByIdAsync(context.TokenId, context.CancellationToken) + var manager = context.ServiceProvider.GetService() + ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0139)); + + var token = await manager.FindByIdAsync(context.TokenId, context.CancellationToken) ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0021)); - if (!await _tokenManager.HasStatusAsync(token, Statuses.Valid, context.CancellationToken)) + if (!await manager.HasStatusAsync(token, Statuses.Valid, context.CancellationToken)) { context.Logger.LogInformation(6005, SR.GetResourceString(SR.ID6005), context.TokenId); @@ -945,13 +934,6 @@ public static partial class OpenIddictValidationHandlers /// public sealed class ValidateAuthorizationEntry : IOpenIddictValidationHandler { - private readonly IOpenIddictAuthorizationManager _authorizationManager; - - public ValidateAuthorizationEntry() => throw new InvalidOperationException(SR.GetResourceString(SR.ID0142)); - - public ValidateAuthorizationEntry(IOpenIddictAuthorizationManager authorizationManager) - => _authorizationManager = authorizationManager ?? throw new ArgumentNullException(nameof(authorizationManager)); - /// /// Gets the default descriptor definition assigned to this handler. /// @@ -959,7 +941,7 @@ public static partial class OpenIddictValidationHandlers = OpenIddictValidationHandlerDescriptor.CreateBuilder() .AddFilter() .AddFilter() - .UseScopedHandler() + .UseSingletonHandler() .SetOrder(ValidateTokenEntry.Descriptor.Order + 1_000) .SetType(OpenIddictValidationHandlerType.BuiltIn) .Build(); @@ -972,8 +954,11 @@ public static partial class OpenIddictValidationHandlers Debug.Assert(context.Principal is { Identity: ClaimsIdentity }, SR.GetResourceString(SR.ID4006)); Debug.Assert(!string.IsNullOrEmpty(context.AuthorizationId), SR.GetResourceString(SR.ID4018)); - var authorization = await _authorizationManager.FindByIdAsync(context.AuthorizationId, context.CancellationToken); - if (authorization is null || !await _authorizationManager.HasStatusAsync(authorization, Statuses.Valid, context.CancellationToken)) + var manager = context.ServiceProvider.GetService() + ?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0142)); + + var authorization = await manager.FindByIdAsync(context.AuthorizationId, context.CancellationToken); + if (authorization is null || !await manager.HasStatusAsync(authorization, Statuses.Valid, context.CancellationToken)) { context.Logger.LogInformation(6006, SR.GetResourceString(SR.ID6006), context.AuthorizationId);