From c61f22f589adc39ede38ceb862544890b05fe9ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Chalet?= Date: Fri, 20 Dec 2019 19:00:30 +0100 Subject: [PATCH] Port the authentication integration tests --- .../OpenIddictServerAspNetCoreHandler.cs | 4 +- .../OpenIddictServerDataProtectionHandlers.cs | 30 +- .../OpenIddictServerOwinHandler.cs | 6 +- .../OpenIddictServerConfiguration.cs | 6 +- .../OpenIddictServerEvents.cs | 12 +- .../OpenIddictServerHandlerFilters.cs | 24 +- ...OpenIddictServerHandlers.Authentication.cs | 6 +- .../OpenIddictServerHandlers.Device.cs | 12 +- .../OpenIddictServerHandlers.Discovery.cs | 4 +- .../OpenIddictServerHandlers.Exchange.cs | 6 +- .../OpenIddictServerHandlers.Introspection.cs | 2 +- .../OpenIddictServerHandlers.Revocation.cs | 2 +- .../OpenIddictServerHandlers.Session.cs | 6 +- .../OpenIddictServerHandlers.Userinfo.cs | 2 +- .../OpenIddictServerHandlers.cs | 225 +++++----- ...nIddictServerAspNetCoreIntegrationTests.cs | 265 +++++++++++- .../OpenIddictServerIntegrationTests.cs | 404 ++++++++++++++++++ .../OpenIddictServerOwinIntegrationTests.cs | 261 ++++++++++- 18 files changed, 1090 insertions(+), 187 deletions(-) diff --git a/src/OpenIddict.Server.AspNetCore/OpenIddictServerAspNetCoreHandler.cs b/src/OpenIddict.Server.AspNetCore/OpenIddictServerAspNetCoreHandler.cs index 1f62beaa..7cbc927c 100644 --- a/src/OpenIddict.Server.AspNetCore/OpenIddictServerAspNetCoreHandler.cs +++ b/src/OpenIddict.Server.AspNetCore/OpenIddictServerAspNetCoreHandler.cs @@ -213,7 +213,7 @@ namespace OpenIddict.Server.AspNetCore transaction.Properties[typeof(AuthenticationProperties).FullName] = properties ?? new AuthenticationProperties(); - var context = new ProcessSigninContext(transaction) + var context = new ProcessSignInContext(transaction) { Principal = user, Response = new OpenIddictResponse() @@ -261,7 +261,7 @@ namespace OpenIddict.Server.AspNetCore throw new InvalidOperationException("An OpenID Connect response cannot be returned from this endpoint."); } - var context = new ProcessSignoutContext(transaction) + var context = new ProcessSignOutContext(transaction) { Response = new OpenIddictResponse() }; diff --git a/src/OpenIddict.Server.DataProtection/OpenIddictServerDataProtectionHandlers.cs b/src/OpenIddict.Server.DataProtection/OpenIddictServerDataProtectionHandlers.cs index cbbf2d30..e7ac6d3e 100644 --- a/src/OpenIddict.Server.DataProtection/OpenIddictServerDataProtectionHandlers.cs +++ b/src/OpenIddict.Server.DataProtection/OpenIddictServerDataProtectionHandlers.cs @@ -155,7 +155,7 @@ namespace OpenIddict.Server.DataProtection /// /// Contains the logic responsible of generating an access token using Data Protection. /// - public class GenerateDataProtectionAccessToken : IOpenIddictServerHandler + public class GenerateDataProtectionAccessToken : IOpenIddictServerHandler { private readonly IOptionsMonitor _options; @@ -166,7 +166,7 @@ namespace OpenIddict.Server.DataProtection /// Gets the default descriptor definition assigned to this handler. /// public static OpenIddictServerHandlerDescriptor Descriptor { get; } - = OpenIddictServerHandlerDescriptor.CreateBuilder() + = OpenIddictServerHandlerDescriptor.CreateBuilder() .AddFilter() .AddFilter() .UseSingletonHandler() @@ -180,7 +180,7 @@ namespace OpenIddict.Server.DataProtection /// /// A that can be used to monitor the asynchronous operation. /// - public ValueTask HandleAsync([NotNull] ProcessSigninContext context) + public ValueTask HandleAsync([NotNull] ProcessSignInContext context) { if (context == null) { @@ -219,7 +219,7 @@ namespace OpenIddict.Server.DataProtection /// /// Contains the logic responsible of generating an authorization code using Data Protection. /// - public class GenerateDataProtectionAuthorizationCode : IOpenIddictServerHandler + public class GenerateDataProtectionAuthorizationCode : IOpenIddictServerHandler { private readonly IOptionsMonitor _options; @@ -230,7 +230,7 @@ namespace OpenIddict.Server.DataProtection /// Gets the default descriptor definition assigned to this handler. /// public static OpenIddictServerHandlerDescriptor Descriptor { get; } - = OpenIddictServerHandlerDescriptor.CreateBuilder() + = OpenIddictServerHandlerDescriptor.CreateBuilder() .AddFilter() .AddFilter() .UseSingletonHandler() @@ -244,7 +244,7 @@ namespace OpenIddict.Server.DataProtection /// /// A that can be used to monitor the asynchronous operation. /// - public ValueTask HandleAsync([NotNull] ProcessSigninContext context) + public ValueTask HandleAsync([NotNull] ProcessSignInContext context) { if (context == null) { @@ -283,7 +283,7 @@ namespace OpenIddict.Server.DataProtection /// /// Contains the logic responsible of generating a device code using Data Protection. /// - public class GenerateDataProtectionDeviceCode : IOpenIddictServerHandler + public class GenerateDataProtectionDeviceCode : IOpenIddictServerHandler { private readonly IOptionsMonitor _options; @@ -294,7 +294,7 @@ namespace OpenIddict.Server.DataProtection /// Gets the default descriptor definition assigned to this handler. /// public static OpenIddictServerHandlerDescriptor Descriptor { get; } - = OpenIddictServerHandlerDescriptor.CreateBuilder() + = OpenIddictServerHandlerDescriptor.CreateBuilder() .AddFilter() .AddFilter() .UseSingletonHandler() @@ -308,7 +308,7 @@ namespace OpenIddict.Server.DataProtection /// /// A that can be used to monitor the asynchronous operation. /// - public ValueTask HandleAsync([NotNull] ProcessSigninContext context) + public ValueTask HandleAsync([NotNull] ProcessSignInContext context) { if (context == null) { @@ -347,7 +347,7 @@ namespace OpenIddict.Server.DataProtection /// /// Contains the logic responsible of generating a refresh token using Data Protection. /// - public class GenerateDataProtectionRefreshToken : IOpenIddictServerHandler + public class GenerateDataProtectionRefreshToken : IOpenIddictServerHandler { private readonly IOptionsMonitor _options; @@ -358,7 +358,7 @@ namespace OpenIddict.Server.DataProtection /// Gets the default descriptor definition assigned to this handler. /// public static OpenIddictServerHandlerDescriptor Descriptor { get; } - = OpenIddictServerHandlerDescriptor.CreateBuilder() + = OpenIddictServerHandlerDescriptor.CreateBuilder() .AddFilter() .AddFilter() .UseSingletonHandler() @@ -372,7 +372,7 @@ namespace OpenIddict.Server.DataProtection /// /// A that can be used to monitor the asynchronous operation. /// - public ValueTask HandleAsync([NotNull] ProcessSigninContext context) + public ValueTask HandleAsync([NotNull] ProcessSignInContext context) { if (context == null) { @@ -411,7 +411,7 @@ namespace OpenIddict.Server.DataProtection /// /// Contains the logic responsible of generating a user code using Data Protection. /// - public class GenerateDataProtectionUserCode : IOpenIddictServerHandler + public class GenerateDataProtectionUserCode : IOpenIddictServerHandler { private readonly IOptionsMonitor _options; @@ -422,7 +422,7 @@ namespace OpenIddict.Server.DataProtection /// Gets the default descriptor definition assigned to this handler. /// public static OpenIddictServerHandlerDescriptor Descriptor { get; } - = OpenIddictServerHandlerDescriptor.CreateBuilder() + = OpenIddictServerHandlerDescriptor.CreateBuilder() .AddFilter() .AddFilter() .UseSingletonHandler() @@ -436,7 +436,7 @@ namespace OpenIddict.Server.DataProtection /// /// A that can be used to monitor the asynchronous operation. /// - public ValueTask HandleAsync([NotNull] ProcessSigninContext context) + public ValueTask HandleAsync([NotNull] ProcessSignInContext context) { if (context == null) { diff --git a/src/OpenIddict.Server.Owin/OpenIddictServerOwinHandler.cs b/src/OpenIddict.Server.Owin/OpenIddictServerOwinHandler.cs index 4f0219f8..81cd24f9 100644 --- a/src/OpenIddict.Server.Owin/OpenIddictServerOwinHandler.cs +++ b/src/OpenIddict.Server.Owin/OpenIddictServerOwinHandler.cs @@ -131,7 +131,7 @@ namespace OpenIddict.Server.Owin return new AuthenticationTicket(null, properties); } - return null; + return new AuthenticationTicket((ClaimsIdentity) context.Principal.Identity, new AuthenticationProperties()); } protected override async Task TeardownCoreAsync() @@ -209,7 +209,7 @@ namespace OpenIddict.Server.Owin transaction.Properties[typeof(AuthenticationProperties).FullName] = signin.Properties ?? new AuthenticationProperties(); - var context = new ProcessSigninContext(transaction) + var context = new ProcessSignInContext(transaction) { Principal = signin.Principal, Response = new OpenIddictResponse() @@ -260,7 +260,7 @@ namespace OpenIddict.Server.Owin transaction.Properties[typeof(AuthenticationProperties).FullName] = signout.Properties ?? new AuthenticationProperties(); - var context = new ProcessSignoutContext(transaction) + var context = new ProcessSignOutContext(transaction) { Response = new OpenIddictResponse() }; diff --git a/src/OpenIddict.Server/OpenIddictServerConfiguration.cs b/src/OpenIddict.Server/OpenIddictServerConfiguration.cs index 764f28b8..e6e6a895 100644 --- a/src/OpenIddict.Server/OpenIddictServerConfiguration.cs +++ b/src/OpenIddict.Server/OpenIddictServerConfiguration.cs @@ -228,13 +228,13 @@ namespace OpenIddict.Server } if (!options.CustomHandlers.Any( - descriptor => descriptor.ContextType == typeof(ProcessSigninContext) && + descriptor => descriptor.ContextType == typeof(ProcessSignInContext) && descriptor.FilterTypes.All(type => !typeof(RequireDegradedModeDisabled).IsAssignableFrom(type)))) { throw new InvalidOperationException(new StringBuilder() .Append("No custom verification sign-in handler was found. When enabling the degraded mode, ") - .Append("a custom 'IOpenIddictServerHandler' must be implemented ") - .Append("to generate device and user codes (e.g by retrieving them from a database).") + .Append("a custom 'IOpenIddictServerHandler' must be implemented ") + .Append("to generate device and user codes and storing them in a database, if applicable.") .ToString()); } } diff --git a/src/OpenIddict.Server/OpenIddictServerEvents.cs b/src/OpenIddict.Server/OpenIddictServerEvents.cs index 56aa463c..dc194131 100644 --- a/src/OpenIddict.Server/OpenIddictServerEvents.cs +++ b/src/OpenIddict.Server/OpenIddictServerEvents.cs @@ -334,12 +334,12 @@ namespace OpenIddict.Server /// /// Represents an event called when processing a sign-in response. /// - public class ProcessSigninContext : BaseValidatingTicketContext + public class ProcessSignInContext : BaseValidatingTicketContext { /// - /// Creates a new instance of the class. + /// Creates a new instance of the class. /// - public ProcessSigninContext([NotNull] OpenIddictServerTransaction transaction) + public ProcessSignInContext([NotNull] OpenIddictServerTransaction transaction) : base(transaction) { } @@ -432,12 +432,12 @@ namespace OpenIddict.Server /// /// Represents an event called when processing a sign-out response. /// - public class ProcessSignoutContext : BaseValidatingContext + public class ProcessSignOutContext : BaseValidatingContext { /// - /// Creates a new instance of the class. + /// Creates a new instance of the class. /// - public ProcessSignoutContext([NotNull] OpenIddictServerTransaction transaction) + public ProcessSignOutContext([NotNull] OpenIddictServerTransaction transaction) : base(transaction) { } diff --git a/src/OpenIddict.Server/OpenIddictServerHandlerFilters.cs b/src/OpenIddict.Server/OpenIddictServerHandlerFilters.cs index cde9e180..f2135d19 100644 --- a/src/OpenIddict.Server/OpenIddictServerHandlerFilters.cs +++ b/src/OpenIddict.Server/OpenIddictServerHandlerFilters.cs @@ -18,9 +18,9 @@ namespace OpenIddict.Server /// /// Represents a filter that excludes the associated handlers if no access token is returned. /// - public class RequireAccessTokenIncluded : IOpenIddictServerHandlerFilter + public class RequireAccessTokenIncluded : IOpenIddictServerHandlerFilter { - public ValueTask IsActiveAsync([NotNull] ProcessSigninContext context) + public ValueTask IsActiveAsync([NotNull] ProcessSignInContext context) { if (context == null) { @@ -34,9 +34,9 @@ namespace OpenIddict.Server /// /// Represents a filter that excludes the associated handlers if no authorization code is returned. /// - public class RequireAuthorizationCodeIncluded : IOpenIddictServerHandlerFilter + public class RequireAuthorizationCodeIncluded : IOpenIddictServerHandlerFilter { - public ValueTask IsActiveAsync([NotNull] ProcessSigninContext context) + public ValueTask IsActiveAsync([NotNull] ProcessSignInContext context) { if (context == null) { @@ -98,9 +98,9 @@ namespace OpenIddict.Server /// /// Represents a filter that excludes the associated handlers if no device code is returned. /// - public class RequireDeviceCodeIncluded : IOpenIddictServerHandlerFilter + public class RequireDeviceCodeIncluded : IOpenIddictServerHandlerFilter { - public ValueTask IsActiveAsync([NotNull] ProcessSigninContext context) + public ValueTask IsActiveAsync([NotNull] ProcessSignInContext context) { if (context == null) { @@ -146,9 +146,9 @@ namespace OpenIddict.Server /// /// Represents a filter that excludes the associated handlers if no identity token is returned. /// - public class RequireIdentityTokenIncluded : IOpenIddictServerHandlerFilter + public class RequireIdentityTokenIncluded : IOpenIddictServerHandlerFilter { - public ValueTask IsActiveAsync([NotNull] ProcessSigninContext context) + public ValueTask IsActiveAsync([NotNull] ProcessSignInContext context) { if (context == null) { @@ -194,9 +194,9 @@ namespace OpenIddict.Server /// /// Represents a filter that excludes the associated handlers if no refresh token is returned. /// - public class RequireRefreshTokenIncluded : IOpenIddictServerHandlerFilter + public class RequireRefreshTokenIncluded : IOpenIddictServerHandlerFilter { - public ValueTask IsActiveAsync([NotNull] ProcessSigninContext context) + public ValueTask IsActiveAsync([NotNull] ProcessSignInContext context) { if (context == null) { @@ -306,9 +306,9 @@ namespace OpenIddict.Server /// /// Represents a filter that excludes the associated handlers if no user code is returned. /// - public class RequireUserCodeIncluded : IOpenIddictServerHandlerFilter + public class RequireUserCodeIncluded : IOpenIddictServerHandlerFilter { - public ValueTask IsActiveAsync([NotNull] ProcessSigninContext context) + public ValueTask IsActiveAsync([NotNull] ProcessSignInContext context) { if (context == null) { diff --git a/src/OpenIddict.Server/OpenIddictServerHandlers.Authentication.cs b/src/OpenIddict.Server/OpenIddictServerHandlers.Authentication.cs index f2990025..d1820de5 100644 --- a/src/OpenIddict.Server/OpenIddictServerHandlers.Authentication.cs +++ b/src/OpenIddict.Server/OpenIddictServerHandlers.Authentication.cs @@ -33,7 +33,7 @@ namespace OpenIddict.Server ApplyAuthorizationResponse.Descriptor, ApplyAuthorizationResponse.Descriptor, ApplyAuthorizationResponse.Descriptor, - ApplyAuthorizationResponse.Descriptor, + ApplyAuthorizationResponse.Descriptor, /* * Authorization request validation: @@ -80,7 +80,7 @@ namespace OpenIddict.Server public static OpenIddictServerHandlerDescriptor Descriptor { get; } = OpenIddictServerHandlerDescriptor.CreateBuilder() .UseScopedHandler() - .SetOrder(int.MinValue + 100_000) + .SetOrder(100_000) .Build(); /// @@ -278,7 +278,7 @@ namespace OpenIddict.Server if (notification.Principal != null) { - var @event = new ProcessSigninContext(context.Transaction) + var @event = new ProcessSignInContext(context.Transaction) { Principal = notification.Principal, Response = new OpenIddictResponse() diff --git a/src/OpenIddict.Server/OpenIddictServerHandlers.Device.cs b/src/OpenIddict.Server/OpenIddictServerHandlers.Device.cs index 2207a761..28cacd4e 100644 --- a/src/OpenIddict.Server/OpenIddictServerHandlers.Device.cs +++ b/src/OpenIddict.Server/OpenIddictServerHandlers.Device.cs @@ -33,7 +33,7 @@ namespace OpenIddict.Server ApplyDeviceResponse.Descriptor, ApplyDeviceResponse.Descriptor, ApplyDeviceResponse.Descriptor, - ApplyDeviceResponse.Descriptor, + ApplyDeviceResponse.Descriptor, /* * Device request validation: @@ -55,7 +55,7 @@ namespace OpenIddict.Server ApplyVerificationResponse.Descriptor, ApplyVerificationResponse.Descriptor, ApplyVerificationResponse.Descriptor, - ApplyVerificationResponse.Descriptor, + ApplyVerificationResponse.Descriptor, /* * Verification request handling: @@ -78,7 +78,7 @@ namespace OpenIddict.Server public static OpenIddictServerHandlerDescriptor Descriptor { get; } = OpenIddictServerHandlerDescriptor.CreateBuilder() .UseScopedHandler() - .SetOrder(int.MinValue + 100_000) + .SetOrder(100_000) .Build(); /// @@ -265,7 +265,7 @@ namespace OpenIddict.Server return; } - var @event = new ProcessSigninContext(context.Transaction) + var @event = new ProcessSignInContext(context.Transaction) { Principal = notification.Principal, Response = new OpenIddictResponse() @@ -860,7 +860,7 @@ namespace OpenIddict.Server public static OpenIddictServerHandlerDescriptor Descriptor { get; } = OpenIddictServerHandlerDescriptor.CreateBuilder() .UseScopedHandler() - .SetOrder(int.MinValue + 100_000) + .SetOrder(100_000) .Build(); /// @@ -1049,7 +1049,7 @@ namespace OpenIddict.Server if (notification.Principal != null) { - var @event = new ProcessSigninContext(context.Transaction) + var @event = new ProcessSignInContext(context.Transaction) { Principal = notification.Principal, Response = new OpenIddictResponse() diff --git a/src/OpenIddict.Server/OpenIddictServerHandlers.Discovery.cs b/src/OpenIddict.Server/OpenIddictServerHandlers.Discovery.cs index 6d56ceb6..6bc42abb 100644 --- a/src/OpenIddict.Server/OpenIddictServerHandlers.Discovery.cs +++ b/src/OpenIddict.Server/OpenIddictServerHandlers.Discovery.cs @@ -82,7 +82,7 @@ namespace OpenIddict.Server public static OpenIddictServerHandlerDescriptor Descriptor { get; } = OpenIddictServerHandlerDescriptor.CreateBuilder() .UseScopedHandler() - .SetOrder(int.MinValue + 100_000) + .SetOrder(100_000) .Build(); /// @@ -911,7 +911,7 @@ namespace OpenIddict.Server public static OpenIddictServerHandlerDescriptor Descriptor { get; } = OpenIddictServerHandlerDescriptor.CreateBuilder() .UseScopedHandler() - .SetOrder(int.MinValue + 100_000) + .SetOrder(100_000) .Build(); /// diff --git a/src/OpenIddict.Server/OpenIddictServerHandlers.Exchange.cs b/src/OpenIddict.Server/OpenIddictServerHandlers.Exchange.cs index 4c60ba4f..cc5ab2c3 100644 --- a/src/OpenIddict.Server/OpenIddictServerHandlers.Exchange.cs +++ b/src/OpenIddict.Server/OpenIddictServerHandlers.Exchange.cs @@ -36,7 +36,7 @@ namespace OpenIddict.Server ApplyTokenResponse.Descriptor, ApplyTokenResponse.Descriptor, ApplyTokenResponse.Descriptor, - ApplyTokenResponse.Descriptor, + ApplyTokenResponse.Descriptor, /* * Token request validation: @@ -83,7 +83,7 @@ namespace OpenIddict.Server public static OpenIddictServerHandlerDescriptor Descriptor { get; } = OpenIddictServerHandlerDescriptor.CreateBuilder() .UseScopedHandler() - .SetOrder(int.MinValue + 100_000) + .SetOrder(100_000) .Build(); /// @@ -276,7 +276,7 @@ namespace OpenIddict.Server if (notification.Principal != null) { - var @event = new ProcessSigninContext(context.Transaction) + var @event = new ProcessSignInContext(context.Transaction) { Principal = notification.Principal, Response = new OpenIddictResponse() diff --git a/src/OpenIddict.Server/OpenIddictServerHandlers.Introspection.cs b/src/OpenIddict.Server/OpenIddictServerHandlers.Introspection.cs index afa2902f..8887561c 100644 --- a/src/OpenIddict.Server/OpenIddictServerHandlers.Introspection.cs +++ b/src/OpenIddict.Server/OpenIddictServerHandlers.Introspection.cs @@ -79,7 +79,7 @@ namespace OpenIddict.Server public static OpenIddictServerHandlerDescriptor Descriptor { get; } = OpenIddictServerHandlerDescriptor.CreateBuilder() .UseScopedHandler() - .SetOrder(int.MinValue + 100_000) + .SetOrder(100_000) .Build(); /// diff --git a/src/OpenIddict.Server/OpenIddictServerHandlers.Revocation.cs b/src/OpenIddict.Server/OpenIddictServerHandlers.Revocation.cs index 16894b5b..ef0ea793 100644 --- a/src/OpenIddict.Server/OpenIddictServerHandlers.Revocation.cs +++ b/src/OpenIddict.Server/OpenIddictServerHandlers.Revocation.cs @@ -71,7 +71,7 @@ namespace OpenIddict.Server public static OpenIddictServerHandlerDescriptor Descriptor { get; } = OpenIddictServerHandlerDescriptor.CreateBuilder() .UseScopedHandler() - .SetOrder(int.MinValue + 100_000) + .SetOrder(100_000) .Build(); /// diff --git a/src/OpenIddict.Server/OpenIddictServerHandlers.Session.cs b/src/OpenIddict.Server/OpenIddictServerHandlers.Session.cs index 50b7dfcd..a5b83807 100644 --- a/src/OpenIddict.Server/OpenIddictServerHandlers.Session.cs +++ b/src/OpenIddict.Server/OpenIddictServerHandlers.Session.cs @@ -30,7 +30,7 @@ namespace OpenIddict.Server HandleLogoutRequest.Descriptor, ApplyLogoutResponse.Descriptor, ApplyLogoutResponse.Descriptor, - ApplyLogoutResponse.Descriptor, + ApplyLogoutResponse.Descriptor, /* * Logout request validation: @@ -60,7 +60,7 @@ namespace OpenIddict.Server public static OpenIddictServerHandlerDescriptor Descriptor { get; } = OpenIddictServerHandlerDescriptor.CreateBuilder() .UseScopedHandler() - .SetOrder(int.MinValue + 100_000) + .SetOrder(100_000) .Build(); /// @@ -251,7 +251,7 @@ namespace OpenIddict.Server return; } - var @event = new ProcessSignoutContext(context.Transaction) + var @event = new ProcessSignOutContext(context.Transaction) { Response = new OpenIddictResponse() }; diff --git a/src/OpenIddict.Server/OpenIddictServerHandlers.Userinfo.cs b/src/OpenIddict.Server/OpenIddictServerHandlers.Userinfo.cs index b4b3f8d7..37043568 100644 --- a/src/OpenIddict.Server/OpenIddictServerHandlers.Userinfo.cs +++ b/src/OpenIddict.Server/OpenIddictServerHandlers.Userinfo.cs @@ -61,7 +61,7 @@ namespace OpenIddict.Server public static OpenIddictServerHandlerDescriptor Descriptor { get; } = OpenIddictServerHandlerDescriptor.CreateBuilder() .UseScopedHandler() - .SetOrder(int.MinValue + 100_000) + .SetOrder(100_000) .Build(); /// diff --git a/src/OpenIddict.Server/OpenIddictServerHandlers.cs b/src/OpenIddict.Server/OpenIddictServerHandlers.cs index cc993956..28be5ec0 100644 --- a/src/OpenIddict.Server/OpenIddictServerHandlers.cs +++ b/src/OpenIddict.Server/OpenIddictServerHandlers.cs @@ -150,7 +150,20 @@ namespace OpenIddict.Server case OpenIddictServerEndpointType.Verification: return default; - default: throw new InvalidOperationException("No identity cannot be extracted from this request."); + case OpenIddictServerEndpointType.Token: throw new InvalidOperationException(new StringBuilder() + .AppendLine("An identity cannot be extracted from this token request.") + .Append("This generally indicates that the OpenIddict server stack was asked ") + .AppendLine("to validate a token for an invalid grant type (e.g password).") + .ToString()); + + + default: throw new InvalidOperationException(new StringBuilder() + .AppendLine("An identity cannot be extracted from this request.") + .Append("This generally indicates that the OpenIddict server stack was asked ") + .AppendLine("to validate a token for an endpoint it doesn't manage.") + .Append("To validate tokens received by custom API endpoints, ") + .Append("the OpenIddict validation services must be used instead.") + .ToString()); } } } @@ -1195,13 +1208,13 @@ namespace OpenIddict.Server /// Contains the logic responsible of ensuring that the sign-in demand /// is compatible with the type of the endpoint that handled the request. /// - public class ValidateSigninDemand : IOpenIddictServerHandler + public class ValidateSigninDemand : IOpenIddictServerHandler { /// /// Gets the default descriptor definition assigned to this handler. /// public static OpenIddictServerHandlerDescriptor Descriptor { get; } - = OpenIddictServerHandlerDescriptor.CreateBuilder() + = OpenIddictServerHandlerDescriptor.CreateBuilder() .UseSingletonHandler() .SetOrder(int.MinValue + 100_000) .Build(); @@ -1213,7 +1226,7 @@ namespace OpenIddict.Server /// /// A that can be used to monitor the asynchronous operation. /// - public ValueTask HandleAsync([NotNull] ProcessSigninContext context) + public ValueTask HandleAsync([NotNull] ProcessSignInContext context) { if (context == null) { @@ -1288,13 +1301,13 @@ namespace OpenIddict.Server /// /// Contains the logic responsible of re-attaching internal claims to the authentication principal. /// - public class RestoreInternalClaims : IOpenIddictServerHandler + public class RestoreInternalClaims : IOpenIddictServerHandler { /// /// Gets the default descriptor definition assigned to this handler. /// public static OpenIddictServerHandlerDescriptor Descriptor { get; } - = OpenIddictServerHandlerDescriptor.CreateBuilder() + = OpenIddictServerHandlerDescriptor.CreateBuilder() .UseSingletonHandler() .SetOrder(ValidateSigninDemand.Descriptor.Order + 1_000) .Build(); @@ -1306,7 +1319,7 @@ namespace OpenIddict.Server /// /// A that can be used to monitor the asynchronous operation. /// - public ValueTask HandleAsync([NotNull] ProcessSigninContext context) + public ValueTask HandleAsync([NotNull] ProcessSignInContext context) { if (context == null) { @@ -1359,13 +1372,13 @@ namespace OpenIddict.Server /// /// Contains the logic responsible of attaching default scopes to the authentication principal. /// - public class AttachDefaultScopes : IOpenIddictServerHandler + public class AttachDefaultScopes : IOpenIddictServerHandler { /// /// Gets the default descriptor definition assigned to this handler. /// public static OpenIddictServerHandlerDescriptor Descriptor { get; } - = OpenIddictServerHandlerDescriptor.CreateBuilder() + = OpenIddictServerHandlerDescriptor.CreateBuilder() .UseSingletonHandler() .SetOrder(RestoreInternalClaims.Descriptor.Order + 1_000) .Build(); @@ -1377,7 +1390,7 @@ namespace OpenIddict.Server /// /// A that can be used to monitor the asynchronous operation. /// - public ValueTask HandleAsync([NotNull] ProcessSigninContext context) + public ValueTask HandleAsync([NotNull] ProcessSignInContext context) { if (context == null) { @@ -1399,13 +1412,13 @@ namespace OpenIddict.Server /// /// Contains the logic responsible of attaching default presenters to the authentication principal. /// - public class AttachDefaultPresenters : IOpenIddictServerHandler + public class AttachDefaultPresenters : IOpenIddictServerHandler { /// /// Gets the default descriptor definition assigned to this handler. /// public static OpenIddictServerHandlerDescriptor Descriptor { get; } - = OpenIddictServerHandlerDescriptor.CreateBuilder() + = OpenIddictServerHandlerDescriptor.CreateBuilder() .UseSingletonHandler() .SetOrder(AttachDefaultScopes.Descriptor.Order + 1_000) .Build(); @@ -1417,7 +1430,7 @@ namespace OpenIddict.Server /// /// A that can be used to monitor the asynchronous operation. /// - public ValueTask HandleAsync([NotNull] ProcessSigninContext context) + public ValueTask HandleAsync([NotNull] ProcessSignInContext context) { if (context == null) { @@ -1438,13 +1451,13 @@ namespace OpenIddict.Server /// /// Contains the logic responsible of inferring resources from the audience claims if necessary. /// - public class InferResources : IOpenIddictServerHandler + public class InferResources : IOpenIddictServerHandler { /// /// Gets the default descriptor definition assigned to this handler. /// public static OpenIddictServerHandlerDescriptor Descriptor { get; } - = OpenIddictServerHandlerDescriptor.CreateBuilder() + = OpenIddictServerHandlerDescriptor.CreateBuilder() .UseSingletonHandler() .SetOrder(AttachDefaultPresenters.Descriptor.Order + 1_000) .Build(); @@ -1456,7 +1469,7 @@ namespace OpenIddict.Server /// /// A that can be used to monitor the asynchronous operation. /// - public ValueTask HandleAsync([NotNull] ProcessSigninContext context) + public ValueTask HandleAsync([NotNull] ProcessSignInContext context) { if (context == null) { @@ -1479,13 +1492,13 @@ namespace OpenIddict.Server /// /// Contains the logic responsible of selecting the token types returned to the client application. /// - public class EvaluateReturnedTokens : IOpenIddictServerHandler + public class EvaluateReturnedTokens : IOpenIddictServerHandler { /// /// Gets the default descriptor definition assigned to this handler. /// public static OpenIddictServerHandlerDescriptor Descriptor { get; } - = OpenIddictServerHandlerDescriptor.CreateBuilder() + = OpenIddictServerHandlerDescriptor.CreateBuilder() .UseSingletonHandler() .SetOrder(InferResources.Descriptor.Order + 1_000) .Build(); @@ -1497,7 +1510,7 @@ namespace OpenIddict.Server /// /// A that can be used to monitor the asynchronous operation. /// - public ValueTask HandleAsync([NotNull] ProcessSigninContext context) + public ValueTask HandleAsync([NotNull] ProcessSignInContext context) { if (context == null) { @@ -1580,7 +1593,7 @@ namespace OpenIddict.Server /// Contains the logic responsible of creating an ad-hoc authorization, if necessary. /// Note: this handler is not used when the degraded mode is enabled. /// - public class AttachAuthorization : IOpenIddictServerHandler + public class AttachAuthorization : IOpenIddictServerHandler { private readonly IOpenIddictApplicationManager _applicationManager; private readonly IOpenIddictAuthorizationManager _authorizationManager; @@ -1605,7 +1618,7 @@ namespace OpenIddict.Server /// Gets the default descriptor definition assigned to this handler. /// public static OpenIddictServerHandlerDescriptor Descriptor { get; } - = OpenIddictServerHandlerDescriptor.CreateBuilder() + = OpenIddictServerHandlerDescriptor.CreateBuilder() .AddFilter() .AddFilter() .UseScopedHandler() @@ -1619,7 +1632,7 @@ namespace OpenIddict.Server /// /// A that can be used to monitor the asynchronous operation. /// - public async ValueTask HandleAsync([NotNull] ProcessSigninContext context) + public async ValueTask HandleAsync([NotNull] ProcessSignInContext context) { if (context == null) { @@ -1691,13 +1704,13 @@ namespace OpenIddict.Server /// Contains the logic responsible of preparing and attaching the claims principal /// used to generate the access token, if one is going to be returned. /// - public class PrepareAccessTokenPrincipal : IOpenIddictServerHandler + public class PrepareAccessTokenPrincipal : IOpenIddictServerHandler { /// /// Gets the default descriptor definition assigned to this handler. /// public static OpenIddictServerHandlerDescriptor Descriptor { get; } - = OpenIddictServerHandlerDescriptor.CreateBuilder() + = OpenIddictServerHandlerDescriptor.CreateBuilder() .AddFilter() .UseSingletonHandler() .SetOrder(AttachAuthorization.Descriptor.Order + 1_000) @@ -1710,7 +1723,7 @@ namespace OpenIddict.Server /// /// A that can be used to monitor the asynchronous operation. /// - public ValueTask HandleAsync([NotNull] ProcessSigninContext context) + public ValueTask HandleAsync([NotNull] ProcessSignInContext context) { if (context == null) { @@ -1812,13 +1825,13 @@ namespace OpenIddict.Server /// Contains the logic responsible of preparing and attaching the claims principal /// used to generate the authorization code, if one is going to be returned. /// - public class PrepareAuthorizationCodePrincipal : IOpenIddictServerHandler + public class PrepareAuthorizationCodePrincipal : IOpenIddictServerHandler { /// /// Gets the default descriptor definition assigned to this handler. /// public static OpenIddictServerHandlerDescriptor Descriptor { get; } - = OpenIddictServerHandlerDescriptor.CreateBuilder() + = OpenIddictServerHandlerDescriptor.CreateBuilder() .AddFilter() .UseSingletonHandler() .SetOrder(PrepareAccessTokenPrincipal.Descriptor.Order + 1_000) @@ -1831,7 +1844,7 @@ namespace OpenIddict.Server /// /// A that can be used to monitor the asynchronous operation. /// - public ValueTask HandleAsync([NotNull] ProcessSigninContext context) + public ValueTask HandleAsync([NotNull] ProcessSignInContext context) { if (context == null) { @@ -1902,13 +1915,13 @@ namespace OpenIddict.Server /// Contains the logic responsible of preparing and attaching the claims principal /// used to generate the device code, if one is going to be returned. /// - public class PrepareDeviceCodePrincipal : IOpenIddictServerHandler + public class PrepareDeviceCodePrincipal : IOpenIddictServerHandler { /// /// Gets the default descriptor definition assigned to this handler. /// public static OpenIddictServerHandlerDescriptor Descriptor { get; } - = OpenIddictServerHandlerDescriptor.CreateBuilder() + = OpenIddictServerHandlerDescriptor.CreateBuilder() .UseSingletonHandler() .SetOrder(PrepareAuthorizationCodePrincipal.Descriptor.Order + 1_000) .Build(); @@ -1920,7 +1933,7 @@ namespace OpenIddict.Server /// /// A that can be used to monitor the asynchronous operation. /// - public ValueTask HandleAsync([NotNull] ProcessSigninContext context) + public ValueTask HandleAsync([NotNull] ProcessSignInContext context) { if (context == null) { @@ -1978,13 +1991,13 @@ namespace OpenIddict.Server /// Contains the logic responsible of preparing and attaching the claims principal /// used to generate the refresh token, if one is going to be returned. /// - public class PrepareRefreshTokenPrincipal : IOpenIddictServerHandler + public class PrepareRefreshTokenPrincipal : IOpenIddictServerHandler { /// /// Gets the default descriptor definition assigned to this handler. /// public static OpenIddictServerHandlerDescriptor Descriptor { get; } - = OpenIddictServerHandlerDescriptor.CreateBuilder() + = OpenIddictServerHandlerDescriptor.CreateBuilder() .AddFilter() .UseSingletonHandler() .SetOrder(PrepareDeviceCodePrincipal.Descriptor.Order + 1_000) @@ -1997,7 +2010,7 @@ namespace OpenIddict.Server /// /// A that can be used to monitor the asynchronous operation. /// - public ValueTask HandleAsync([NotNull] ProcessSigninContext context) + public ValueTask HandleAsync([NotNull] ProcessSignInContext context) { if (context == null) { @@ -2063,13 +2076,13 @@ namespace OpenIddict.Server /// Contains the logic responsible of preparing and attaching the claims principal /// used to generate the identity token, if one is going to be returned. /// - public class PrepareIdentityTokenPrincipal : IOpenIddictServerHandler + public class PrepareIdentityTokenPrincipal : IOpenIddictServerHandler { /// /// Gets the default descriptor definition assigned to this handler. /// public static OpenIddictServerHandlerDescriptor Descriptor { get; } - = OpenIddictServerHandlerDescriptor.CreateBuilder() + = OpenIddictServerHandlerDescriptor.CreateBuilder() .AddFilter() .UseSingletonHandler() .SetOrder(PrepareRefreshTokenPrincipal.Descriptor.Order + 1_000) @@ -2082,7 +2095,7 @@ namespace OpenIddict.Server /// /// A that can be used to monitor the asynchronous operation. /// - public ValueTask HandleAsync([NotNull] ProcessSigninContext context) + public ValueTask HandleAsync([NotNull] ProcessSignInContext context) { if (context == null) { @@ -2174,13 +2187,13 @@ namespace OpenIddict.Server /// Contains the logic responsible of preparing and attaching the claims principal /// used to generate the user code, if one is going to be returned. /// - public class PrepareUserCodePrincipal : IOpenIddictServerHandler + public class PrepareUserCodePrincipal : IOpenIddictServerHandler { /// /// Gets the default descriptor definition assigned to this handler. /// public static OpenIddictServerHandlerDescriptor Descriptor { get; } - = OpenIddictServerHandlerDescriptor.CreateBuilder() + = OpenIddictServerHandlerDescriptor.CreateBuilder() .AddFilter() .UseSingletonHandler() .SetOrder(PrepareIdentityTokenPrincipal.Descriptor.Order + 1_000) @@ -2193,7 +2206,7 @@ namespace OpenIddict.Server /// /// A that can be used to monitor the asynchronous operation. /// - public ValueTask HandleAsync([NotNull] ProcessSigninContext context) + public ValueTask HandleAsync([NotNull] ProcessSignInContext context) { if (context == null) { @@ -2248,7 +2261,7 @@ namespace OpenIddict.Server /// corresponding to the received authorization code or refresh token. /// Note: this handler is not used when the degraded mode is enabled. /// - public class RedeemTokenEntry : IOpenIddictServerHandler + public class RedeemTokenEntry : IOpenIddictServerHandler { private readonly IOpenIddictTokenManager _tokenManager; @@ -2267,7 +2280,7 @@ namespace OpenIddict.Server /// Gets the default descriptor definition assigned to this handler. /// public static OpenIddictServerHandlerDescriptor Descriptor { get; } - = OpenIddictServerHandlerDescriptor.CreateBuilder() + = OpenIddictServerHandlerDescriptor.CreateBuilder() .AddFilter() .AddFilter() .UseScopedHandler() @@ -2281,7 +2294,7 @@ namespace OpenIddict.Server /// /// A that can be used to monitor the asynchronous operation. /// - public async ValueTask HandleAsync([NotNull] ProcessSigninContext context) + public async ValueTask HandleAsync([NotNull] ProcessSignInContext context) { if (context == null) { @@ -2343,7 +2356,7 @@ namespace OpenIddict.Server /// Contains the logic responsible of redeeming the device code entry associated with the user code. /// Note: this handler is not used when the degraded mode is enabled. /// - public class RedeemDeviceCodeEntry : IOpenIddictServerHandler + public class RedeemDeviceCodeEntry : IOpenIddictServerHandler { private readonly IOpenIddictTokenManager _tokenManager; @@ -2362,7 +2375,7 @@ namespace OpenIddict.Server /// Gets the default descriptor definition assigned to this handler. /// public static OpenIddictServerHandlerDescriptor Descriptor { get; } - = OpenIddictServerHandlerDescriptor.CreateBuilder() + = OpenIddictServerHandlerDescriptor.CreateBuilder() .AddFilter() .AddFilter() .UseScopedHandler() @@ -2376,7 +2389,7 @@ namespace OpenIddict.Server /// /// A that can be used to monitor the asynchronous operation. /// - public async ValueTask HandleAsync([NotNull] ProcessSigninContext context) + public async ValueTask HandleAsync([NotNull] ProcessSignInContext context) { if (context == null) { @@ -2416,7 +2429,7 @@ namespace OpenIddict.Server /// Contains the logic responsible of redeeming the user code entry, if applicable. /// Note: this handler is not used when the degraded mode is enabled. /// - public class RedeemUserCodeEntry : IOpenIddictServerHandler + public class RedeemUserCodeEntry : IOpenIddictServerHandler { private readonly IOpenIddictTokenManager _tokenManager; @@ -2435,7 +2448,7 @@ namespace OpenIddict.Server /// Gets the default descriptor definition assigned to this handler. /// public static OpenIddictServerHandlerDescriptor Descriptor { get; } - = OpenIddictServerHandlerDescriptor.CreateBuilder() + = OpenIddictServerHandlerDescriptor.CreateBuilder() .AddFilter() .AddFilter() .UseScopedHandler() @@ -2449,7 +2462,7 @@ namespace OpenIddict.Server /// /// A that can be used to monitor the asynchronous operation. /// - public async ValueTask HandleAsync([NotNull] ProcessSigninContext context) + public async ValueTask HandleAsync([NotNull] ProcessSignInContext context) { if (context == null) { @@ -2484,7 +2497,7 @@ namespace OpenIddict.Server /// Contains the logic responsible of revoking all the tokens that were previously issued. /// Note: this handler is not used when the degraded mode is enabled. /// - public class RevokeExistingTokenEntries : IOpenIddictServerHandler + public class RevokeExistingTokenEntries : IOpenIddictServerHandler { private readonly IOpenIddictTokenManager _tokenManager; @@ -2503,7 +2516,7 @@ namespace OpenIddict.Server /// Gets the default descriptor definition assigned to this handler. /// public static OpenIddictServerHandlerDescriptor Descriptor { get; } - = OpenIddictServerHandlerDescriptor.CreateBuilder() + = OpenIddictServerHandlerDescriptor.CreateBuilder() .AddFilter() .AddFilter() .AddFilter() @@ -2518,7 +2531,7 @@ namespace OpenIddict.Server /// /// A that can be used to monitor the asynchronous operation. /// - public async ValueTask HandleAsync([NotNull] ProcessSigninContext context) + public async ValueTask HandleAsync([NotNull] ProcessSignInContext context) { if (context == null) { @@ -2559,7 +2572,7 @@ namespace OpenIddict.Server /// Contains the logic responsible of extending the lifetime of the refresh token entry. /// Note: this handler is not used when the degraded mode is enabled. /// - public class ExtendRefreshTokenEntry : IOpenIddictServerHandler + public class ExtendRefreshTokenEntry : IOpenIddictServerHandler { private readonly IOpenIddictTokenManager _tokenManager; @@ -2578,7 +2591,7 @@ namespace OpenIddict.Server /// Gets the default descriptor definition assigned to this handler. /// public static OpenIddictServerHandlerDescriptor Descriptor { get; } - = OpenIddictServerHandlerDescriptor.CreateBuilder() + = OpenIddictServerHandlerDescriptor.CreateBuilder() .AddFilter() .AddFilter() .AddFilter() @@ -2594,7 +2607,7 @@ namespace OpenIddict.Server /// /// A that can be used to monitor the asynchronous operation. /// - public async ValueTask HandleAsync([NotNull] ProcessSigninContext context) + public async ValueTask HandleAsync([NotNull] ProcessSignInContext context) { if (context == null) { @@ -2637,13 +2650,13 @@ namespace OpenIddict.Server /// /// Contains the logic responsible of generating an access token using IdentityModel. /// - public class GenerateIdentityModelAccessToken : IOpenIddictServerHandler + public class GenerateIdentityModelAccessToken : IOpenIddictServerHandler { /// /// Gets the default descriptor definition assigned to this handler. /// public static OpenIddictServerHandlerDescriptor Descriptor { get; } - = OpenIddictServerHandlerDescriptor.CreateBuilder() + = OpenIddictServerHandlerDescriptor.CreateBuilder() .AddFilter() .UseSingletonHandler() .SetOrder(ExtendRefreshTokenEntry.Descriptor.Order + 1_000) @@ -2656,7 +2669,7 @@ namespace OpenIddict.Server /// /// A that can be used to monitor the asynchronous operation. /// - public ValueTask HandleAsync([NotNull] ProcessSigninContext context) + public ValueTask HandleAsync([NotNull] ProcessSignInContext context) { if (context == null) { @@ -2707,7 +2720,7 @@ namespace OpenIddict.Server /// Contains the logic responsible of creating a reference access token entry. /// Note: this handler is not used when the degraded mode is enabled. /// - public class CreateReferenceAccessTokenEntry : IOpenIddictServerHandler + public class CreateReferenceAccessTokenEntry : IOpenIddictServerHandler { private readonly IOpenIddictApplicationManager _applicationManager; private readonly IOpenIddictTokenManager _tokenManager; @@ -2732,7 +2745,7 @@ namespace OpenIddict.Server /// Gets the default descriptor definition assigned to this handler. /// public static OpenIddictServerHandlerDescriptor Descriptor { get; } - = OpenIddictServerHandlerDescriptor.CreateBuilder() + = OpenIddictServerHandlerDescriptor.CreateBuilder() .AddFilter() .AddFilter() .AddFilter() @@ -2748,7 +2761,7 @@ namespace OpenIddict.Server /// /// A that can be used to monitor the asynchronous operation. /// - public async ValueTask HandleAsync([NotNull] ProcessSigninContext context) + public async ValueTask HandleAsync([NotNull] ProcessSignInContext context) { if (context == null) { @@ -2807,13 +2820,13 @@ namespace OpenIddict.Server /// /// Contains the logic responsible of generating an authorization code using IdentityModel. /// - public class GenerateIdentityModelAuthorizationCode : IOpenIddictServerHandler + public class GenerateIdentityModelAuthorizationCode : IOpenIddictServerHandler { /// /// Gets the default descriptor definition assigned to this handler. /// public static OpenIddictServerHandlerDescriptor Descriptor { get; } - = OpenIddictServerHandlerDescriptor.CreateBuilder() + = OpenIddictServerHandlerDescriptor.CreateBuilder() .AddFilter() .UseSingletonHandler() .SetOrder(CreateReferenceAccessTokenEntry.Descriptor.Order + 1_000) @@ -2826,7 +2839,7 @@ namespace OpenIddict.Server /// /// A that can be used to monitor the asynchronous operation. /// - public ValueTask HandleAsync([NotNull] ProcessSigninContext context) + public ValueTask HandleAsync([NotNull] ProcessSignInContext context) { if (context == null) { @@ -2885,7 +2898,7 @@ namespace OpenIddict.Server /// Contains the logic responsible of creating a reference authorization code entry. /// Note: this handler is not used when the degraded mode is enabled. /// - public class CreateReferenceAuthorizationCodeEntry : IOpenIddictServerHandler + public class CreateReferenceAuthorizationCodeEntry : IOpenIddictServerHandler { private readonly IOpenIddictApplicationManager _applicationManager; private readonly IOpenIddictTokenManager _tokenManager; @@ -2910,7 +2923,7 @@ namespace OpenIddict.Server /// Gets the default descriptor definition assigned to this handler. /// public static OpenIddictServerHandlerDescriptor Descriptor { get; } - = OpenIddictServerHandlerDescriptor.CreateBuilder() + = OpenIddictServerHandlerDescriptor.CreateBuilder() .AddFilter() .AddFilter() .AddFilter() @@ -2925,7 +2938,7 @@ namespace OpenIddict.Server /// /// A that can be used to monitor the asynchronous operation. /// - public async ValueTask HandleAsync([NotNull] ProcessSigninContext context) + public async ValueTask HandleAsync([NotNull] ProcessSignInContext context) { if (context == null) { @@ -2984,13 +2997,13 @@ namespace OpenIddict.Server /// /// Contains the logic responsible of generating a device code using IdentityModel. /// - public class GenerateIdentityModelDeviceCode : IOpenIddictServerHandler + public class GenerateIdentityModelDeviceCode : IOpenIddictServerHandler { /// /// Gets the default descriptor definition assigned to this handler. /// public static OpenIddictServerHandlerDescriptor Descriptor { get; } - = OpenIddictServerHandlerDescriptor.CreateBuilder() + = OpenIddictServerHandlerDescriptor.CreateBuilder() .AddFilter() .UseSingletonHandler() .SetOrder(CreateReferenceAuthorizationCodeEntry.Descriptor.Order + 1_000) @@ -3003,7 +3016,7 @@ namespace OpenIddict.Server /// /// A that can be used to monitor the asynchronous operation. /// - public ValueTask HandleAsync([NotNull] ProcessSigninContext context) + public ValueTask HandleAsync([NotNull] ProcessSignInContext context) { if (context == null) { @@ -3062,7 +3075,7 @@ namespace OpenIddict.Server /// Contains the logic responsible of creating a reference device code entry. /// Note: this handler is not used when the degraded mode is enabled. /// - public class CreateReferenceDeviceCodeEntry : IOpenIddictServerHandler + public class CreateReferenceDeviceCodeEntry : IOpenIddictServerHandler { private readonly IOpenIddictApplicationManager _applicationManager; private readonly IOpenIddictTokenManager _tokenManager; @@ -3087,7 +3100,7 @@ namespace OpenIddict.Server /// Gets the default descriptor definition assigned to this handler. /// public static OpenIddictServerHandlerDescriptor Descriptor { get; } - = OpenIddictServerHandlerDescriptor.CreateBuilder() + = OpenIddictServerHandlerDescriptor.CreateBuilder() .AddFilter() .AddFilter() .AddFilter() @@ -3102,7 +3115,7 @@ namespace OpenIddict.Server /// /// A that can be used to monitor the asynchronous operation. /// - public async ValueTask HandleAsync([NotNull] ProcessSigninContext context) + public async ValueTask HandleAsync([NotNull] ProcessSignInContext context) { if (context == null) { @@ -3167,7 +3180,7 @@ namespace OpenIddict.Server /// Contains the logic responsible of updating the existing reference device code entry. /// Note: this handler is not used when the degraded mode is enabled. /// - public class UpdateReferenceDeviceCodeEntry : IOpenIddictServerHandler + public class UpdateReferenceDeviceCodeEntry : IOpenIddictServerHandler { private readonly IOpenIddictApplicationManager _applicationManager; private readonly IOpenIddictTokenManager _tokenManager; @@ -3192,7 +3205,7 @@ namespace OpenIddict.Server /// Gets the default descriptor definition assigned to this handler. /// public static OpenIddictServerHandlerDescriptor Descriptor { get; } - = OpenIddictServerHandlerDescriptor.CreateBuilder() + = OpenIddictServerHandlerDescriptor.CreateBuilder() .AddFilter() .AddFilter() .AddFilter() @@ -3207,7 +3220,7 @@ namespace OpenIddict.Server /// /// A that can be used to monitor the asynchronous operation. /// - public async ValueTask HandleAsync([NotNull] ProcessSigninContext context) + public async ValueTask HandleAsync([NotNull] ProcessSignInContext context) { if (context == null) { @@ -3262,13 +3275,13 @@ namespace OpenIddict.Server /// /// Contains the logic responsible of generating a refresh token using IdentityModel. /// - public class GenerateIdentityModelRefreshToken : IOpenIddictServerHandler + public class GenerateIdentityModelRefreshToken : IOpenIddictServerHandler { /// /// Gets the default descriptor definition assigned to this handler. /// public static OpenIddictServerHandlerDescriptor Descriptor { get; } - = OpenIddictServerHandlerDescriptor.CreateBuilder() + = OpenIddictServerHandlerDescriptor.CreateBuilder() .AddFilter() .UseSingletonHandler() .SetOrder(UpdateReferenceDeviceCodeEntry.Descriptor.Order + 1_000) @@ -3281,7 +3294,7 @@ namespace OpenIddict.Server /// /// A that can be used to monitor the asynchronous operation. /// - public ValueTask HandleAsync([NotNull] ProcessSigninContext context) + public ValueTask HandleAsync([NotNull] ProcessSignInContext context) { if (context == null) { @@ -3340,7 +3353,7 @@ namespace OpenIddict.Server /// Contains the logic responsible of creating a reference refresh token entry. /// Note: this handler is not used when the degraded mode is enabled. /// - public class CreateReferenceRefreshTokenEntry : IOpenIddictServerHandler + public class CreateReferenceRefreshTokenEntry : IOpenIddictServerHandler { private readonly IOpenIddictApplicationManager _applicationManager; private readonly IOpenIddictTokenManager _tokenManager; @@ -3365,7 +3378,7 @@ namespace OpenIddict.Server /// Gets the default descriptor definition assigned to this handler. /// public static OpenIddictServerHandlerDescriptor Descriptor { get; } - = OpenIddictServerHandlerDescriptor.CreateBuilder() + = OpenIddictServerHandlerDescriptor.CreateBuilder() .AddFilter() .AddFilter() .AddFilter() @@ -3380,7 +3393,7 @@ namespace OpenIddict.Server /// /// A that can be used to monitor the asynchronous operation. /// - public async ValueTask HandleAsync([NotNull] ProcessSigninContext context) + public async ValueTask HandleAsync([NotNull] ProcessSignInContext context) { if (context == null) { @@ -3439,13 +3452,13 @@ namespace OpenIddict.Server /// /// Contains the logic responsible of generating and attaching the device code identifier to the user code principal. /// - public class AttachDeviceCodeIdentifier : IOpenIddictServerHandler + public class AttachDeviceCodeIdentifier : IOpenIddictServerHandler { /// /// Gets the default descriptor definition assigned to this handler. /// public static OpenIddictServerHandlerDescriptor Descriptor { get; } - = OpenIddictServerHandlerDescriptor.CreateBuilder() + = OpenIddictServerHandlerDescriptor.CreateBuilder() .AddFilter() .AddFilter() .UseSingletonHandler() @@ -3459,7 +3472,7 @@ namespace OpenIddict.Server /// /// A that can be used to monitor the asynchronous operation. /// - public ValueTask HandleAsync([NotNull] ProcessSigninContext context) + public ValueTask HandleAsync([NotNull] ProcessSignInContext context) { if (context == null) { @@ -3479,13 +3492,13 @@ namespace OpenIddict.Server /// /// Contains the logic responsible of generating a user code using IdentityModel. /// - public class GenerateIdentityModelUserCode : IOpenIddictServerHandler + public class GenerateIdentityModelUserCode : IOpenIddictServerHandler { /// /// Gets the default descriptor definition assigned to this handler. /// public static OpenIddictServerHandlerDescriptor Descriptor { get; } - = OpenIddictServerHandlerDescriptor.CreateBuilder() + = OpenIddictServerHandlerDescriptor.CreateBuilder() .AddFilter() .UseSingletonHandler() .SetOrder(AttachDeviceCodeIdentifier.Descriptor.Order + 1_000) @@ -3498,7 +3511,7 @@ namespace OpenIddict.Server /// /// A that can be used to monitor the asynchronous operation. /// - public ValueTask HandleAsync([NotNull] ProcessSigninContext context) + public ValueTask HandleAsync([NotNull] ProcessSignInContext context) { if (context == null) { @@ -3546,7 +3559,7 @@ namespace OpenIddict.Server /// Contains the logic responsible of creating a reference user code entry. /// Note: this handler is not used when the degraded mode is enabled. /// - public class CreateReferenceUserCodeEntry : IOpenIddictServerHandler + public class CreateReferenceUserCodeEntry : IOpenIddictServerHandler { private readonly IOpenIddictApplicationManager _applicationManager; private readonly IOpenIddictTokenManager _tokenManager; @@ -3571,7 +3584,7 @@ namespace OpenIddict.Server /// Gets the default descriptor definition assigned to this handler. /// public static OpenIddictServerHandlerDescriptor Descriptor { get; } - = OpenIddictServerHandlerDescriptor.CreateBuilder() + = OpenIddictServerHandlerDescriptor.CreateBuilder() .AddFilter() .AddFilter() .AddFilter() @@ -3586,7 +3599,7 @@ namespace OpenIddict.Server /// /// A that can be used to monitor the asynchronous operation. /// - public async ValueTask HandleAsync([NotNull] ProcessSigninContext context) + public async ValueTask HandleAsync([NotNull] ProcessSignInContext context) { if (context == null) { @@ -3658,13 +3671,13 @@ namespace OpenIddict.Server /// Contains the logic responsible of generating and attaching the hashes of /// the access token and authorization code to the identity token principal. /// - public class AttachTokenDigests : IOpenIddictServerHandler + public class AttachTokenDigests : IOpenIddictServerHandler { /// /// Gets the default descriptor definition assigned to this handler. /// public static OpenIddictServerHandlerDescriptor Descriptor { get; } - = OpenIddictServerHandlerDescriptor.CreateBuilder() + = OpenIddictServerHandlerDescriptor.CreateBuilder() .AddFilter() .UseSingletonHandler() .SetOrder(CreateReferenceUserCodeEntry.Descriptor.Order + 1_000) @@ -3677,7 +3690,7 @@ namespace OpenIddict.Server /// /// A that can be used to monitor the asynchronous operation. /// - public ValueTask HandleAsync([NotNull] ProcessSigninContext context) + public ValueTask HandleAsync([NotNull] ProcessSignInContext context) { if (context == null) { @@ -3789,13 +3802,13 @@ namespace OpenIddict.Server /// /// Contains the logic responsible of generating an identity token using IdentityModel. /// - public class GenerateIdentityModelIdentityToken : IOpenIddictServerHandler + public class GenerateIdentityModelIdentityToken : IOpenIddictServerHandler { /// /// Gets the default descriptor definition assigned to this handler. /// public static OpenIddictServerHandlerDescriptor Descriptor { get; } - = OpenIddictServerHandlerDescriptor.CreateBuilder() + = OpenIddictServerHandlerDescriptor.CreateBuilder() .AddFilter() .UseSingletonHandler() .SetOrder(AttachTokenDigests.Descriptor.Order + 1_000) @@ -3808,7 +3821,7 @@ namespace OpenIddict.Server /// /// A that can be used to monitor the asynchronous operation. /// - public ValueTask HandleAsync([NotNull] ProcessSigninContext context) + public ValueTask HandleAsync([NotNull] ProcessSignInContext context) { if (context == null) { @@ -3847,13 +3860,13 @@ namespace OpenIddict.Server /// Contains the logic responsible of beautifying the user code returned to the client. /// Note: this handler is not used when the degraded mode is enabled. /// - public class BeautifyUserCode : IOpenIddictServerHandler + public class BeautifyUserCode : IOpenIddictServerHandler { /// /// Gets the default descriptor definition assigned to this handler. /// public static OpenIddictServerHandlerDescriptor Descriptor { get; } - = OpenIddictServerHandlerDescriptor.CreateBuilder() + = OpenIddictServerHandlerDescriptor.CreateBuilder() // Technically, this handler doesn't require that the degraded mode be disabled // but the default CreateReferenceUserCodeEntry that creates the user code // reference identifiers only works when the degraded mode is disabled. @@ -3870,7 +3883,7 @@ namespace OpenIddict.Server /// /// A that can be used to monitor the asynchronous operation. /// - public ValueTask HandleAsync([NotNull] ProcessSigninContext context) + public ValueTask HandleAsync([NotNull] ProcessSignInContext context) { if (context == null) { @@ -3904,13 +3917,13 @@ namespace OpenIddict.Server /// /// Contains the logic responsible of attaching additional access token properties to the sign-in response. /// - public class AttachAccessTokenProperties : IOpenIddictServerHandler + public class AttachAccessTokenProperties : IOpenIddictServerHandler { /// /// Gets the default descriptor definition assigned to this handler. /// public static OpenIddictServerHandlerDescriptor Descriptor { get; } - = OpenIddictServerHandlerDescriptor.CreateBuilder() + = OpenIddictServerHandlerDescriptor.CreateBuilder() .AddFilter() .UseSingletonHandler() .SetOrder(BeautifyUserCode.Descriptor.Order + 1_000) @@ -3923,7 +3936,7 @@ namespace OpenIddict.Server /// /// A that can be used to monitor the asynchronous operation. /// - public ValueTask HandleAsync([NotNull] ProcessSigninContext context) + public ValueTask HandleAsync([NotNull] ProcessSignInContext context) { if (context == null) { @@ -3955,13 +3968,13 @@ namespace OpenIddict.Server /// /// Contains the logic responsible of attaching additional device code properties to the sign-in response. /// - public class AttachDeviceCodeProperties : IOpenIddictServerHandler + public class AttachDeviceCodeProperties : IOpenIddictServerHandler { /// /// Gets the default descriptor definition assigned to this handler. /// public static OpenIddictServerHandlerDescriptor Descriptor { get; } - = OpenIddictServerHandlerDescriptor.CreateBuilder() + = OpenIddictServerHandlerDescriptor.CreateBuilder() .AddFilter() .UseSingletonHandler() .SetOrder(AttachAccessTokenProperties.Descriptor.Order + 1_000) @@ -3974,7 +3987,7 @@ namespace OpenIddict.Server /// /// A that can be used to monitor the asynchronous operation. /// - public ValueTask HandleAsync([NotNull] ProcessSigninContext context) + public ValueTask HandleAsync([NotNull] ProcessSignInContext context) { if (context == null) { diff --git a/test/OpenIddict.Server.AspNetCore.IntegrationTests/OpenIddictServerAspNetCoreIntegrationTests.cs b/test/OpenIddict.Server.AspNetCore.IntegrationTests/OpenIddictServerAspNetCoreIntegrationTests.cs index 58b6710b..33abed4d 100644 --- a/test/OpenIddict.Server.AspNetCore.IntegrationTests/OpenIddictServerAspNetCoreIntegrationTests.cs +++ b/test/OpenIddict.Server.AspNetCore.IntegrationTests/OpenIddictServerAspNetCoreIntegrationTests.cs @@ -5,8 +5,10 @@ */ using System; +using System.Linq; using System.Security.Claims; using System.Text.Json; +using System.Threading.Tasks; using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; @@ -15,12 +17,243 @@ using Microsoft.AspNetCore.TestHost; using Microsoft.Extensions.DependencyInjection; using OpenIddict.Abstractions; using OpenIddict.Server.FunctionalTests; +using Xunit; using static OpenIddict.Abstractions.OpenIddictConstants; +using static OpenIddict.Server.AspNetCore.OpenIddictServerAspNetCoreHandlers; +using static OpenIddict.Server.OpenIddictServerEvents; namespace OpenIddict.Server.AspNetCore.FunctionalTests { public partial class OpenIddictServerAspNetCoreIntegrationTests : OpenIddictServerIntegrationTests { + [Theory] + [InlineData("/", OpenIddictServerEndpointType.Unknown)] + [InlineData("/connect", OpenIddictServerEndpointType.Unknown)] + [InlineData("/CONNECT", OpenIddictServerEndpointType.Unknown)] + [InlineData("/connect/", OpenIddictServerEndpointType.Unknown)] + [InlineData("/CONNECT/", OpenIddictServerEndpointType.Unknown)] + [InlineData("/connect/authorize", OpenIddictServerEndpointType.Authorization)] + [InlineData("/CONNECT/AUTHORIZE", OpenIddictServerEndpointType.Authorization)] + [InlineData("/connect/authorize/", OpenIddictServerEndpointType.Authorization)] + [InlineData("/CONNECT/AUTHORIZE/", OpenIddictServerEndpointType.Authorization)] + [InlineData("/connect/authorize/subpath", OpenIddictServerEndpointType.Unknown)] + [InlineData("/CONNECT/AUTHORIZE/SUBPATH", OpenIddictServerEndpointType.Unknown)] + [InlineData("/connect/authorize/subpath/", OpenIddictServerEndpointType.Unknown)] + [InlineData("/CONNECT/AUTHORIZE/SUBPATH/", OpenIddictServerEndpointType.Unknown)] + [InlineData("/connect/introspect", OpenIddictServerEndpointType.Introspection)] + [InlineData("/CONNECT/INTROSPECT", OpenIddictServerEndpointType.Introspection)] + [InlineData("/connect/introspect/", OpenIddictServerEndpointType.Introspection)] + [InlineData("/CONNECT/INTROSPECT/", OpenIddictServerEndpointType.Introspection)] + [InlineData("/connect/introspect/subpath", OpenIddictServerEndpointType.Unknown)] + [InlineData("/CONNECT/INTROSPECT/SUBPATH", OpenIddictServerEndpointType.Unknown)] + [InlineData("/connect/introspect/subpath/", OpenIddictServerEndpointType.Unknown)] + [InlineData("/CONNECT/INTROSPECT/SUBPATH/", OpenIddictServerEndpointType.Unknown)] + [InlineData("/connect/logout", OpenIddictServerEndpointType.Logout)] + [InlineData("/CONNECT/LOGOUT", OpenIddictServerEndpointType.Logout)] + [InlineData("/connect/logout/", OpenIddictServerEndpointType.Logout)] + [InlineData("/CONNECT/LOGOUT/", OpenIddictServerEndpointType.Logout)] + [InlineData("/connect/logout/subpath", OpenIddictServerEndpointType.Unknown)] + [InlineData("/CONNECT/LOGOUT/SUBPATH", OpenIddictServerEndpointType.Unknown)] + [InlineData("/connect/logout/subpath/", OpenIddictServerEndpointType.Unknown)] + [InlineData("/CONNECT/LOGOUT/SUBPATH/", OpenIddictServerEndpointType.Unknown)] + [InlineData("/connect/revoke", OpenIddictServerEndpointType.Revocation)] + [InlineData("/CONNECT/REVOKE", OpenIddictServerEndpointType.Revocation)] + [InlineData("/connect/revoke/", OpenIddictServerEndpointType.Revocation)] + [InlineData("/CONNECT/REVOKE/", OpenIddictServerEndpointType.Revocation)] + [InlineData("/connect/revoke/subpath", OpenIddictServerEndpointType.Unknown)] + [InlineData("/CONNECT/REVOKE/SUBPATH", OpenIddictServerEndpointType.Unknown)] + [InlineData("/connect/revoke/subpath/", OpenIddictServerEndpointType.Unknown)] + [InlineData("/CONNECT/REVOKE/SUBPATH/", OpenIddictServerEndpointType.Unknown)] + [InlineData("/connect/token", OpenIddictServerEndpointType.Token)] + [InlineData("/CONNECT/TOKEN", OpenIddictServerEndpointType.Token)] + [InlineData("/connect/token/", OpenIddictServerEndpointType.Token)] + [InlineData("/CONNECT/TOKEN/", OpenIddictServerEndpointType.Token)] + [InlineData("/connect/token/subpath", OpenIddictServerEndpointType.Unknown)] + [InlineData("/CONNECT/TOKEN/SUBPATH", OpenIddictServerEndpointType.Unknown)] + [InlineData("/connect/token/subpath/", OpenIddictServerEndpointType.Unknown)] + [InlineData("/CONNECT/TOKEN/SUBPATH/", OpenIddictServerEndpointType.Unknown)] + [InlineData("/connect/userinfo", OpenIddictServerEndpointType.Userinfo)] + [InlineData("/CONNECT/USERINFO", OpenIddictServerEndpointType.Userinfo)] + [InlineData("/connect/userinfo/", OpenIddictServerEndpointType.Userinfo)] + [InlineData("/CONNECT/USERINFO/", OpenIddictServerEndpointType.Userinfo)] + [InlineData("/connect/userinfo/subpath", OpenIddictServerEndpointType.Unknown)] + [InlineData("/CONNECT/USERINFO/SUBPATH", OpenIddictServerEndpointType.Unknown)] + [InlineData("/connect/userinfo/subpath/", OpenIddictServerEndpointType.Unknown)] + [InlineData("/CONNECT/USERINFO/SUBPATH/", OpenIddictServerEndpointType.Unknown)] + [InlineData("/.well-known/openid-configuration", OpenIddictServerEndpointType.Configuration)] + [InlineData("/.WELL-KNOWN/OPENID-CONFIGURATION", OpenIddictServerEndpointType.Configuration)] + [InlineData("/.well-known/openid-configuration/", OpenIddictServerEndpointType.Configuration)] + [InlineData("/.WELL-KNOWN/OPENID-CONFIGURATION/", OpenIddictServerEndpointType.Configuration)] + [InlineData("/.well-known/openid-configuration/subpath", OpenIddictServerEndpointType.Unknown)] + [InlineData("/.WELL-KNOWN/OPENID-CONFIGURATION/SUBPATH", OpenIddictServerEndpointType.Unknown)] + [InlineData("/.well-known/openid-configuration/subpath/", OpenIddictServerEndpointType.Unknown)] + [InlineData("/.WELL-KNOWN/OPENID-CONFIGURATION/SUBPATH/", OpenIddictServerEndpointType.Unknown)] + [InlineData("/.well-known/jwks", OpenIddictServerEndpointType.Cryptography)] + [InlineData("/.WELL-KNOWN/JWKS", OpenIddictServerEndpointType.Cryptography)] + [InlineData("/.well-known/jwks/", OpenIddictServerEndpointType.Cryptography)] + [InlineData("/.WELL-KNOWN/JWKS/", OpenIddictServerEndpointType.Cryptography)] + [InlineData("/.well-known/jwks/subpath", OpenIddictServerEndpointType.Unknown)] + [InlineData("/.WELL-KNOWN/JWKS/SUBPATH", OpenIddictServerEndpointType.Unknown)] + [InlineData("/.well-known/jwks/subpath/", OpenIddictServerEndpointType.Unknown)] + [InlineData("/.WELL-KNOWN/JWKS/SUBPATH/", OpenIddictServerEndpointType.Unknown)] + public Task ProcessRequest_MatchesCorrespondingEndpoint(string path, OpenIddictServerEndpointType type) + { + // Arrange + var client = CreateClient(options => + { + options.EnableDegradedMode(); + + options.AddEventHandler(builder => + builder.UseInlineHandler(context => + { + // Assert + Assert.Equal(type, context.EndpointType); + + return default; + })); + }); + + // Act + return client.PostAsync(path, new OpenIddictRequest()); + } + + [Theory] + [InlineData("/custom/connect/authorize", OpenIddictServerEndpointType.Authorization)] + [InlineData("/custom/connect/custom", OpenIddictServerEndpointType.Unknown)] + [InlineData("/custom/connect/introspect", OpenIddictServerEndpointType.Introspection)] + [InlineData("/custom/connect/logout", OpenIddictServerEndpointType.Logout)] + [InlineData("/custom/connect/revoke", OpenIddictServerEndpointType.Revocation)] + [InlineData("/custom/connect/token", OpenIddictServerEndpointType.Token)] + [InlineData("/custom/connect/userinfo", OpenIddictServerEndpointType.Userinfo)] + [InlineData("/custom/.well-known/openid-configuration", OpenIddictServerEndpointType.Configuration)] + [InlineData("/custom/.well-known/jwks", OpenIddictServerEndpointType.Cryptography)] + public Task ProcessRequest_AllowsOverridingEndpoint(string address, OpenIddictServerEndpointType type) + { + // Arrange + var client = CreateClient(options => + { + options.EnableDegradedMode(); + + options.AddEventHandler(builder => + { + builder.UseInlineHandler(context => + { + // Act + context.EndpointType = type; + + // Assert + Assert.Equal(type, context.EndpointType); + + return default; + }); + + builder.SetOrder(InferEndpointType.Descriptor.Order + 500); + }); + }); + + // Act + return client.PostAsync(address, new OpenIddictRequest()); + } + + [Theory] + [InlineData("/.well-known/openid-configuration")] + [InlineData("/.well-known/jwks")] + [InlineData("/connect/authorize")] + [InlineData("/connect/introspect")] + [InlineData("/connect/logout")] + [InlineData("/connect/revoke")] + [InlineData("/connect/token")] + [InlineData("/connect/userinfo")] + public async Task HandleRequestAsync_RejectsInsecureHttpRequests(string address) + { + // Arrange + var client = CreateClient(options => + { + options.EnableDegradedMode(); + + options.UseAspNetCore() + .Configure(options => options.DisableTransportSecurityRequirement = false); + }); + + // Act + var response = await client.PostAsync(address, new OpenIddictRequest()); + + // Assert + Assert.Equal(Errors.InvalidRequest, response.Error); + Assert.Equal("This server only accepts HTTPS requests.", response.ErrorDescription); + } + + [Theory] + [InlineData("/.well-known/openid-configuration")] + [InlineData("/.well-known/jwks")] + [InlineData("/custom")] + [InlineData("/connect/authorize")] + [InlineData("/connect/introspect")] + [InlineData("/connect/logout")] + [InlineData("/connect/revoke")] + [InlineData("/connect/token")] + [InlineData("/connect/userinfo")] + public async Task ProcessRequest_AllowsHandlingResponse(string address) + { + // Arrange + var client = CreateClient(options => + { + options.EnableDegradedMode(); + + options.AddEventHandler(builder => + builder.UseInlineHandler(context => + { + context.Transaction.SetProperty("custom_response", new + { + name = "Bob le Bricoleur" + }); + + context.HandleRequest(); + + return default; + })); + }); + + // Act + var response = await client.PostAsync(address, new OpenIddictRequest()); + + // Assert + Assert.Equal("Bob le Bricoleur", (string) response["name"]); + } + + [Theory] + [InlineData("/.well-known/openid-configuration")] + [InlineData("/.well-known/jwks")] + [InlineData("/custom")] + [InlineData("/connect/authorize")] + [InlineData("/connect/introspect")] + [InlineData("/connect/logout")] + [InlineData("/connect/revoke")] + [InlineData("/connect/token")] + [InlineData("/connect/userinfo")] + public async Task ProcessRequest_AllowsSkippingHandler(string address) + { + // Arrange + var client = CreateClient(options => + { + options.EnableDegradedMode(); + + options.AddEventHandler(builder => + builder.UseInlineHandler(context => + { + context.SkipRequest(); + + return default; + })); + }); + + // Act + var response = await client.PostAsync(address, new OpenIddictRequest()); + + // Assert + Assert.Equal("Bob le Magnifique", (string) response["name"]); + } + protected override OpenIddictServerIntegrationTestClient CreateClient(Action configuration = null) { var builder = new WebHostBuilder(); @@ -58,36 +291,48 @@ namespace OpenIddict.Server.AspNetCore.FunctionalTests app.UseAuthentication(); - app.Use(next => context => + app.Use(next => async context => { - if (context.Request.Path == "/invalid-signin") + if (context.Request.Path == "/signin") { var identity = new ClaimsIdentity(OpenIddictServerAspNetCoreDefaults.AuthenticationScheme); identity.AddClaim(Claims.Subject, "Bob le Bricoleur"); var principal = new ClaimsPrincipal(identity); - return context.SignInAsync(OpenIddictServerAspNetCoreDefaults.AuthenticationScheme, principal); + await context.SignInAsync(OpenIddictServerAspNetCoreDefaults.AuthenticationScheme, principal); + return; } - else if (context.Request.Path == "/invalid-signout") + else if (context.Request.Path == "/signout") { - return context.SignOutAsync(OpenIddictServerAspNetCoreDefaults.AuthenticationScheme); + await context.SignOutAsync(OpenIddictServerAspNetCoreDefaults.AuthenticationScheme); + return; } - else if (context.Request.Path == "/invalid-challenge") + else if (context.Request.Path == "/challenge") { - return context.ChallengeAsync( + await context.ChallengeAsync( OpenIddictServerAspNetCoreDefaults.AuthenticationScheme, new AuthenticationProperties()); + return; } - else if (context.Request.Path == "/invalid-authenticate") + else if (context.Request.Path == "/authenticate") { - return context.AuthenticateAsync(OpenIddictServerAspNetCoreDefaults.AuthenticationScheme); + var result = await context.AuthenticateAsync(OpenIddictServerAspNetCoreDefaults.AuthenticationScheme); + if (result?.Principal == null) + { + return; + } + + context.Response.ContentType = "application/json"; + await context.Response.WriteAsync(JsonSerializer.Serialize( + result.Principal.Claims.ToDictionary(claim => claim.Type, claim => claim.Value))); + return; } - return next(context); + await next(context); }); app.Run(context => diff --git a/test/OpenIddict.Server.IntegrationTests/OpenIddictServerIntegrationTests.cs b/test/OpenIddict.Server.IntegrationTests/OpenIddictServerIntegrationTests.cs index 1c63fe50..2aa9d860 100644 --- a/test/OpenIddict.Server.IntegrationTests/OpenIddictServerIntegrationTests.cs +++ b/test/OpenIddict.Server.IntegrationTests/OpenIddictServerIntegrationTests.cs @@ -6,19 +6,423 @@ using System; using System.Security.Claims; +using System.Text; +using System.Threading.Tasks; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using Moq; using OpenIddict.Abstractions; using OpenIddict.Core; +using Xunit; using static OpenIddict.Abstractions.OpenIddictConstants; using static OpenIddict.Server.OpenIddictServerEvents; +using static OpenIddict.Server.OpenIddictServerHandlers; namespace OpenIddict.Server.FunctionalTests { public abstract partial class OpenIddictServerIntegrationTests { + [Fact] + public async Task ProcessAuthentication_UnknownEndpointCausesAnException() + { + // Arrange + var client = CreateClient(options => options.EnableDegradedMode()); + + // Act and assert + var exception = await Assert.ThrowsAsync(delegate + { + return client.PostAsync("/authenticate", new OpenIddictRequest()); + }); + + Assert.Equal(new StringBuilder() + .AppendLine("An identity cannot be extracted from this request.") + .Append("This generally indicates that the OpenIddict server stack was asked ") + .AppendLine("to validate a token for an endpoint it doesn't manage.") + .Append("To validate tokens received by custom API endpoints, ") + .Append("the OpenIddict validation services must be used instead.") + .ToString(), exception.Message); + } + + [Fact] + public async Task ProcessAuthentication_InvalidEndpointCausesAnException() + { + // Arrange + var client = CreateClient(options => + { + options.EnableDegradedMode(); + options.SetConfigurationEndpointUris("/authenticate"); + + options.AddEventHandler(builder => + builder.UseInlineHandler(context => + { + context.SkipRequest(); + + return default; + })); + }); + + // Act and assert + var exception = await Assert.ThrowsAsync(delegate + { + return client.GetAsync("/authenticate"); + }); + + Assert.Equal(new StringBuilder() + .AppendLine("An identity cannot be extracted from this request.") + .Append("This generally indicates that the OpenIddict server stack was asked ") + .AppendLine("to validate a token for an endpoint it doesn't manage.") + .Append("To validate tokens received by custom API endpoints, ") + .Append("the OpenIddict validation services must be used instead.") + .ToString(), exception.Message); + } + + [Fact] + public async Task ProcessAuthentication_UnsupportedGrantTypeThrowsAnException() + { + // Arrange + var client = CreateClient(options => + { + options.EnableDegradedMode(); + options.SetTokenEndpointUris("/authenticate"); + + options.AddEventHandler(builder => + builder.UseInlineHandler(context => + { + context.SkipRequest(); + + return default; + })); + }); + + // Act and assert + var exception = await Assert.ThrowsAsync(delegate + { + return client.PostAsync("/authenticate", new OpenIddictRequest + { + GrantType = GrantTypes.Password, + Username = "johndoe", + Password = "A3ddj3w", + }); + }); + + Assert.Equal(new StringBuilder() + .AppendLine("An identity cannot be extracted from this token request.") + .Append("This generally indicates that the OpenIddict server stack was asked ") + .AppendLine("to validate a token for an invalid grant type (e.g password).") + .ToString(), exception.Message); + } + + [Fact] + public async Task ProcessAuthentication_MissingIdTokenHintReturnsNull() + { + // Arrange + var client = CreateClient(options => + { + options.EnableDegradedMode(); + options.SetLogoutEndpointUris("/authenticate"); + + options.AddEventHandler(builder => + builder.UseInlineHandler(context => + { + context.SkipRequest(); + + return default; + })); + }); + + // Act + var response = await client.GetAsync("/authenticate", new OpenIddictRequest + { + IdTokenHint = null + }); + + // Assert + Assert.Null((string) response[Claims.Subject]); + } + + [Fact] + public async Task ProcessAuthentication_InvalidIdTokenHintReturnsNull() + { + // Arrange + var client = CreateClient(options => + { + options.EnableDegradedMode(); + options.SetLogoutEndpointUris("/authenticate"); + + options.AddEventHandler(builder => + builder.UseInlineHandler(context => + { + context.SkipRequest(); + + return default; + })); + }); + + // Act + var response = await client.GetAsync("/authenticate", new OpenIddictRequest + { + IdTokenHint = "38323A4B-6CB2-41B8-B457-1951987CB383" + }); + + // Assert + Assert.Null((string) response[Claims.Subject]); + } + + [Fact] + public async Task ProcessAuthentication_ValidIdTokenHintReturnsExpectedIdentity() + { + // Arrange + var client = CreateClient(options => + { + options.EnableDegradedMode(); + options.SetLogoutEndpointUris("/authenticate"); + + options.AddEventHandler(builder => + builder.UseInlineHandler(context => + { + context.SkipRequest(); + + return default; + })); + + options.AddEventHandler(builder => + { + builder.UseInlineHandler(context => + { + Assert.Equal("id_token", context.Token); + Assert.Equal(TokenUsages.IdToken, context.TokenType); + + context.Principal = new ClaimsPrincipal(new ClaimsIdentity("Bearer")) + .SetClaim(Claims.Subject, "Bob le Magnifique"); + + return default; + }); + + builder.SetOrder(ValidateIdentityModelToken.Descriptor.Order - 500); + }); + }); + + // Act + var response = await client.GetAsync("/authenticate", new OpenIddictRequest + { + IdTokenHint = "id_token" + }); + + // Assert + Assert.Equal("Bob le Magnifique", (string) response[Claims.Subject]); + } + + [Fact] + public async Task ProcessAuthentication_MissingAuthorizationCodeReturnsNull() + { + // Arrange + var client = CreateClient(options => + { + options.EnableDegradedMode(); + options.SetTokenEndpointUris("/authenticate"); + + options.AddEventHandler(builder => + builder.UseInlineHandler(context => + { + context.SkipRequest(); + + return default; + })); + }); + + // Act + var response = await client.PostAsync("/authenticate", new OpenIddictRequest + { + ClientId = "Fabrikam", + Code = null, + GrantType = GrantTypes.AuthorizationCode + }); + + // Assert + Assert.Null((string) response[Claims.Subject]); + } + + [Fact] + public async Task ProcessAuthentication_InvalidAuthorizationCodeReturnsNull() + { + // Arrange + var client = CreateClient(options => + { + options.EnableDegradedMode(); + options.SetTokenEndpointUris("/authenticate"); + + options.AddEventHandler(builder => + builder.UseInlineHandler(context => + { + context.SkipRequest(); + + return default; + })); + }); + + // Act + var response = await client.PostAsync("/authenticate", new OpenIddictRequest + { + ClientId = "Fabrikam", + Code = "38323A4B-6CB2-41B8-B457-1951987CB383", + GrantType = GrantTypes.AuthorizationCode + }); + + // Assert + Assert.Null((string) response[Claims.Subject]); + } + + [Fact] + public async Task ProcessAuthentication_ValidAuthorizationCodeReturnsExpectedIdentity() + { + // Arrange + var client = CreateClient(options => + { + options.EnableDegradedMode(); + options.SetTokenEndpointUris("/authenticate"); + + options.AddEventHandler(builder => + builder.UseInlineHandler(context => + { + context.SkipRequest(); + + return default; + })); + + options.AddEventHandler(builder => + { + builder.UseInlineHandler(context => + { + Assert.Equal("authorization_code", context.Token); + Assert.Equal(TokenUsages.AuthorizationCode, context.TokenType); + + context.Principal = new ClaimsPrincipal(new ClaimsIdentity("Bearer")) + .SetClaim(Claims.Subject, "Bob le Magnifique") + .SetPresenters("Fabrikam"); + + return default; + }); + + builder.SetOrder(ValidateIdentityModelToken.Descriptor.Order - 500); + }); + }); + + // Act + var response = await client.PostAsync("/authenticate", new OpenIddictRequest + { + ClientId = "Fabrikam", + Code = "authorization_code", + GrantType = GrantTypes.AuthorizationCode + }); + + // Assert + Assert.Equal("Bob le Magnifique", (string) response[Claims.Subject]); + } + + [Fact] + public async Task ProcessAuthentication_MissingRefreshTokenReturnsNull() + { + // Arrange + var client = CreateClient(options => + { + options.EnableDegradedMode(); + options.SetTokenEndpointUris("/authenticate"); + + options.AddEventHandler(builder => + builder.UseInlineHandler(context => + { + context.SkipRequest(); + + return default; + })); + }); + + // Act + var response = await client.PostAsync("/authenticate", new OpenIddictRequest + { + GrantType = GrantTypes.RefreshToken, + RefreshToken = null + }); + + // Assert + Assert.Null((string) response[Claims.Subject]); + } + + [Fact] + public async Task ProcessAuthentication_InvalidRefreshTokenReturnsNull() + { + // Arrange + var client = CreateClient(options => + { + options.EnableDegradedMode(); + options.SetTokenEndpointUris("/authenticate"); + + options.AddEventHandler(builder => + builder.UseInlineHandler(context => + { + context.SkipRequest(); + + return default; + })); + }); + + // Act + var response = await client.PostAsync("/authenticate", new OpenIddictRequest + { + GrantType = GrantTypes.RefreshToken, + RefreshToken = "38323A4B-6CB2-41B8-B457-1951987CB383" + }); + + // Assert + Assert.Null((string) response[Claims.Subject]); + } + + [Fact] + public async Task ProcessAuthentication_ValidRefreshTokenReturnsExpectedIdentity() + { + // Arrange + var client = CreateClient(options => + { + options.EnableDegradedMode(); + options.SetTokenEndpointUris("/authenticate"); + + options.AddEventHandler(builder => + builder.UseInlineHandler(context => + { + context.SkipRequest(); + + return default; + })); + + options.AddEventHandler(builder => + { + builder.UseInlineHandler(context => + { + Assert.Equal("refresh_token", context.Token); + Assert.Equal(TokenUsages.RefreshToken, context.TokenType); + + context.Principal = new ClaimsPrincipal(new ClaimsIdentity("Bearer")) + .SetClaim(Claims.Subject, "Bob le Magnifique"); + + return default; + }); + + builder.SetOrder(ValidateIdentityModelToken.Descriptor.Order - 500); + }); + }); + + // Act + var response = await client.PostAsync("/authenticate", new OpenIddictRequest + { + GrantType = GrantTypes.RefreshToken, + RefreshToken = "refresh_token" + }); + + // Assert + Assert.Equal("Bob le Magnifique", (string) response[Claims.Subject]); + } + protected virtual void ConfigureServices(IServiceCollection services) { services.AddOpenIddict() diff --git a/test/OpenIddict.Server.Owin.IntegrationTests/OpenIddictServerOwinIntegrationTests.cs b/test/OpenIddict.Server.Owin.IntegrationTests/OpenIddictServerOwinIntegrationTests.cs index bc42f75d..20bc836a 100644 --- a/test/OpenIddict.Server.Owin.IntegrationTests/OpenIddictServerOwinIntegrationTests.cs +++ b/test/OpenIddict.Server.Owin.IntegrationTests/OpenIddictServerOwinIntegrationTests.cs @@ -5,6 +5,7 @@ */ using System; +using System.Linq; using System.Security.Claims; using System.Text.Json; using System.Threading.Tasks; @@ -14,12 +15,243 @@ using Microsoft.Owin.Testing; using OpenIddict.Abstractions; using OpenIddict.Server.FunctionalTests; using Owin; +using Xunit; using static OpenIddict.Abstractions.OpenIddictConstants; +using static OpenIddict.Server.OpenIddictServerEvents; +using static OpenIddict.Server.Owin.OpenIddictServerOwinHandlers; namespace OpenIddict.Server.Owin.FunctionalTests { public partial class OpenIddictServerOwinIntegrationTests : OpenIddictServerIntegrationTests { + [Theory] + [InlineData("/", OpenIddictServerEndpointType.Unknown)] + [InlineData("/connect", OpenIddictServerEndpointType.Unknown)] + [InlineData("/CONNECT", OpenIddictServerEndpointType.Unknown)] + [InlineData("/connect/", OpenIddictServerEndpointType.Unknown)] + [InlineData("/CONNECT/", OpenIddictServerEndpointType.Unknown)] + [InlineData("/connect/authorize", OpenIddictServerEndpointType.Authorization)] + [InlineData("/CONNECT/AUTHORIZE", OpenIddictServerEndpointType.Authorization)] + [InlineData("/connect/authorize/", OpenIddictServerEndpointType.Authorization)] + [InlineData("/CONNECT/AUTHORIZE/", OpenIddictServerEndpointType.Authorization)] + [InlineData("/connect/authorize/subpath", OpenIddictServerEndpointType.Unknown)] + [InlineData("/CONNECT/AUTHORIZE/SUBPATH", OpenIddictServerEndpointType.Unknown)] + [InlineData("/connect/authorize/subpath/", OpenIddictServerEndpointType.Unknown)] + [InlineData("/CONNECT/AUTHORIZE/SUBPATH/", OpenIddictServerEndpointType.Unknown)] + [InlineData("/connect/introspect", OpenIddictServerEndpointType.Introspection)] + [InlineData("/CONNECT/INTROSPECT", OpenIddictServerEndpointType.Introspection)] + [InlineData("/connect/introspect/", OpenIddictServerEndpointType.Introspection)] + [InlineData("/CONNECT/INTROSPECT/", OpenIddictServerEndpointType.Introspection)] + [InlineData("/connect/introspect/subpath", OpenIddictServerEndpointType.Unknown)] + [InlineData("/CONNECT/INTROSPECT/SUBPATH", OpenIddictServerEndpointType.Unknown)] + [InlineData("/connect/introspect/subpath/", OpenIddictServerEndpointType.Unknown)] + [InlineData("/CONNECT/INTROSPECT/SUBPATH/", OpenIddictServerEndpointType.Unknown)] + [InlineData("/connect/logout", OpenIddictServerEndpointType.Logout)] + [InlineData("/CONNECT/LOGOUT", OpenIddictServerEndpointType.Logout)] + [InlineData("/connect/logout/", OpenIddictServerEndpointType.Logout)] + [InlineData("/CONNECT/LOGOUT/", OpenIddictServerEndpointType.Logout)] + [InlineData("/connect/logout/subpath", OpenIddictServerEndpointType.Unknown)] + [InlineData("/CONNECT/LOGOUT/SUBPATH", OpenIddictServerEndpointType.Unknown)] + [InlineData("/connect/logout/subpath/", OpenIddictServerEndpointType.Unknown)] + [InlineData("/CONNECT/LOGOUT/SUBPATH/", OpenIddictServerEndpointType.Unknown)] + [InlineData("/connect/revoke", OpenIddictServerEndpointType.Revocation)] + [InlineData("/CONNECT/REVOKE", OpenIddictServerEndpointType.Revocation)] + [InlineData("/connect/revoke/", OpenIddictServerEndpointType.Revocation)] + [InlineData("/CONNECT/REVOKE/", OpenIddictServerEndpointType.Revocation)] + [InlineData("/connect/revoke/subpath", OpenIddictServerEndpointType.Unknown)] + [InlineData("/CONNECT/REVOKE/SUBPATH", OpenIddictServerEndpointType.Unknown)] + [InlineData("/connect/revoke/subpath/", OpenIddictServerEndpointType.Unknown)] + [InlineData("/CONNECT/REVOKE/SUBPATH/", OpenIddictServerEndpointType.Unknown)] + [InlineData("/connect/token", OpenIddictServerEndpointType.Token)] + [InlineData("/CONNECT/TOKEN", OpenIddictServerEndpointType.Token)] + [InlineData("/connect/token/", OpenIddictServerEndpointType.Token)] + [InlineData("/CONNECT/TOKEN/", OpenIddictServerEndpointType.Token)] + [InlineData("/connect/token/subpath", OpenIddictServerEndpointType.Unknown)] + [InlineData("/CONNECT/TOKEN/SUBPATH", OpenIddictServerEndpointType.Unknown)] + [InlineData("/connect/token/subpath/", OpenIddictServerEndpointType.Unknown)] + [InlineData("/CONNECT/TOKEN/SUBPATH/", OpenIddictServerEndpointType.Unknown)] + [InlineData("/connect/userinfo", OpenIddictServerEndpointType.Userinfo)] + [InlineData("/CONNECT/USERINFO", OpenIddictServerEndpointType.Userinfo)] + [InlineData("/connect/userinfo/", OpenIddictServerEndpointType.Userinfo)] + [InlineData("/CONNECT/USERINFO/", OpenIddictServerEndpointType.Userinfo)] + [InlineData("/connect/userinfo/subpath", OpenIddictServerEndpointType.Unknown)] + [InlineData("/CONNECT/USERINFO/SUBPATH", OpenIddictServerEndpointType.Unknown)] + [InlineData("/connect/userinfo/subpath/", OpenIddictServerEndpointType.Unknown)] + [InlineData("/CONNECT/USERINFO/SUBPATH/", OpenIddictServerEndpointType.Unknown)] + [InlineData("/.well-known/openid-configuration", OpenIddictServerEndpointType.Configuration)] + [InlineData("/.WELL-KNOWN/OPENID-CONFIGURATION", OpenIddictServerEndpointType.Configuration)] + [InlineData("/.well-known/openid-configuration/", OpenIddictServerEndpointType.Configuration)] + [InlineData("/.WELL-KNOWN/OPENID-CONFIGURATION/", OpenIddictServerEndpointType.Configuration)] + [InlineData("/.well-known/openid-configuration/subpath", OpenIddictServerEndpointType.Unknown)] + [InlineData("/.WELL-KNOWN/OPENID-CONFIGURATION/SUBPATH", OpenIddictServerEndpointType.Unknown)] + [InlineData("/.well-known/openid-configuration/subpath/", OpenIddictServerEndpointType.Unknown)] + [InlineData("/.WELL-KNOWN/OPENID-CONFIGURATION/SUBPATH/", OpenIddictServerEndpointType.Unknown)] + [InlineData("/.well-known/jwks", OpenIddictServerEndpointType.Cryptography)] + [InlineData("/.WELL-KNOWN/JWKS", OpenIddictServerEndpointType.Cryptography)] + [InlineData("/.well-known/jwks/", OpenIddictServerEndpointType.Cryptography)] + [InlineData("/.WELL-KNOWN/JWKS/", OpenIddictServerEndpointType.Cryptography)] + [InlineData("/.well-known/jwks/subpath", OpenIddictServerEndpointType.Unknown)] + [InlineData("/.WELL-KNOWN/JWKS/SUBPATH", OpenIddictServerEndpointType.Unknown)] + [InlineData("/.well-known/jwks/subpath/", OpenIddictServerEndpointType.Unknown)] + [InlineData("/.WELL-KNOWN/JWKS/SUBPATH/", OpenIddictServerEndpointType.Unknown)] + public Task ProcessRequest_MatchesCorrespondingEndpoint(string path, OpenIddictServerEndpointType type) + { + // Arrange + var client = CreateClient(options => + { + options.EnableDegradedMode(); + + options.AddEventHandler(builder => + builder.UseInlineHandler(context => + { + // Assert + Assert.Equal(type, context.EndpointType); + + return default; + })); + }); + + // Act + return client.PostAsync(path, new OpenIddictRequest()); + } + + [Theory] + [InlineData("/custom/connect/authorize", OpenIddictServerEndpointType.Authorization)] + [InlineData("/custom/connect/custom", OpenIddictServerEndpointType.Unknown)] + [InlineData("/custom/connect/introspect", OpenIddictServerEndpointType.Introspection)] + [InlineData("/custom/connect/logout", OpenIddictServerEndpointType.Logout)] + [InlineData("/custom/connect/revoke", OpenIddictServerEndpointType.Revocation)] + [InlineData("/custom/connect/token", OpenIddictServerEndpointType.Token)] + [InlineData("/custom/connect/userinfo", OpenIddictServerEndpointType.Userinfo)] + [InlineData("/custom/.well-known/openid-configuration", OpenIddictServerEndpointType.Configuration)] + [InlineData("/custom/.well-known/jwks", OpenIddictServerEndpointType.Cryptography)] + public Task ProcessRequest_AllowsOverridingEndpoint(string address, OpenIddictServerEndpointType type) + { + // Arrange + var client = CreateClient(options => + { + options.EnableDegradedMode(); + + options.AddEventHandler(builder => + { + builder.UseInlineHandler(context => + { + // Act + context.EndpointType = type; + + // Assert + Assert.Equal(type, context.EndpointType); + + return default; + }); + + builder.SetOrder(InferEndpointType.Descriptor.Order + 500); + }); + }); + + // Act + return client.PostAsync(address, new OpenIddictRequest()); + } + + [Theory] + [InlineData("/.well-known/openid-configuration")] + [InlineData("/.well-known/jwks")] + [InlineData("/connect/authorize")] + [InlineData("/connect/introspect")] + [InlineData("/connect/logout")] + [InlineData("/connect/revoke")] + [InlineData("/connect/token")] + [InlineData("/connect/userinfo")] + public async Task HandleRequestAsync_RejectsInsecureHttpRequests(string address) + { + // Arrange + var client = CreateClient(options => + { + options.EnableDegradedMode(); + + options.UseOwin() + .Configure(options => options.DisableTransportSecurityRequirement = false); + }); + + // Act + var response = await client.PostAsync(address, new OpenIddictRequest()); + + // Assert + Assert.Equal(Errors.InvalidRequest, response.Error); + Assert.Equal("This server only accepts HTTPS requests.", response.ErrorDescription); + } + + [Theory] + [InlineData("/.well-known/openid-configuration")] + [InlineData("/.well-known/jwks")] + [InlineData("/custom")] + [InlineData("/connect/authorize")] + [InlineData("/connect/introspect")] + [InlineData("/connect/logout")] + [InlineData("/connect/revoke")] + [InlineData("/connect/token")] + [InlineData("/connect/userinfo")] + public async Task ProcessRequest_AllowsHandlingResponse(string address) + { + // Arrange + var client = CreateClient(options => + { + options.EnableDegradedMode(); + + options.AddEventHandler(builder => + builder.UseInlineHandler(context => + { + context.Transaction.SetProperty("custom_response", new + { + name = "Bob le Bricoleur" + }); + + context.HandleRequest(); + + return default; + })); + }); + + // Act + var response = await client.PostAsync(address, new OpenIddictRequest()); + + // Assert + Assert.Equal("Bob le Bricoleur", (string) response["name"]); + } + + [Theory] + [InlineData("/.well-known/openid-configuration")] + [InlineData("/.well-known/jwks")] + [InlineData("/custom")] + [InlineData("/connect/authorize")] + [InlineData("/connect/introspect")] + [InlineData("/connect/logout")] + [InlineData("/connect/revoke")] + [InlineData("/connect/token")] + [InlineData("/connect/userinfo")] + public async Task ProcessRequest_AllowsSkippingHandler(string address) + { + // Arrange + var client = CreateClient(options => + { + options.EnableDegradedMode(); + + options.AddEventHandler(builder => + builder.UseInlineHandler(context => + { + context.SkipRequest(); + + return default; + })); + }); + + // Act + var response = await client.PostAsync(address, new OpenIddictRequest()); + + // Assert + Assert.Equal("Bob le Magnifique", (string) response["name"]); + } + protected override OpenIddictServerIntegrationTestClient CreateClient(Action configuration = null) { var services = new ServiceCollection(); @@ -71,35 +303,44 @@ namespace OpenIddict.Server.Owin.FunctionalTests app.UseOpenIddictServer(); - app.Use((context, next) => + app.Use(async (context, next) => { - if (context.Request.Path == new PathString("/invalid-signin")) + if (context.Request.Path == new PathString("/signin")) { var identity = new ClaimsIdentity(OpenIddictServerOwinDefaults.AuthenticationType); identity.AddClaim(Claims.Subject, "Bob le Bricoleur"); context.Authentication.SignIn(identity); - return Task.CompletedTask; + return; } - else if (context.Request.Path == new PathString("/invalid-signout")) + else if (context.Request.Path == new PathString("/signout")) { context.Authentication.SignOut(OpenIddictServerOwinDefaults.AuthenticationType); - return Task.CompletedTask; + return; } - else if (context.Request.Path == new PathString("/invalid-challenge")) + else if (context.Request.Path == new PathString("/challenge")) { context.Authentication.Challenge(OpenIddictServerOwinDefaults.AuthenticationType); - return Task.CompletedTask; + return; } - else if (context.Request.Path == new PathString("/invalid-authenticate")) + else if (context.Request.Path == new PathString("/authenticate")) { - return context.Authentication.AuthenticateAsync(OpenIddictServerOwinDefaults.AuthenticationType); + var result = await context.Authentication.AuthenticateAsync(OpenIddictServerOwinDefaults.AuthenticationType); + if (result?.Identity == null) + { + return; + } + + context.Response.ContentType = "application/json"; + await context.Response.WriteAsync(JsonSerializer.Serialize( + result.Identity.Claims.ToDictionary(claim => claim.Type, claim => claim.Value))); + return; } - return next(); + await next(); }); app.Run(context =>