Browse Source

Convert all the scoped event handlers to singleton services

pull/2533/head
Kévin Chalet 2 weeks ago
parent
commit
058c115713
  1. 101
      src/OpenIddict.Client/OpenIddictClientHandlers.Protection.cs
  2. 17
      src/OpenIddict.Client/OpenIddictClientHandlers.cs
  3. 422
      src/OpenIddict.Server/OpenIddictServerHandlers.Authentication.cs
  4. 79
      src/OpenIddict.Server/OpenIddictServerHandlers.Device.cs
  5. 152
      src/OpenIddict.Server/OpenIddictServerHandlers.Exchange.cs
  6. 33
      src/OpenIddict.Server/OpenIddictServerHandlers.Introspection.cs
  7. 168
      src/OpenIddict.Server/OpenIddictServerHandlers.Protection.cs
  8. 33
      src/OpenIddict.Server/OpenIddictServerHandlers.Revocation.cs
  9. 130
      src/OpenIddict.Server/OpenIddictServerHandlers.Session.cs
  10. 448
      src/OpenIddict.Server/OpenIddictServerHandlers.cs
  11. 83
      src/OpenIddict.Validation/OpenIddictValidationHandlers.Protection.cs

101
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
/// </summary>
public sealed class ValidateReferenceTokenIdentifier : IOpenIddictClientHandler<ValidateTokenContext>
{
private readonly IOpenIddictTokenManager _tokenManager;
public ValidateReferenceTokenIdentifier() => throw new InvalidOperationException(SR.GetResourceString(SR.ID0318));
public ValidateReferenceTokenIdentifier(IOpenIddictTokenManager tokenManager)
=> _tokenManager = tokenManager ?? throw new ArgumentNullException(nameof(tokenManager));
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
/// </summary>
public static OpenIddictClientHandlerDescriptor Descriptor { get; }
= OpenIddictClientHandlerDescriptor.CreateBuilder<ValidateTokenContext>()
.AddFilter<RequireTokenStorageEnabled>()
.UseScopedHandler<ValidateReferenceTokenIdentifier>()
.UseSingletonHandler<ValidateReferenceTokenIdentifier>()
.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<IOpenIddictTokenManager>()
?? 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
/// </summary>
public sealed class RestoreTokenEntryProperties : IOpenIddictClientHandler<ValidateTokenContext>
{
private readonly IOpenIddictTokenManager _tokenManager;
public RestoreTokenEntryProperties() => throw new InvalidOperationException(SR.GetResourceString(SR.ID0318));
public RestoreTokenEntryProperties(IOpenIddictTokenManager tokenManager)
=> _tokenManager = tokenManager ?? throw new ArgumentNullException(nameof(tokenManager));
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
/// </summary>
public static OpenIddictClientHandlerDescriptor Descriptor { get; }
= OpenIddictClientHandlerDescriptor.CreateBuilder<ValidateTokenContext>()
.AddFilter<RequireTokenStorageEnabled>()
.UseScopedHandler<RestoreTokenEntryProperties>()
.UseSingletonHandler<RestoreTokenEntryProperties>()
.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<IOpenIddictTokenManager>()
?? 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
/// </summary>
public sealed class ValidateTokenEntry : IOpenIddictClientHandler<ValidateTokenContext>
{
private readonly IOpenIddictTokenManager _tokenManager;
public ValidateTokenEntry() => throw new InvalidOperationException(SR.GetResourceString(SR.ID0139));
public ValidateTokenEntry(IOpenIddictTokenManager tokenManager)
=> _tokenManager = tokenManager ?? throw new ArgumentNullException(nameof(tokenManager));
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
/// </summary>
@ -838,7 +824,7 @@ public static partial class OpenIddictClientHandlers
= OpenIddictClientHandlerDescriptor.CreateBuilder<ValidateTokenContext>()
.AddFilter<RequireTokenStorageEnabled>()
.AddFilter<RequireTokenIdResolved>()
.UseScopedHandler<ValidateTokenEntry>()
.UseSingletonHandler<ValidateTokenEntry>()
.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<IOpenIddictTokenManager>()
?? 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
/// </summary>
public sealed class CreateTokenEntry : IOpenIddictClientHandler<GenerateTokenContext>
{
private readonly IOpenIddictTokenManager _tokenManager;
public CreateTokenEntry() => throw new InvalidOperationException(SR.GetResourceString(SR.ID0318));
public CreateTokenEntry(IOpenIddictTokenManager tokenManager)
=> _tokenManager = tokenManager ?? throw new ArgumentNullException(nameof(tokenManager));
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
/// </summary>
@ -957,7 +939,7 @@ public static partial class OpenIddictClientHandlers
= OpenIddictClientHandlerDescriptor.CreateBuilder<GenerateTokenContext>()
.AddFilter<RequireTokenStorageEnabled>()
.AddFilter<RequireTokenEntryCreated>()
.UseScopedHandler<CreateTokenEntry>()
.UseSingletonHandler<CreateTokenEntry>()
.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<IOpenIddictTokenManager>()
?? 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
/// </summary>
public sealed class AttachTokenPayload : IOpenIddictClientHandler<GenerateTokenContext>
{
private readonly IOpenIddictTokenManager _tokenManager;
public AttachTokenPayload() => throw new InvalidOperationException(SR.GetResourceString(SR.ID0318));
public AttachTokenPayload(IOpenIddictTokenManager tokenManager)
=> _tokenManager = tokenManager ?? throw new ArgumentNullException(nameof(tokenManager));
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
/// </summary>
@ -1156,7 +1134,7 @@ public static partial class OpenIddictClientHandlers
= OpenIddictClientHandlerDescriptor.CreateBuilder<GenerateTokenContext>()
.AddFilter<RequireTokenStorageEnabled>()
.AddFilter<RequireTokenPayloadPersisted>()
.UseScopedHandler<AttachTokenPayload>()
.UseSingletonHandler<AttachTokenPayload>()
.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<IOpenIddictTokenManager>()
?? 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);

17
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
/// </summary>
public sealed class RedeemStateTokenEntry : IOpenIddictClientHandler<ProcessAuthenticationContext>
{
private readonly IOpenIddictTokenManager _tokenManager;
public RedeemStateTokenEntry() => throw new InvalidOperationException(SR.GetResourceString(SR.ID0318));
public RedeemStateTokenEntry(IOpenIddictTokenManager tokenManager)
=> _tokenManager = tokenManager ?? throw new ArgumentNullException(nameof(tokenManager));
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
/// </summary>
@ -833,7 +827,7 @@ public static partial class OpenIddictClientHandlers
.AddFilter<RequireStateTokenPrincipal>()
.AddFilter<RequireStateTokenRedeemed>()
.AddFilter<RequireStateTokenValidated>()
.UseScopedHandler<RedeemStateTokenEntry>()
.UseSingletonHandler<RedeemStateTokenEntry>()
// 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<IOpenIddictTokenManager>()
?? 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,

422
src/OpenIddict.Server/OpenIddictServerHandlers.Authentication.cs

@ -1330,27 +1330,12 @@ public static partial class OpenIddictServerHandlers
/// </summary>
public sealed class ValidateResponseType : IOpenIddictServerHandler<ValidateAuthorizationRequestContext>
{
private readonly IOpenIddictApplicationManager? _applicationManager;
public ValidateResponseType(IOpenIddictApplicationManager? applicationManager = null)
=> _applicationManager = applicationManager;
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
/// </summary>
public static OpenIddictServerHandlerDescriptor Descriptor { get; }
= OpenIddictServerHandlerDescriptor.CreateBuilder<ValidateAuthorizationRequestContext>()
.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<IOptionsMonitor<OpenIddictServerOptions>>().CurrentValue;
return options.EnableDegradedMode
? new ValidateResponseType(applicationManager: null)
: new ValidateResponseType(provider.GetService<IOpenIddictApplicationManager>()
?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)));
})
.UseSingletonHandler<ValidateResponseType>()
.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<IOpenIddictApplicationManager>()
?? 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
/// </summary>
public sealed class ValidateClientRedirectUri : IOpenIddictServerHandler<ValidateAuthorizationRequestContext>
{
private readonly IOpenIddictApplicationManager _applicationManager;
public ValidateClientRedirectUri() => throw new InvalidOperationException(SR.GetResourceString(SR.ID0016));
public ValidateClientRedirectUri(IOpenIddictApplicationManager applicationManager)
=> _applicationManager = applicationManager ?? throw new ArgumentNullException(nameof(applicationManager));
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
/// </summary>
public static OpenIddictServerHandlerDescriptor Descriptor { get; }
= OpenIddictServerHandlerDescriptor.CreateBuilder<ValidateAuthorizationRequestContext>()
.AddFilter<RequireDegradedModeDisabled>()
.UseScopedHandler<ValidateClientRedirectUri>()
.UseSingletonHandler<ValidateClientRedirectUri>()
.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<IOpenIddictApplicationManager>()
?? 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
/// </summary>
public sealed class ValidateScopes : IOpenIddictServerHandler<ValidateAuthorizationRequestContext>
{
private readonly IOpenIddictScopeManager? _scopeManager;
public ValidateScopes(IOpenIddictScopeManager? scopeManager = null)
=> _scopeManager = scopeManager;
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
/// </summary>
public static OpenIddictServerHandlerDescriptor Descriptor { get; }
= OpenIddictServerHandlerDescriptor.CreateBuilder<ValidateAuthorizationRequestContext>()
.AddFilter<RequireScopeValidationEnabled>()
.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<IOptionsMonitor<OpenIddictServerOptions>>().CurrentValue;
return options.EnableDegradedMode
? new ValidateScopes()
: new ValidateScopes(provider.GetService<IOpenIddictScopeManager>()
?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)));
})
.UseSingletonHandler<ValidateScopes>()
.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<IOpenIddictScopeManager>()
?? 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
/// </summary>
public sealed class ValidateResources : IOpenIddictServerHandler<ValidateAuthorizationRequestContext>
{
private readonly IOpenIddictResourceManager? _resourceManager;
public ValidateResources(IOpenIddictResourceManager? resourceManager = null)
=> _resourceManager = resourceManager;
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
/// </summary>
public static OpenIddictServerHandlerDescriptor Descriptor { get; }
= OpenIddictServerHandlerDescriptor.CreateBuilder<ValidateAuthorizationRequestContext>()
.AddFilter<RequireResourceValidationEnabled>()
.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<IOptionsMonitor<OpenIddictServerOptions>>().CurrentValue;
return options.EnableDegradedMode
? new ValidateResources()
: new ValidateResources(provider.GetService<IOpenIddictResourceManager>()
?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)));
})
.UseSingletonHandler<ValidateResources>()
.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<IOpenIddictResourceManager>()
?? 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
/// </summary>
public sealed class ValidateEndpointPermissions : IOpenIddictServerHandler<ValidateAuthorizationRequestContext>
{
private readonly IOpenIddictApplicationManager _applicationManager;
public ValidateEndpointPermissions() => throw new InvalidOperationException(SR.GetResourceString(SR.ID0016));
public ValidateEndpointPermissions(IOpenIddictApplicationManager applicationManager)
=> _applicationManager = applicationManager ?? throw new ArgumentNullException(nameof(applicationManager));
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
/// </summary>
@ -1660,7 +1598,7 @@ public static partial class OpenIddictServerHandlers
= OpenIddictServerHandlerDescriptor.CreateBuilder<ValidateAuthorizationRequestContext>()
.AddFilter<RequireEndpointPermissionsEnabled>()
.AddFilter<RequireDegradedModeDisabled>()
.UseScopedHandler<ValidateEndpointPermissions>()
.UseSingletonHandler<ValidateEndpointPermissions>()
.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<IOpenIddictApplicationManager>()
?? 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
/// </summary>
public sealed class ValidateGrantTypePermissions : IOpenIddictServerHandler<ValidateAuthorizationRequestContext>
{
private readonly IOpenIddictApplicationManager _applicationManager;
public ValidateGrantTypePermissions() => throw new InvalidOperationException(SR.GetResourceString(SR.ID0016));
public ValidateGrantTypePermissions(IOpenIddictApplicationManager applicationManager)
=> _applicationManager = applicationManager ?? throw new ArgumentNullException(nameof(applicationManager));
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
/// </summary>
@ -1710,7 +1644,7 @@ public static partial class OpenIddictServerHandlers
= OpenIddictServerHandlerDescriptor.CreateBuilder<ValidateAuthorizationRequestContext>()
.AddFilter<RequireGrantTypePermissionsEnabled>()
.AddFilter<RequireDegradedModeDisabled>()
.UseScopedHandler<ValidateGrantTypePermissions>()
.UseSingletonHandler<ValidateGrantTypePermissions>()
.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<IOpenIddictApplicationManager>()
?? 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
/// </summary>
public sealed class ValidateResponseTypePermissions : IOpenIddictServerHandler<ValidateAuthorizationRequestContext>
{
private readonly IOpenIddictApplicationManager _applicationManager;
public ValidateResponseTypePermissions() => throw new InvalidOperationException(SR.GetResourceString(SR.ID0016));
public ValidateResponseTypePermissions(IOpenIddictApplicationManager applicationManager)
=> _applicationManager = applicationManager ?? throw new ArgumentNullException(nameof(applicationManager));
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
/// </summary>
@ -1805,7 +1735,7 @@ public static partial class OpenIddictServerHandlers
= OpenIddictServerHandlerDescriptor.CreateBuilder<ValidateAuthorizationRequestContext>()
.AddFilter<RequireResponseTypePermissionsEnabled>()
.AddFilter<RequireDegradedModeDisabled>()
.UseScopedHandler<ValidateResponseTypePermissions>()
.UseSingletonHandler<ValidateResponseTypePermissions>()
.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<IOpenIddictApplicationManager>()
?? 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
/// </summary>
public sealed class ValidateScopePermissions : IOpenIddictServerHandler<ValidateAuthorizationRequestContext>
{
private readonly IOpenIddictApplicationManager _applicationManager;
public ValidateScopePermissions() => throw new InvalidOperationException(SR.GetResourceString(SR.ID0016));
public ValidateScopePermissions(IOpenIddictApplicationManager applicationManager)
=> _applicationManager = applicationManager ?? throw new ArgumentNullException(nameof(applicationManager));
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
/// </summary>
@ -1880,7 +1806,7 @@ public static partial class OpenIddictServerHandlers
= OpenIddictServerHandlerDescriptor.CreateBuilder<ValidateAuthorizationRequestContext>()
.AddFilter<RequireScopePermissionsEnabled>()
.AddFilter<RequireDegradedModeDisabled>()
.UseScopedHandler<ValidateScopePermissions>()
.UseSingletonHandler<ValidateScopePermissions>()
.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<IOpenIddictApplicationManager>()
?? 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
/// </summary>
public sealed class ValidateResourcePermissions : IOpenIddictServerHandler<ValidateAuthorizationRequestContext>
{
private readonly IOpenIddictApplicationManager _applicationManager;
public ValidateResourcePermissions() => throw new InvalidOperationException(SR.GetResourceString(SR.ID0016));
public ValidateResourcePermissions(IOpenIddictApplicationManager applicationManager)
=> _applicationManager = applicationManager ?? throw new ArgumentNullException(nameof(applicationManager));
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
/// </summary>
@ -1941,7 +1863,7 @@ public static partial class OpenIddictServerHandlers
= OpenIddictServerHandlerDescriptor.CreateBuilder<ValidateAuthorizationRequestContext>()
.AddFilter<RequireResourcePermissionsEnabled>()
.AddFilter<RequireDegradedModeDisabled>()
.UseScopedHandler<ValidateResourcePermissions>()
.UseSingletonHandler<ValidateResourcePermissions>()
.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<IOpenIddictApplicationManager>()
?? 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
/// </summary>
public sealed class ValidatePushedAuthorizationRequestsRequirement : IOpenIddictServerHandler<ValidateAuthorizationRequestContext>
{
private readonly IOpenIddictApplicationManager _applicationManager;
public ValidatePushedAuthorizationRequestsRequirement() => throw new InvalidOperationException(SR.GetResourceString(SR.ID0016));
public ValidatePushedAuthorizationRequestsRequirement(IOpenIddictApplicationManager applicationManager)
=> _applicationManager = applicationManager ?? throw new ArgumentNullException(nameof(applicationManager));
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
/// </summary>
public static OpenIddictServerHandlerDescriptor Descriptor { get; }
= OpenIddictServerHandlerDescriptor.CreateBuilder<ValidateAuthorizationRequestContext>()
.AddFilter<RequireDegradedModeDisabled>()
.UseScopedHandler<ValidatePushedAuthorizationRequestsRequirement>()
.UseSingletonHandler<ValidatePushedAuthorizationRequestsRequirement>()
.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<IOpenIddictApplicationManager>()
?? 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
/// </summary>
public sealed class ValidateProofKeyForCodeExchangeRequirement : IOpenIddictServerHandler<ValidateAuthorizationRequestContext>
{
private readonly IOpenIddictApplicationManager _applicationManager;
public ValidateProofKeyForCodeExchangeRequirement() => throw new InvalidOperationException(SR.GetResourceString(SR.ID0016));
public ValidateProofKeyForCodeExchangeRequirement(IOpenIddictApplicationManager applicationManager)
=> _applicationManager = applicationManager ?? throw new ArgumentNullException(nameof(applicationManager));
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
/// </summary>
public static OpenIddictServerHandlerDescriptor Descriptor { get; }
= OpenIddictServerHandlerDescriptor.CreateBuilder<ValidateAuthorizationRequestContext>()
.AddFilter<RequireDegradedModeDisabled>()
.UseScopedHandler<ValidateProofKeyForCodeExchangeRequirement>()
.UseSingletonHandler<ValidateProofKeyForCodeExchangeRequirement>()
.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<IOpenIddictApplicationManager>()
?? 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
/// </summary>
public sealed class ValidatePushedResponseType : IOpenIddictServerHandler<ValidatePushedAuthorizationRequestContext>
{
private readonly IOpenIddictApplicationManager? _applicationManager;
public ValidatePushedResponseType(IOpenIddictApplicationManager? applicationManager = null)
=> _applicationManager = applicationManager;
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
/// </summary>
public static OpenIddictServerHandlerDescriptor Descriptor { get; }
= OpenIddictServerHandlerDescriptor.CreateBuilder<ValidatePushedAuthorizationRequestContext>()
.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<IOptionsMonitor<OpenIddictServerOptions>>().CurrentValue;
return options.EnableDegradedMode
? new ValidatePushedResponseType(applicationManager: null)
: new ValidatePushedResponseType(provider.GetService<IOpenIddictApplicationManager>()
?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)));
})
.UseSingletonHandler<ValidatePushedResponseType>()
.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<IOpenIddictApplicationManager>()
?? 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
/// </summary>
public sealed class ValidatePushedClientRedirectUri : IOpenIddictServerHandler<ValidatePushedAuthorizationRequestContext>
{
private readonly IOpenIddictApplicationManager _applicationManager;
public ValidatePushedClientRedirectUri() => throw new InvalidOperationException(SR.GetResourceString(SR.ID0016));
public ValidatePushedClientRedirectUri(IOpenIddictApplicationManager applicationManager)
=> _applicationManager = applicationManager ?? throw new ArgumentNullException(nameof(applicationManager));
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
/// </summary>
public static OpenIddictServerHandlerDescriptor Descriptor { get; }
= OpenIddictServerHandlerDescriptor.CreateBuilder<ValidatePushedAuthorizationRequestContext>()
.AddFilter<RequireDegradedModeDisabled>()
.UseScopedHandler<ValidatePushedClientRedirectUri>()
.UseSingletonHandler<ValidatePushedClientRedirectUri>()
.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<IOpenIddictApplicationManager>()
?? 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
/// </summary>
public sealed class ValidatePushedScopes : IOpenIddictServerHandler<ValidatePushedAuthorizationRequestContext>
{
private readonly IOpenIddictScopeManager? _scopeManager;
public ValidatePushedScopes(IOpenIddictScopeManager? scopeManager = null)
=> _scopeManager = scopeManager;
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
/// </summary>
public static OpenIddictServerHandlerDescriptor Descriptor { get; }
= OpenIddictServerHandlerDescriptor.CreateBuilder<ValidatePushedAuthorizationRequestContext>()
.AddFilter<RequireScopeValidationEnabled>()
.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<IOptionsMonitor<OpenIddictServerOptions>>().CurrentValue;
return options.EnableDegradedMode
? new ValidatePushedScopes()
: new ValidatePushedScopes(provider.GetService<IOpenIddictScopeManager>()
?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)));
})
.UseSingletonHandler<ValidatePushedScopes>()
.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<IOpenIddictScopeManager>()
?? 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
/// </summary>
public sealed class ValidatePushedResources : IOpenIddictServerHandler<ValidatePushedAuthorizationRequestContext>
{
private readonly IOpenIddictResourceManager? _resourceManager;
public ValidatePushedResources(IOpenIddictResourceManager? resourceManager = null)
=> _resourceManager = resourceManager;
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
/// </summary>
public static OpenIddictServerHandlerDescriptor Descriptor { get; }
= OpenIddictServerHandlerDescriptor.CreateBuilder<ValidatePushedAuthorizationRequestContext>()
.AddFilter<RequireResourceValidationEnabled>()
.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<IOptionsMonitor<OpenIddictServerOptions>>().CurrentValue;
return options.EnableDegradedMode
? new ValidatePushedResources()
: new ValidatePushedResources(provider.GetService<IOpenIddictResourceManager>()
?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)));
})
.UseSingletonHandler<ValidatePushedResources>()
.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<IOpenIddictResourceManager>()
?? 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
/// </summary>
public sealed class ValidatePushedEndpointPermissions : IOpenIddictServerHandler<ValidatePushedAuthorizationRequestContext>
{
private readonly IOpenIddictApplicationManager _applicationManager;
public ValidatePushedEndpointPermissions() => throw new InvalidOperationException(SR.GetResourceString(SR.ID0016));
public ValidatePushedEndpointPermissions(IOpenIddictApplicationManager applicationManager)
=> _applicationManager = applicationManager ?? throw new ArgumentNullException(nameof(applicationManager));
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
/// </summary>
@ -3747,7 +3602,7 @@ public static partial class OpenIddictServerHandlers
= OpenIddictServerHandlerDescriptor.CreateBuilder<ValidatePushedAuthorizationRequestContext>()
.AddFilter<RequireEndpointPermissionsEnabled>()
.AddFilter<RequireDegradedModeDisabled>()
.UseScopedHandler<ValidatePushedEndpointPermissions>()
.UseSingletonHandler<ValidatePushedEndpointPermissions>()
.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<IOpenIddictApplicationManager>()
?? 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
/// </summary>
public sealed class ValidatePushedGrantTypePermissions : IOpenIddictServerHandler<ValidatePushedAuthorizationRequestContext>
{
private readonly IOpenIddictApplicationManager _applicationManager;
public ValidatePushedGrantTypePermissions() => throw new InvalidOperationException(SR.GetResourceString(SR.ID0016));
public ValidatePushedGrantTypePermissions(IOpenIddictApplicationManager applicationManager)
=> _applicationManager = applicationManager ?? throw new ArgumentNullException(nameof(applicationManager));
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
/// </summary>
@ -3797,7 +3648,7 @@ public static partial class OpenIddictServerHandlers
= OpenIddictServerHandlerDescriptor.CreateBuilder<ValidatePushedAuthorizationRequestContext>()
.AddFilter<RequireGrantTypePermissionsEnabled>()
.AddFilter<RequireDegradedModeDisabled>()
.UseScopedHandler<ValidatePushedGrantTypePermissions>()
.UseSingletonHandler<ValidatePushedGrantTypePermissions>()
.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<IOpenIddictApplicationManager>()
?? 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
/// </summary>
public sealed class ValidatePushedResponseTypePermissions : IOpenIddictServerHandler<ValidatePushedAuthorizationRequestContext>
{
private readonly IOpenIddictApplicationManager _applicationManager;
public ValidatePushedResponseTypePermissions() => throw new InvalidOperationException(SR.GetResourceString(SR.ID0016));
public ValidatePushedResponseTypePermissions(IOpenIddictApplicationManager applicationManager)
=> _applicationManager = applicationManager ?? throw new ArgumentNullException(nameof(applicationManager));
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
/// </summary>
@ -3892,7 +3739,7 @@ public static partial class OpenIddictServerHandlers
= OpenIddictServerHandlerDescriptor.CreateBuilder<ValidatePushedAuthorizationRequestContext>()
.AddFilter<RequireResponseTypePermissionsEnabled>()
.AddFilter<RequireDegradedModeDisabled>()
.UseScopedHandler<ValidatePushedResponseTypePermissions>()
.UseSingletonHandler<ValidatePushedResponseTypePermissions>()
.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<IOpenIddictApplicationManager>()
?? 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
/// </summary>
public sealed class ValidatePushedScopePermissions : IOpenIddictServerHandler<ValidatePushedAuthorizationRequestContext>
{
private readonly IOpenIddictApplicationManager _applicationManager;
public ValidatePushedScopePermissions() => throw new InvalidOperationException(SR.GetResourceString(SR.ID0016));
public ValidatePushedScopePermissions(IOpenIddictApplicationManager applicationManager)
=> _applicationManager = applicationManager ?? throw new ArgumentNullException(nameof(applicationManager));
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
/// </summary>
@ -3967,7 +3810,7 @@ public static partial class OpenIddictServerHandlers
= OpenIddictServerHandlerDescriptor.CreateBuilder<ValidatePushedAuthorizationRequestContext>()
.AddFilter<RequireScopePermissionsEnabled>()
.AddFilter<RequireDegradedModeDisabled>()
.UseScopedHandler<ValidatePushedScopePermissions>()
.UseSingletonHandler<ValidatePushedScopePermissions>()
.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<IOpenIddictApplicationManager>()
?? 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
/// </summary>
public sealed class ValidatePushedResourcePermissions : IOpenIddictServerHandler<ValidatePushedAuthorizationRequestContext>
{
private readonly IOpenIddictApplicationManager _applicationManager;
public ValidatePushedResourcePermissions() => throw new InvalidOperationException(SR.GetResourceString(SR.ID0016));
public ValidatePushedResourcePermissions(IOpenIddictApplicationManager applicationManager)
=> _applicationManager = applicationManager ?? throw new ArgumentNullException(nameof(applicationManager));
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
/// </summary>
@ -4028,7 +3867,7 @@ public static partial class OpenIddictServerHandlers
= OpenIddictServerHandlerDescriptor.CreateBuilder<ValidatePushedAuthorizationRequestContext>()
.AddFilter<RequireResourcePermissionsEnabled>()
.AddFilter<RequireDegradedModeDisabled>()
.UseScopedHandler<ValidatePushedResourcePermissions>()
.UseSingletonHandler<ValidatePushedResourcePermissions>()
.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<IOpenIddictApplicationManager>()
?? 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
/// </summary>
public sealed class ValidatePushedProofKeyForCodeExchangeRequirement : IOpenIddictServerHandler<ValidatePushedAuthorizationRequestContext>
{
private readonly IOpenIddictApplicationManager _applicationManager;
public ValidatePushedProofKeyForCodeExchangeRequirement() => throw new InvalidOperationException(SR.GetResourceString(SR.ID0016));
public ValidatePushedProofKeyForCodeExchangeRequirement(IOpenIddictApplicationManager applicationManager)
=> _applicationManager = applicationManager ?? throw new ArgumentNullException(nameof(applicationManager));
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
/// </summary>
public static OpenIddictServerHandlerDescriptor Descriptor { get; }
= OpenIddictServerHandlerDescriptor.CreateBuilder<ValidatePushedAuthorizationRequestContext>()
.AddFilter<RequireDegradedModeDisabled>()
.UseScopedHandler<ValidatePushedProofKeyForCodeExchangeRequirement>()
.UseSingletonHandler<ValidatePushedProofKeyForCodeExchangeRequirement>()
.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<IOpenIddictApplicationManager>()
?? 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);

79
src/OpenIddict.Server/OpenIddictServerHandlers.Device.cs

@ -436,28 +436,13 @@ public static partial class OpenIddictServerHandlers
/// </summary>
public sealed class ValidateScopes : IOpenIddictServerHandler<ValidateDeviceAuthorizationRequestContext>
{
private readonly IOpenIddictScopeManager? _scopeManager;
public ValidateScopes(IOpenIddictScopeManager? scopeManager = null)
=> _scopeManager = scopeManager;
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
/// </summary>
public static OpenIddictServerHandlerDescriptor Descriptor { get; }
= OpenIddictServerHandlerDescriptor.CreateBuilder<ValidateDeviceAuthorizationRequestContext>()
.AddFilter<RequireScopeValidationEnabled>()
.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<IOptionsMonitor<OpenIddictServerOptions>>().CurrentValue;
return options.EnableDegradedMode
? new ValidateScopes()
: new ValidateScopes(provider.GetService<IOpenIddictScopeManager>()
?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)));
})
.UseSingletonHandler<ValidateScopes>()
.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<IOpenIddictScopeManager>()
?? 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
/// </summary>
public sealed class ValidateEndpointPermissions : IOpenIddictServerHandler<ValidateDeviceAuthorizationRequestContext>
{
private readonly IOpenIddictApplicationManager _applicationManager;
public ValidateEndpointPermissions() => throw new InvalidOperationException(SR.GetResourceString(SR.ID0016));
public ValidateEndpointPermissions(IOpenIddictApplicationManager applicationManager)
=> _applicationManager = applicationManager ?? throw new ArgumentNullException(nameof(applicationManager));
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
/// </summary>
@ -583,7 +559,7 @@ public static partial class OpenIddictServerHandlers
.AddFilter<RequireClientIdParameter>()
.AddFilter<RequireDegradedModeDisabled>()
.AddFilter<RequireEndpointPermissionsEnabled>()
.UseScopedHandler<ValidateEndpointPermissions>()
.UseSingletonHandler<ValidateEndpointPermissions>()
.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<IOpenIddictApplicationManager>()
?? 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
/// </summary>
public sealed class ValidateGrantTypePermissions : IOpenIddictServerHandler<ValidateDeviceAuthorizationRequestContext>
{
private readonly IOpenIddictApplicationManager _applicationManager;
public ValidateGrantTypePermissions() => throw new InvalidOperationException(SR.GetResourceString(SR.ID0016));
public ValidateGrantTypePermissions(IOpenIddictApplicationManager applicationManager)
=> _applicationManager = applicationManager ?? throw new ArgumentNullException(nameof(applicationManager));
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
/// </summary>
@ -636,7 +608,7 @@ public static partial class OpenIddictServerHandlers
= OpenIddictServerHandlerDescriptor.CreateBuilder<ValidateDeviceAuthorizationRequestContext>()
.AddFilter<RequireGrantTypePermissionsEnabled>()
.AddFilter<RequireDegradedModeDisabled>()
.UseScopedHandler<ValidateGrantTypePermissions>()
.UseSingletonHandler<ValidateGrantTypePermissions>()
.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<IOpenIddictApplicationManager>()
?? 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
/// </summary>
public sealed class ValidateScopePermissions : IOpenIddictServerHandler<ValidateDeviceAuthorizationRequestContext>
{
private readonly IOpenIddictApplicationManager _applicationManager;
public ValidateScopePermissions() => throw new InvalidOperationException(SR.GetResourceString(SR.ID0016));
public ValidateScopePermissions(IOpenIddictApplicationManager applicationManager)
=> _applicationManager = applicationManager ?? throw new ArgumentNullException(nameof(applicationManager));
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
/// </summary>
@ -703,7 +671,7 @@ public static partial class OpenIddictServerHandlers
.AddFilter<RequireClientIdParameter>()
.AddFilter<RequireDegradedModeDisabled>()
.AddFilter<RequireScopePermissionsEnabled>()
.UseScopedHandler<ValidateScopePermissions>()
.UseSingletonHandler<ValidateScopePermissions>()
.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<IOpenIddictApplicationManager>()
?? 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);

152
src/OpenIddict.Server/OpenIddictServerHandlers.Exchange.cs

@ -1002,28 +1002,13 @@ public static partial class OpenIddictServerHandlers
/// </summary>
public sealed class ValidateScopes : IOpenIddictServerHandler<ValidateTokenRequestContext>
{
private readonly IOpenIddictScopeManager? _scopeManager;
public ValidateScopes(IOpenIddictScopeManager? scopeManager = null)
=> _scopeManager = scopeManager;
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
/// </summary>
public static OpenIddictServerHandlerDescriptor Descriptor { get; }
= OpenIddictServerHandlerDescriptor.CreateBuilder<ValidateTokenRequestContext>()
.AddFilter<RequireScopeValidationEnabled>()
.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<IOptionsMonitor<OpenIddictServerOptions>>().CurrentValue;
return options.EnableDegradedMode
? new ValidateScopes()
: new ValidateScopes(provider.GetService<IOpenIddictScopeManager>()
?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)));
})
.UseSingletonHandler<ValidateScopes>()
.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<IOpenIddictScopeManager>()
?? 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
/// </summary>
public sealed class ValidateResources : IOpenIddictServerHandler<ValidateTokenRequestContext>
{
private readonly IOpenIddictResourceManager? _resourceManager;
public ValidateResources(IOpenIddictResourceManager? resourceManager = null)
=> _resourceManager = resourceManager;
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
/// </summary>
public static OpenIddictServerHandlerDescriptor Descriptor { get; }
= OpenIddictServerHandlerDescriptor.CreateBuilder<ValidateTokenRequestContext>()
.AddFilter<RequireResourceValidationEnabled>()
.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<IOptionsMonitor<OpenIddictServerOptions>>().CurrentValue;
return options.EnableDegradedMode
? new ValidateResources()
: new ValidateResources(provider.GetService<IOpenIddictResourceManager>()
?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)));
})
.UseSingletonHandler<ValidateResources>()
.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<IOpenIddictResourceManager>()
?? 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
/// </summary>
public sealed class ValidateEndpointPermissions : IOpenIddictServerHandler<ValidateTokenRequestContext>
{
private readonly IOpenIddictApplicationManager _applicationManager;
public ValidateEndpointPermissions() => throw new InvalidOperationException(SR.GetResourceString(SR.ID0016));
public ValidateEndpointPermissions(IOpenIddictApplicationManager applicationManager)
=> _applicationManager = applicationManager ?? throw new ArgumentNullException(nameof(applicationManager));
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
/// </summary>
@ -1272,7 +1231,7 @@ public static partial class OpenIddictServerHandlers
.AddFilter<RequireClientIdParameter>()
.AddFilter<RequireDegradedModeDisabled>()
.AddFilter<RequireEndpointPermissionsEnabled>()
.UseScopedHandler<ValidateEndpointPermissions>()
.UseSingletonHandler<ValidateEndpointPermissions>()
.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<IOpenIddictApplicationManager>()
?? 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
/// </summary>
public sealed class ValidateGrantTypePermissions : IOpenIddictServerHandler<ValidateTokenRequestContext>
{
private readonly IOpenIddictApplicationManager _applicationManager;
public ValidateGrantTypePermissions() => throw new InvalidOperationException(SR.GetResourceString(SR.ID0016));
public ValidateGrantTypePermissions(IOpenIddictApplicationManager applicationManager)
=> _applicationManager = applicationManager ?? throw new ArgumentNullException(nameof(applicationManager));
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
/// </summary>
@ -1324,7 +1279,7 @@ public static partial class OpenIddictServerHandlers
.AddFilter<RequireClientIdParameter>()
.AddFilter<RequireDegradedModeDisabled>()
.AddFilter<RequireGrantTypePermissionsEnabled>()
.UseScopedHandler<ValidateGrantTypePermissions>()
.UseSingletonHandler<ValidateGrantTypePermissions>()
.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<IOpenIddictApplicationManager>()
?? 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
/// </summary>
public sealed class ValidateScopePermissions : IOpenIddictServerHandler<ValidateTokenRequestContext>
{
private readonly IOpenIddictApplicationManager _applicationManager;
public ValidateScopePermissions() => throw new InvalidOperationException(SR.GetResourceString(SR.ID0016));
public ValidateScopePermissions(IOpenIddictApplicationManager applicationManager)
=> _applicationManager = applicationManager ?? throw new ArgumentNullException(nameof(applicationManager));
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
/// </summary>
@ -1391,7 +1342,7 @@ public static partial class OpenIddictServerHandlers
.AddFilter<RequireClientIdParameter>()
.AddFilter<RequireDegradedModeDisabled>()
.AddFilter<RequireScopePermissionsEnabled>()
.UseScopedHandler<ValidateScopePermissions>()
.UseSingletonHandler<ValidateScopePermissions>()
.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<IOpenIddictApplicationManager>()
?? 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
/// </summary>
public sealed class ValidateAudiencePermissions : IOpenIddictServerHandler<ValidateTokenRequestContext>
{
private readonly IOpenIddictApplicationManager _applicationManager;
public ValidateAudiencePermissions() => throw new InvalidOperationException(SR.GetResourceString(SR.ID0016));
public ValidateAudiencePermissions(IOpenIddictApplicationManager applicationManager)
=> _applicationManager = applicationManager ?? throw new ArgumentNullException(nameof(applicationManager));
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
/// </summary>
@ -1453,7 +1400,7 @@ public static partial class OpenIddictServerHandlers
.AddFilter<RequireClientIdParameter>()
.AddFilter<RequireDegradedModeDisabled>()
.AddFilter<RequireAudiencePermissionsEnabled>()
.UseScopedHandler<ValidateAudiencePermissions>()
.UseSingletonHandler<ValidateAudiencePermissions>()
.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<IOpenIddictApplicationManager>()
?? 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
/// </summary>
public sealed class ValidateResourcePermissions : IOpenIddictServerHandler<ValidateTokenRequestContext>
{
private readonly IOpenIddictApplicationManager _applicationManager;
public ValidateResourcePermissions() => throw new InvalidOperationException(SR.GetResourceString(SR.ID0016));
public ValidateResourcePermissions(IOpenIddictApplicationManager applicationManager)
=> _applicationManager = applicationManager ?? throw new ArgumentNullException(nameof(applicationManager));
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
/// </summary>
@ -1508,7 +1451,7 @@ public static partial class OpenIddictServerHandlers
.AddFilter<RequireClientIdParameter>()
.AddFilter<RequireDegradedModeDisabled>()
.AddFilter<RequireResourcePermissionsEnabled>()
.UseScopedHandler<ValidateResourcePermissions>()
.UseSingletonHandler<ValidateResourcePermissions>()
.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<IOpenIddictApplicationManager>()
?? 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
/// </summary>
public sealed class ValidateProofKeyForCodeExchangeRequirement : IOpenIddictServerHandler<ValidateTokenRequestContext>
{
private readonly IOpenIddictApplicationManager _applicationManager;
public ValidateProofKeyForCodeExchangeRequirement() => throw new InvalidOperationException(SR.GetResourceString(SR.ID0016));
public ValidateProofKeyForCodeExchangeRequirement(IOpenIddictApplicationManager applicationManager)
=> _applicationManager = applicationManager ?? throw new ArgumentNullException(nameof(applicationManager));
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
/// </summary>
@ -1562,7 +1501,7 @@ public static partial class OpenIddictServerHandlers
= OpenIddictServerHandlerDescriptor.CreateBuilder<ValidateTokenRequestContext>()
.AddFilter<RequireClientIdParameter>()
.AddFilter<RequireDegradedModeDisabled>()
.UseScopedHandler<ValidateProofKeyForCodeExchangeRequirement>()
.UseSingletonHandler<ValidateProofKeyForCodeExchangeRequirement>()
.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<IOpenIddictApplicationManager>()
?? 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);

33
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
/// </summary>
public sealed class ValidateEndpointPermissions : IOpenIddictServerHandler<ValidateIntrospectionRequestContext>
{
private readonly IOpenIddictApplicationManager _applicationManager;
public ValidateEndpointPermissions() => throw new InvalidOperationException(SR.GetResourceString(SR.ID0016));
public ValidateEndpointPermissions(IOpenIddictApplicationManager applicationManager)
=> _applicationManager = applicationManager ?? throw new ArgumentNullException(nameof(applicationManager));
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
/// </summary>
@ -516,7 +510,7 @@ public static partial class OpenIddictServerHandlers
.AddFilter<RequireClientIdParameter>()
.AddFilter<RequireDegradedModeDisabled>()
.AddFilter<RequireEndpointPermissionsEnabled>()
.UseScopedHandler<ValidateEndpointPermissions>()
.UseSingletonHandler<ValidateEndpointPermissions>()
.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<IOpenIddictApplicationManager>()
?? 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
/// </summary>
public sealed class AttachApplicationClaims : IOpenIddictServerHandler<HandleIntrospectionRequestContext>
{
private readonly IOpenIddictApplicationManager _applicationManager;
public AttachApplicationClaims() => throw new InvalidOperationException(SR.GetResourceString(SR.ID0016));
public AttachApplicationClaims(IOpenIddictApplicationManager applicationManager)
=> _applicationManager = applicationManager ?? throw new ArgumentNullException(nameof(applicationManager));
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
/// </summary>
@ -788,7 +778,7 @@ public static partial class OpenIddictServerHandlers
= OpenIddictServerHandlerDescriptor.CreateBuilder<HandleIntrospectionRequestContext>()
.AddFilter<RequireClientIdParameter>()
.AddFilter<RequireDegradedModeDisabled>()
.UseScopedHandler<AttachApplicationClaims>()
.UseSingletonHandler<AttachApplicationClaims>()
.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<IOpenIddictApplicationManager>()
?? 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);

168
src/OpenIddict.Server/OpenIddictServerHandlers.Protection.cs

@ -62,27 +62,12 @@ public static partial class OpenIddictServerHandlers
/// </summary>
public sealed class ResolveTokenValidationParameters : IOpenIddictServerHandler<ValidateTokenContext>
{
private readonly IOpenIddictApplicationManager? _applicationManager;
public ResolveTokenValidationParameters(IOpenIddictApplicationManager? applicationManager = null)
=> _applicationManager = applicationManager;
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
/// </summary>
public static OpenIddictServerHandlerDescriptor Descriptor { get; }
= OpenIddictServerHandlerDescriptor.CreateBuilder<ValidateTokenContext>()
.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<IOptionsMonitor<OpenIddictServerOptions>>().CurrentValue;
return options.EnableDegradedMode
? new ResolveTokenValidationParameters()
: new ResolveTokenValidationParameters(provider.GetService<IOpenIddictApplicationManager>()
?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)));
})
.UseSingletonHandler<ResolveTokenValidationParameters>()
.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<IOpenIddictApplicationManager>()
?? 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
/// </summary>
public sealed class ValidateReferenceTokenIdentifier : IOpenIddictServerHandler<ValidateTokenContext>
{
private readonly IOpenIddictTokenManager _tokenManager;
public ValidateReferenceTokenIdentifier() => throw new InvalidOperationException(SR.GetResourceString(SR.ID0016));
public ValidateReferenceTokenIdentifier(IOpenIddictTokenManager tokenManager)
=> _tokenManager = tokenManager ?? throw new ArgumentNullException(nameof(tokenManager));
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
/// </summary>
@ -336,7 +312,7 @@ public static partial class OpenIddictServerHandlers
= OpenIddictServerHandlerDescriptor.CreateBuilder<ValidateTokenContext>()
.AddFilter<RequireDegradedModeDisabled>()
.AddFilter<RequireTokenStorageEnabled>()
.UseScopedHandler<ValidateReferenceTokenIdentifier>()
.UseSingletonHandler<ValidateReferenceTokenIdentifier>()
.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<IOpenIddictTokenManager>()
?? 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
/// </summary>
public sealed class RestoreTokenEntryProperties : IOpenIddictServerHandler<ValidateTokenContext>
{
private readonly IOpenIddictTokenManager _tokenManager;
public RestoreTokenEntryProperties() => throw new InvalidOperationException(SR.GetResourceString(SR.ID0016));
public RestoreTokenEntryProperties(IOpenIddictTokenManager tokenManager)
=> _tokenManager = tokenManager ?? throw new ArgumentNullException(nameof(tokenManager));
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
/// </summary>
@ -767,7 +739,7 @@ public static partial class OpenIddictServerHandlers
= OpenIddictServerHandlerDescriptor.CreateBuilder<ValidateTokenContext>()
.AddFilter<RequireDegradedModeDisabled>()
.AddFilter<RequireTokenStorageEnabled>()
.UseScopedHandler<RestoreTokenEntryProperties>()
.UseSingletonHandler<RestoreTokenEntryProperties>()
.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<IOpenIddictTokenManager>()
?? 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
/// </summary>
public sealed class ValidateTokenEntry : IOpenIddictServerHandler<ValidateTokenContext>
{
private readonly IOpenIddictTokenManager _tokenManager;
public ValidateTokenEntry() => throw new InvalidOperationException(SR.GetResourceString(SR.ID0016));
public ValidateTokenEntry(IOpenIddictTokenManager tokenManager)
=> _tokenManager = tokenManager ?? throw new ArgumentNullException(nameof(tokenManager));
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
/// </summary>
@ -1224,7 +1192,7 @@ public static partial class OpenIddictServerHandlers
.AddFilter<RequireDegradedModeDisabled>()
.AddFilter<RequireTokenStorageEnabled>()
.AddFilter<RequireTokenIdResolved>()
.UseScopedHandler<ValidateTokenEntry>()
.UseSingletonHandler<ValidateTokenEntry>()
.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<IOpenIddictTokenManager>()
?? 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
/// </summary>
public sealed class ValidateAuthorizationEntry : IOpenIddictServerHandler<ValidateTokenContext>
{
private readonly IOpenIddictAuthorizationManager _authorizationManager;
public ValidateAuthorizationEntry() => throw new InvalidOperationException(SR.GetResourceString(SR.ID0016));
public ValidateAuthorizationEntry(IOpenIddictAuthorizationManager authorizationManager)
=> _authorizationManager = authorizationManager ?? throw new ArgumentNullException(nameof(authorizationManager));
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
/// </summary>
@ -1401,7 +1365,7 @@ public static partial class OpenIddictServerHandlers
.AddFilter<RequireDegradedModeDisabled>()
.AddFilter<RequireAuthorizationStorageEnabled>()
.AddFilter<RequireAuthorizationIdResolved>()
.UseScopedHandler<ValidateAuthorizationEntry>()
.UseSingletonHandler<ValidateAuthorizationEntry>()
.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<IOpenIddictAuthorizationManager>()
?? 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
/// </summary>
public sealed class CreateTokenEntry : IOpenIddictServerHandler<GenerateTokenContext>
{
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));
}
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
/// </summary>
@ -1519,7 +1473,7 @@ public static partial class OpenIddictServerHandlers
.AddFilter<RequireDegradedModeDisabled>()
.AddFilter<RequireTokenStorageEnabled>()
.AddFilter<RequireTokenEntryCreated>()
.UseScopedHandler<CreateTokenEntry>()
.UseSingletonHandler<CreateTokenEntry>()
.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<IOpenIddictApplicationManager>()
?? 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<IOpenIddictTokenManager>()
?? 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
/// </summary>
public sealed class AttachTokenPayload : IOpenIddictServerHandler<GenerateTokenContext>
{
private readonly IOpenIddictTokenManager _tokenManager;
public AttachTokenPayload() => throw new InvalidOperationException(SR.GetResourceString(SR.ID0016));
public AttachTokenPayload(IOpenIddictTokenManager tokenManager)
=> _tokenManager = tokenManager ?? throw new ArgumentNullException(nameof(tokenManager));
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
/// </summary>
@ -1799,7 +1752,7 @@ public static partial class OpenIddictServerHandlers
.AddFilter<RequireDegradedModeDisabled>()
.AddFilter<RequireTokenStorageEnabled>()
.AddFilter<RequireTokenPayloadPersisted>()
.UseScopedHandler<AttachTokenPayload>()
.UseSingletonHandler<AttachTokenPayload>()
.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<IOpenIddictTokenManager>()
?? 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);

33
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
/// </summary>
public sealed class ValidateEndpointPermissions : IOpenIddictServerHandler<ValidateRevocationRequestContext>
{
private readonly IOpenIddictApplicationManager _applicationManager;
public ValidateEndpointPermissions() => throw new InvalidOperationException(SR.GetResourceString(SR.ID0016));
public ValidateEndpointPermissions(IOpenIddictApplicationManager applicationManager)
=> _applicationManager = applicationManager ?? throw new ArgumentNullException(nameof(applicationManager));
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
/// </summary>
@ -457,7 +451,7 @@ public static partial class OpenIddictServerHandlers
.AddFilter<RequireClientIdParameter>()
.AddFilter<RequireDegradedModeDisabled>()
.AddFilter<RequireEndpointPermissionsEnabled>()
.UseScopedHandler<ValidateEndpointPermissions>()
.UseSingletonHandler<ValidateEndpointPermissions>()
.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<IOpenIddictApplicationManager>()
?? 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
/// </summary>
public sealed class RevokeToken : IOpenIddictServerHandler<HandleRevocationRequestContext>
{
private readonly IOpenIddictTokenManager _tokenManager;
public RevokeToken() => throw new InvalidOperationException(SR.GetResourceString(SR.ID0016));
public RevokeToken(IOpenIddictTokenManager tokenManager)
=> _tokenManager = tokenManager ?? throw new ArgumentNullException(nameof(tokenManager));
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
/// </summary>
public static OpenIddictServerHandlerDescriptor Descriptor { get; }
= OpenIddictServerHandlerDescriptor.CreateBuilder<HandleRevocationRequestContext>()
.AddFilter<RequireDegradedModeDisabled>()
.UseScopedHandler<RevokeToken>()
.UseSingletonHandler<RevokeToken>()
.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<IOpenIddictTokenManager>()
?? 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,

130
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
/// </summary>
public sealed class ValidateClientPostLogoutRedirectUri : IOpenIddictServerHandler<ValidateEndSessionRequestContext>
{
private readonly IOpenIddictApplicationManager _applicationManager;
public ValidateClientPostLogoutRedirectUri() => throw new InvalidOperationException(SR.GetResourceString(SR.ID0016));
public ValidateClientPostLogoutRedirectUri(IOpenIddictApplicationManager applicationManager)
=> _applicationManager = applicationManager ?? throw new ArgumentNullException(nameof(applicationManager));
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
/// </summary>
@ -569,7 +561,7 @@ public static partial class OpenIddictServerHandlers
= OpenIddictServerHandlerDescriptor.CreateBuilder<ValidateEndSessionRequestContext>()
.AddFilter<RequireDegradedModeDisabled>()
.AddFilter<RequirePostLogoutRedirectUriParameter>()
.UseScopedHandler<ValidateClientPostLogoutRedirectUri>()
.UseSingletonHandler<ValidateClientPostLogoutRedirectUri>()
.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<IOpenIddictApplicationManager>()
?? 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
/// </summary>
public sealed class ValidateEndpointPermissions : IOpenIddictServerHandler<ValidateEndSessionRequestContext>
{
private readonly IOpenIddictApplicationManager _applicationManager;
public ValidateEndpointPermissions() => throw new InvalidOperationException(SR.GetResourceString(SR.ID0016));
public ValidateEndpointPermissions(IOpenIddictApplicationManager applicationManager)
=> _applicationManager = applicationManager ?? throw new ArgumentNullException(nameof(applicationManager));
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
/// </summary>
@ -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<RequireClientIdParameter>()
.UseScopedHandler<ValidateEndpointPermissions>()
.UseSingletonHandler<ValidateEndpointPermissions>()
.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<IOpenIddictApplicationManager>()
?? 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
/// </summary>
public sealed class ValidateAuthorizedParty : IOpenIddictServerHandler<ValidateEndSessionRequestContext>
{
private readonly IOpenIddictApplicationManager? _applicationManager;
public ValidateAuthorizedParty(IOpenIddictApplicationManager? applicationManager = null)
=> _applicationManager = applicationManager;
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
/// </summary>
public static OpenIddictServerHandlerDescriptor Descriptor { get; }
= OpenIddictServerHandlerDescriptor.CreateBuilder<ValidateEndSessionRequestContext>()
.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<IOptionsMonitor<OpenIddictServerOptions>>().CurrentValue;
return options.EnableDegradedMode
? new ValidateAuthorizedParty()
: new ValidateAuthorizedParty(provider.GetService<IOpenIddictApplicationManager>()
?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)));
})
.UseSingletonHandler<ValidateAuthorizedParty>()
.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<IOpenIddictApplicationManager>()
?? 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<bool> 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<bool> 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<string>(StringComparer.Ordinal);
identifiers.UnionWith(principal.GetAudiences());
identifiers.UnionWith(principal.GetPresenters());
var identifiers = new HashSet<string>(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;
}
}
}
}

448
src/OpenIddict.Server/OpenIddictServerHandlers.cs

@ -962,27 +962,12 @@ public static partial class OpenIddictServerHandlers
/// </summary>
public sealed class ValidateClientId : IOpenIddictServerHandler<ProcessAuthenticationContext>
{
private readonly IOpenIddictApplicationManager? _applicationManager;
public ValidateClientId(IOpenIddictApplicationManager? applicationManager = null)
=> _applicationManager = applicationManager;
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
/// </summary>
public static OpenIddictServerHandlerDescriptor Descriptor { get; }
= OpenIddictServerHandlerDescriptor.CreateBuilder<ProcessAuthenticationContext>()
.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<IOptionsMonitor<OpenIddictServerOptions>>().CurrentValue;
return options.EnableDegradedMode
? new ValidateClientId()
: new ValidateClientId(provider.GetService<IOpenIddictApplicationManager>()
?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)));
})
.UseSingletonHandler<ValidateClientId>()
.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<IOpenIddictApplicationManager>()
?? 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
/// </summary>
public sealed class ValidateClientType : IOpenIddictServerHandler<ProcessAuthenticationContext>
{
private readonly IOpenIddictApplicationManager _applicationManager;
public ValidateClientType() => throw new InvalidOperationException(SR.GetResourceString(SR.ID0016));
public ValidateClientType(IOpenIddictApplicationManager applicationManager)
=> _applicationManager = applicationManager ?? throw new ArgumentNullException(nameof(applicationManager));
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
/// </summary>
@ -1092,7 +1068,7 @@ public static partial class OpenIddictServerHandlers
= OpenIddictServerHandlerDescriptor.CreateBuilder<ProcessAuthenticationContext>()
.AddFilter<RequireClientIdParameter>()
.AddFilter<RequireDegradedModeDisabled>()
.UseScopedHandler<ValidateClientType>()
.UseSingletonHandler<ValidateClientType>()
.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<IOpenIddictApplicationManager>()
?? 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
/// </summary>
public sealed class ValidateClientSecret : IOpenIddictServerHandler<ProcessAuthenticationContext>
{
private readonly IOpenIddictApplicationManager _applicationManager;
public ValidateClientSecret() => throw new InvalidOperationException(SR.GetResourceString(SR.ID0016));
public ValidateClientSecret(IOpenIddictApplicationManager applicationManager)
=> _applicationManager = applicationManager ?? throw new ArgumentNullException(nameof(applicationManager));
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
/// </summary>
@ -1202,7 +1174,7 @@ public static partial class OpenIddictServerHandlers
.AddFilter<RequireClientIdParameter>()
.AddFilter<RequireClientSecretParameter>()
.AddFilter<RequireDegradedModeDisabled>()
.UseScopedHandler<ValidateClientSecret>()
.UseSingletonHandler<ValidateClientSecret>()
.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<IOpenIddictApplicationManager>()
?? 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
/// </summary>
public sealed class ValidateClientCertificate : IOpenIddictServerHandler<ProcessAuthenticationContext>
{
private readonly IOpenIddictApplicationManager? _applicationManager;
public ValidateClientCertificate() { }
public ValidateClientCertificate(IOpenIddictApplicationManager applicationManager)
=> _applicationManager = applicationManager ?? throw new ArgumentNullException(nameof(applicationManager));
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
/// </summary>
public static OpenIddictServerHandlerDescriptor Descriptor { get; }
= OpenIddictServerHandlerDescriptor.CreateBuilder<ProcessAuthenticationContext>()
.AddFilter<RequireClientCertificate>()
.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<IOptionsMonitor<OpenIddictServerOptions>>().CurrentValue;
return options.EnableDegradedMode
? new ValidateClientCertificate()
: new ValidateClientCertificate(provider.GetService<IOpenIddictApplicationManager>()
?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)));
})
.UseScopedHandler<ValidateClientCertificate>()
.UseSingletonHandler<ValidateClientCertificate>()
.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<IOpenIddictApplicationManager>()
?? 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
/// </summary>
public sealed class RejectDeviceCodeEntry : IOpenIddictServerHandler<ProcessChallengeContext>
{
private readonly IOpenIddictTokenManager _tokenManager;
public RejectDeviceCodeEntry() => throw new InvalidOperationException(SR.GetResourceString(SR.ID0016));
public RejectDeviceCodeEntry(IOpenIddictTokenManager tokenManager)
=> _tokenManager = tokenManager ?? throw new ArgumentNullException(nameof(tokenManager));
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
/// </summary>
@ -2635,7 +2583,7 @@ public static partial class OpenIddictServerHandlers
= OpenIddictServerHandlerDescriptor.CreateBuilder<ProcessChallengeContext>()
.AddFilter<RequireDegradedModeDisabled>()
.AddFilter<RequireTokenStorageEnabled>()
.UseScopedHandler<RejectDeviceCodeEntry>()
.UseSingletonHandler<RejectDeviceCodeEntry>()
.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<IOpenIddictTokenManager>()
?? 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
/// </summary>
public sealed class RejectUserCodeEntry : IOpenIddictServerHandler<ProcessChallengeContext>
{
private readonly IOpenIddictTokenManager _tokenManager;
public RejectUserCodeEntry() => throw new InvalidOperationException(SR.GetResourceString(SR.ID0016));
public RejectUserCodeEntry(IOpenIddictTokenManager tokenManager)
=> _tokenManager = tokenManager ?? throw new ArgumentNullException(nameof(tokenManager));
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
/// </summary>
@ -2691,7 +2635,7 @@ public static partial class OpenIddictServerHandlers
= OpenIddictServerHandlerDescriptor.CreateBuilder<ProcessChallengeContext>()
.AddFilter<RequireDegradedModeDisabled>()
.AddFilter<RequireTokenStorageEnabled>()
.UseScopedHandler<RejectUserCodeEntry>()
.UseSingletonHandler<RejectUserCodeEntry>()
.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<IOpenIddictTokenManager>()
?? 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
/// </summary>
public sealed class RedeemTokenEntry : IOpenIddictServerHandler<ProcessSignInContext>
{
private readonly IOpenIddictTokenManager _tokenManager;
public RedeemTokenEntry() => throw new InvalidOperationException(SR.GetResourceString(SR.ID0016));
public RedeemTokenEntry(IOpenIddictTokenManager tokenManager)
=> _tokenManager = tokenManager ?? throw new ArgumentNullException(nameof(tokenManager));
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
/// </summary>
@ -2927,7 +2867,7 @@ public static partial class OpenIddictServerHandlers
= OpenIddictServerHandlerDescriptor.CreateBuilder<ProcessSignInContext>()
.AddFilter<RequireDegradedModeDisabled>()
.AddFilter<RequireTokenStorageEnabled>()
.UseScopedHandler<RedeemTokenEntry>()
.UseSingletonHandler<RedeemTokenEntry>()
// 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<IOpenIddictTokenManager>()
?? 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
/// </summary>
public sealed class AttachAuthorization : IOpenIddictServerHandler<ProcessSignInContext>
{
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));
}
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
/// </summary>
@ -3443,7 +3373,7 @@ public static partial class OpenIddictServerHandlers
= OpenIddictServerHandlerDescriptor.CreateBuilder<ProcessSignInContext>()
.AddFilter<RequireDegradedModeDisabled>()
.AddFilter<RequireAuthorizationStorageEnabled>()
.UseScopedHandler<AttachAuthorization>()
.UseSingletonHandler<AttachAuthorization>()
.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<IOpenIddictApplicationManager>()
?? 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<IOpenIddictAuthorizationManager>()
?? 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
/// </summary>
public sealed class PrepareAccessTokenPrincipal : IOpenIddictServerHandler<ProcessSignInContext>
{
private readonly IOpenIddictApplicationManager? _applicationManager;
public PrepareAccessTokenPrincipal(IOpenIddictApplicationManager? applicationManager = null)
=> _applicationManager = applicationManager;
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
/// </summary>
public static OpenIddictServerHandlerDescriptor Descriptor { get; }
= OpenIddictServerHandlerDescriptor.CreateBuilder<ProcessSignInContext>()
.AddFilter<RequireAccessTokenGenerated>()
.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<IOptionsMonitor<OpenIddictServerOptions>>().CurrentValue;
return options.EnableDegradedMode
? new PrepareAccessTokenPrincipal()
: new PrepareAccessTokenPrincipal(provider.GetService<IOpenIddictApplicationManager>()
?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)));
})
.UseSingletonHandler<PrepareAccessTokenPrincipal>()
.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<IOpenIddictApplicationManager>()
?? 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
/// </summary>
public sealed class PrepareAuthorizationCodePrincipal : IOpenIddictServerHandler<ProcessSignInContext>
{
private readonly IOpenIddictApplicationManager? _applicationManager;
public PrepareAuthorizationCodePrincipal(IOpenIddictApplicationManager? applicationManager = null)
=> _applicationManager = applicationManager;
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
/// </summary>
public static OpenIddictServerHandlerDescriptor Descriptor { get; }
= OpenIddictServerHandlerDescriptor.CreateBuilder<ProcessSignInContext>()
.AddFilter<RequireAuthorizationCodeGenerated>()
.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<IOptionsMonitor<OpenIddictServerOptions>>().CurrentValue;
return options.EnableDegradedMode
? new PrepareAuthorizationCodePrincipal()
: new PrepareAuthorizationCodePrincipal(provider.GetService<IOpenIddictApplicationManager>()
?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)));
})
.UseSingletonHandler<PrepareAuthorizationCodePrincipal>()
.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<IOpenIddictApplicationManager>()
?? 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
/// </summary>
public sealed class PrepareDeviceCodePrincipal : IOpenIddictServerHandler<ProcessSignInContext>
{
private readonly IOpenIddictApplicationManager? _applicationManager;
public PrepareDeviceCodePrincipal(IOpenIddictApplicationManager? applicationManager = null)
=> _applicationManager = applicationManager;
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
/// </summary>
public static OpenIddictServerHandlerDescriptor Descriptor { get; }
= OpenIddictServerHandlerDescriptor.CreateBuilder<ProcessSignInContext>()
.AddFilter<RequireDeviceCodeGenerated>()
.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<IOptionsMonitor<OpenIddictServerOptions>>().CurrentValue;
return options.EnableDegradedMode
? new PrepareDeviceCodePrincipal()
: new PrepareDeviceCodePrincipal(provider.GetService<IOpenIddictApplicationManager>()
?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)));
})
.UseSingletonHandler<PrepareDeviceCodePrincipal>()
.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<IOpenIddictApplicationManager>()
?? 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
/// </summary>
public sealed class PrepareIssuedTokenPrincipal : IOpenIddictServerHandler<ProcessSignInContext>
{
private readonly IOpenIddictApplicationManager? _applicationManager;
public PrepareIssuedTokenPrincipal(IOpenIddictApplicationManager? applicationManager = null)
=> _applicationManager = applicationManager;
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
/// </summary>
public static OpenIddictServerHandlerDescriptor Descriptor { get; }
= OpenIddictServerHandlerDescriptor.CreateBuilder<ProcessSignInContext>()
.AddFilter<RequireIssuedTokenGenerated>()
.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<IOptionsMonitor<OpenIddictServerOptions>>().CurrentValue;
return options.EnableDegradedMode
? new PrepareIssuedTokenPrincipal()
: new PrepareIssuedTokenPrincipal(provider.GetService<IOpenIddictApplicationManager>()
?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)));
})
.UseSingletonHandler<PrepareIssuedTokenPrincipal>()
.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<IOpenIddictApplicationManager>()
?? 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<IOpenIddictApplicationManager>()
?? 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
/// </summary>
public sealed class PrepareRequestTokenPrincipal : IOpenIddictServerHandler<ProcessSignInContext>
{
private readonly IOpenIddictApplicationManager? _applicationManager;
public PrepareRequestTokenPrincipal(IOpenIddictApplicationManager? applicationManager = null)
=> _applicationManager = applicationManager;
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
/// </summary>
public static OpenIddictServerHandlerDescriptor Descriptor { get; }
= OpenIddictServerHandlerDescriptor.CreateBuilder<ProcessSignInContext>()
.AddFilter<RequireRequestTokenGenerated>()
.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<IOptionsMonitor<OpenIddictServerOptions>>().CurrentValue;
return options.EnableDegradedMode
? new PrepareRequestTokenPrincipal()
: new PrepareRequestTokenPrincipal(provider.GetService<IOpenIddictApplicationManager>()
?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)));
})
.UseSingletonHandler<PrepareRequestTokenPrincipal>()
.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<IOpenIddictApplicationManager>()
?? 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
/// </summary>
public sealed class PrepareRefreshTokenPrincipal : IOpenIddictServerHandler<ProcessSignInContext>
{
private readonly IOpenIddictApplicationManager? _applicationManager;
public PrepareRefreshTokenPrincipal(IOpenIddictApplicationManager? applicationManager = null)
=> _applicationManager = applicationManager;
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
/// </summary>
public static OpenIddictServerHandlerDescriptor Descriptor { get; }
= OpenIddictServerHandlerDescriptor.CreateBuilder<ProcessSignInContext>()
.AddFilter<RequireRefreshTokenGenerated>()
.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<IOptionsMonitor<OpenIddictServerOptions>>().CurrentValue;
return options.EnableDegradedMode
? new PrepareRefreshTokenPrincipal()
: new PrepareRefreshTokenPrincipal(provider.GetService<IOpenIddictApplicationManager>()
?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)));
})
.UseSingletonHandler<PrepareRefreshTokenPrincipal>()
.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<IOpenIddictApplicationManager>()
?? 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<IOpenIddictApplicationManager>()
?? 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
/// </summary>
public sealed class PrepareIdentityTokenPrincipal : IOpenIddictServerHandler<ProcessSignInContext>
{
private readonly IOpenIddictApplicationManager? _applicationManager;
public PrepareIdentityTokenPrincipal(IOpenIddictApplicationManager? applicationManager = null)
=> _applicationManager = applicationManager;
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
/// </summary>
public static OpenIddictServerHandlerDescriptor Descriptor { get; }
= OpenIddictServerHandlerDescriptor.CreateBuilder<ProcessSignInContext>()
.AddFilter<RequireIdentityTokenGenerated>()
.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<IOptionsMonitor<OpenIddictServerOptions>>().CurrentValue;
return options.EnableDegradedMode
? new PrepareIdentityTokenPrincipal()
: new PrepareIdentityTokenPrincipal(provider.GetService<IOpenIddictApplicationManager>()
?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)));
})
.UseSingletonHandler<PrepareIdentityTokenPrincipal>()
.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<IOpenIddictApplicationManager>()
?? 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
/// </summary>
public sealed class PrepareUserCodePrincipal : IOpenIddictServerHandler<ProcessSignInContext>
{
private readonly IOpenIddictApplicationManager? _applicationManager;
public PrepareUserCodePrincipal(IOpenIddictApplicationManager? applicationManager = null)
=> _applicationManager = applicationManager;
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
/// </summary>
public static OpenIddictServerHandlerDescriptor Descriptor { get; }
= OpenIddictServerHandlerDescriptor.CreateBuilder<ProcessSignInContext>()
.AddFilter<RequireUserCodeGenerated>()
.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<IOptionsMonitor<OpenIddictServerOptions>>().CurrentValue;
return options.EnableDegradedMode
? new PrepareUserCodePrincipal()
: new PrepareUserCodePrincipal(provider.GetService<IOpenIddictApplicationManager>()
?? throw new InvalidOperationException(SR.GetResourceString(SR.ID0016)));
})
.UseSingletonHandler<PrepareUserCodePrincipal>()
.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<IOpenIddictApplicationManager>()
?? 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
/// </summary>
public sealed class UpdateReferenceDeviceCodeEntry : IOpenIddictServerHandler<ProcessSignInContext>
{
private readonly IOpenIddictTokenManager _tokenManager;
public UpdateReferenceDeviceCodeEntry() => throw new InvalidOperationException(SR.GetResourceString(SR.ID0016));
public UpdateReferenceDeviceCodeEntry(IOpenIddictTokenManager tokenManager)
=> _tokenManager = tokenManager ?? throw new ArgumentNullException(nameof(tokenManager));
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
/// </summary>
@ -5232,7 +5021,7 @@ public static partial class OpenIddictServerHandlers
.AddFilter<RequireDegradedModeDisabled>()
.AddFilter<RequireTokenStorageEnabled>()
.AddFilter<RequireDeviceCodeGenerated>()
.UseScopedHandler<UpdateReferenceDeviceCodeEntry>()
.UseSingletonHandler<UpdateReferenceDeviceCodeEntry>()
.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<IOpenIddictTokenManager>()
?? 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
/// </summary>
public sealed class RedeemLogoutTokenEntry : IOpenIddictServerHandler<ProcessSignOutContext>
{
private readonly IOpenIddictTokenManager _tokenManager;
public RedeemLogoutTokenEntry() => throw new InvalidOperationException(SR.GetResourceString(SR.ID0016));
public RedeemLogoutTokenEntry(IOpenIddictTokenManager tokenManager)
=> _tokenManager = tokenManager ?? throw new ArgumentNullException(nameof(tokenManager));
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
/// </summary>
@ -5826,7 +5611,7 @@ public static partial class OpenIddictServerHandlers
.AddFilter<RequireEndSessionRequest>()
.AddFilter<RequireDegradedModeDisabled>()
.AddFilter<RequireTokenStorageEnabled>()
.UseScopedHandler<RedeemLogoutTokenEntry>()
.UseSingletonHandler<RedeemLogoutTokenEntry>()
// 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<IOpenIddictTokenManager>()
?? 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);
}
}

83
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
/// </summary>
public sealed class ValidateReferenceTokenIdentifier : IOpenIddictValidationHandler<ValidateTokenContext>
{
private readonly IOpenIddictTokenManager _tokenManager;
public ValidateReferenceTokenIdentifier() => throw new InvalidOperationException(SR.GetResourceString(SR.ID0139));
public ValidateReferenceTokenIdentifier(IOpenIddictTokenManager tokenManager)
=> _tokenManager = tokenManager ?? throw new ArgumentNullException(nameof(tokenManager));
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
/// </summary>
public static OpenIddictValidationHandlerDescriptor Descriptor { get; }
= OpenIddictValidationHandlerDescriptor.CreateBuilder<ValidateTokenContext>()
.AddFilter<RequireTokenEntryValidationEnabled>()
.UseScopedHandler<ValidateReferenceTokenIdentifier>()
.UseSingletonHandler<ValidateReferenceTokenIdentifier>()
.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<IOpenIddictTokenManager>()
?? 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
/// </summary>
public sealed class RestoreTokenEntryProperties : IOpenIddictValidationHandler<ValidateTokenContext>
{
private readonly IOpenIddictTokenManager _tokenManager;
public RestoreTokenEntryProperties() => throw new InvalidOperationException(SR.GetResourceString(SR.ID0139));
public RestoreTokenEntryProperties(IOpenIddictTokenManager tokenManager)
=> _tokenManager = tokenManager ?? throw new ArgumentNullException(nameof(tokenManager));
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
/// </summary>
public static OpenIddictValidationHandlerDescriptor Descriptor { get; }
= OpenIddictValidationHandlerDescriptor.CreateBuilder<ValidateTokenContext>()
.AddFilter<RequireTokenEntryValidationEnabled>()
.UseScopedHandler<RestoreTokenEntryProperties>()
.UseSingletonHandler<RestoreTokenEntryProperties>()
.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<IOpenIddictTokenManager>()
?? 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
/// </summary>
public sealed class ValidateTokenEntry : IOpenIddictValidationHandler<ValidateTokenContext>
{
private readonly IOpenIddictTokenManager _tokenManager;
public ValidateTokenEntry() => throw new InvalidOperationException(SR.GetResourceString(SR.ID0139));
public ValidateTokenEntry(IOpenIddictTokenManager tokenManager)
=> _tokenManager = tokenManager ?? throw new ArgumentNullException(nameof(tokenManager));
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
/// </summary>
@ -909,7 +895,7 @@ public static partial class OpenIddictValidationHandlers
= OpenIddictValidationHandlerDescriptor.CreateBuilder<ValidateTokenContext>()
.AddFilter<RequireTokenEntryValidationEnabled>()
.AddFilter<RequireTokenIdResolved>()
.UseScopedHandler<ValidateTokenEntry>()
.UseSingletonHandler<ValidateTokenEntry>()
.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<IOpenIddictTokenManager>()
?? 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
/// </summary>
public sealed class ValidateAuthorizationEntry : IOpenIddictValidationHandler<ValidateTokenContext>
{
private readonly IOpenIddictAuthorizationManager _authorizationManager;
public ValidateAuthorizationEntry() => throw new InvalidOperationException(SR.GetResourceString(SR.ID0142));
public ValidateAuthorizationEntry(IOpenIddictAuthorizationManager authorizationManager)
=> _authorizationManager = authorizationManager ?? throw new ArgumentNullException(nameof(authorizationManager));
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
/// </summary>
@ -959,7 +941,7 @@ public static partial class OpenIddictValidationHandlers
= OpenIddictValidationHandlerDescriptor.CreateBuilder<ValidateTokenContext>()
.AddFilter<RequireAuthorizationEntryValidationEnabled>()
.AddFilter<RequireAuthorizationIdResolved>()
.UseScopedHandler<ValidateAuthorizationEntry>()
.UseSingletonHandler<ValidateAuthorizationEntry>()
.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<IOpenIddictAuthorizationManager>()
?? 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);

Loading…
Cancel
Save