diff --git a/src/OpenIddict.Abstractions/OpenIddictBuilder.cs b/src/OpenIddict.Abstractions/OpenIddictBuilder.cs index 4627bb4e..7fea9e49 100644 --- a/src/OpenIddict.Abstractions/OpenIddictBuilder.cs +++ b/src/OpenIddict.Abstractions/OpenIddictBuilder.cs @@ -35,13 +35,6 @@ namespace Microsoft.Extensions.DependencyInjection [EditorBrowsable(EditorBrowsableState.Never)] public IServiceCollection Services { get; } - /// - /// Returns a string that represents the current object. - /// - /// A string that represents the current object. - [EditorBrowsable(EditorBrowsableState.Never)] - public override string ToString() => base.ToString(); - /// /// Determines whether the specified object is equal to the current object. /// @@ -56,5 +49,12 @@ namespace Microsoft.Extensions.DependencyInjection /// A hash code for the current object. [EditorBrowsable(EditorBrowsableState.Never)] public override int GetHashCode() => base.GetHashCode(); + + /// + /// Returns a string that represents the current object. + /// + /// A string that represents the current object. + [EditorBrowsable(EditorBrowsableState.Never)] + public override string ToString() => base.ToString(); } } diff --git a/src/OpenIddict.Core/OpenIddictCoreBuilder.cs b/src/OpenIddict.Core/OpenIddictCoreBuilder.cs index 7218ebe2..7207b6ca 100644 --- a/src/OpenIddict.Core/OpenIddictCoreBuilder.cs +++ b/src/OpenIddict.Core/OpenIddictCoreBuilder.cs @@ -805,13 +805,6 @@ namespace Microsoft.Extensions.DependencyInjection return Configure(options => options.EntityCacheLimit = limit); } - /// - /// Returns a string that represents the current object. - /// - /// A string that represents the current object. - [EditorBrowsable(EditorBrowsableState.Never)] - public override string ToString() => base.ToString(); - /// /// Determines whether the specified object is equal to the current object. /// @@ -826,5 +819,12 @@ namespace Microsoft.Extensions.DependencyInjection /// A hash code for the current object. [EditorBrowsable(EditorBrowsableState.Never)] public override int GetHashCode() => base.GetHashCode(); + + /// + /// Returns a string that represents the current object. + /// + /// A string that represents the current object. + [EditorBrowsable(EditorBrowsableState.Never)] + public override string ToString() => base.ToString(); } } diff --git a/src/OpenIddict.EntityFramework/Configurations/OpenIddictApplicationConfiguration.cs b/src/OpenIddict.EntityFramework/Configurations/OpenIddictApplicationConfiguration.cs index 1d6749af..abec7341 100644 --- a/src/OpenIddict.EntityFramework/Configurations/OpenIddictApplicationConfiguration.cs +++ b/src/OpenIddict.EntityFramework/Configurations/OpenIddictApplicationConfiguration.cs @@ -65,11 +65,17 @@ namespace OpenIddict.EntityFramework HasMany(application => application.Authorizations) .WithOptional(authorization => authorization.Application) - .Map(association => association.MapKey("ApplicationId")); + .Map(association => + { + association.MapKey(nameof(OpenIddictAuthorization.Application) + nameof(OpenIddictApplication.Id)); + }); HasMany(application => application.Tokens) .WithOptional(token => token.Application) - .Map(association => association.MapKey("ApplicationId")); + .Map(association => + { + association.MapKey(nameof(OpenIddictToken.Application) + nameof(OpenIddictApplication.Id)); + }); ToTable("OpenIddictApplications"); } diff --git a/src/OpenIddict.EntityFramework/Configurations/OpenIddictAuthorizationConfiguration.cs b/src/OpenIddict.EntityFramework/Configurations/OpenIddictAuthorizationConfiguration.cs index 4cdc0625..06698f2d 100644 --- a/src/OpenIddict.EntityFramework/Configurations/OpenIddictAuthorizationConfiguration.cs +++ b/src/OpenIddict.EntityFramework/Configurations/OpenIddictAuthorizationConfiguration.cs @@ -63,7 +63,7 @@ namespace OpenIddict.EntityFramework HasMany(authorization => authorization.Tokens) .WithOptional(token => token.Authorization) - .Map(association => association.MapKey("AuthorizationId")) + .Map(association => association.MapKey(nameof(OpenIddictToken.Authorization) + nameof(OpenIddictAuthorization.Id))) .WillCascadeOnDelete(); ToTable("OpenIddictAuthorizations"); diff --git a/src/OpenIddict.EntityFramework/OpenIddictEntityFrameworkBuilder.cs b/src/OpenIddict.EntityFramework/OpenIddictEntityFrameworkBuilder.cs index 4dc84220..2b8df5da 100644 --- a/src/OpenIddict.EntityFramework/OpenIddictEntityFrameworkBuilder.cs +++ b/src/OpenIddict.EntityFramework/OpenIddictEntityFrameworkBuilder.cs @@ -112,13 +112,6 @@ namespace Microsoft.Extensions.DependencyInjection return Configure(options => options.DbContextType = type); } - /// - /// Returns a string that represents the current object. - /// - /// A string that represents the current object. - [EditorBrowsable(EditorBrowsableState.Never)] - public override string ToString() => base.ToString(); - /// /// Determines whether the specified object is equal to the current object. /// @@ -133,5 +126,12 @@ namespace Microsoft.Extensions.DependencyInjection /// A hash code for the current object. [EditorBrowsable(EditorBrowsableState.Never)] public override int GetHashCode() => base.GetHashCode(); + + /// + /// Returns a string that represents the current object. + /// + /// A string that represents the current object. + [EditorBrowsable(EditorBrowsableState.Never)] + public override string ToString() => base.ToString(); } } diff --git a/src/OpenIddict.EntityFrameworkCore/Configurations/OpenIddictAuthorizationConfiguration.cs b/src/OpenIddict.EntityFrameworkCore/Configurations/OpenIddictAuthorizationConfiguration.cs index c32295cf..f0254283 100644 --- a/src/OpenIddict.EntityFrameworkCore/Configurations/OpenIddictAuthorizationConfiguration.cs +++ b/src/OpenIddict.EntityFrameworkCore/Configurations/OpenIddictAuthorizationConfiguration.cs @@ -64,7 +64,7 @@ namespace OpenIddict.EntityFrameworkCore builder.HasMany(authorization => authorization.Tokens) .WithOne(token => token.Authorization) - .HasForeignKey("AuthorizationId") + .HasForeignKey(nameof(OpenIddictToken.Authorization) + nameof(OpenIddictAuthorization.Id)) .IsRequired(required: false); builder.ToTable("OpenIddictAuthorizations"); diff --git a/src/OpenIddict.EntityFrameworkCore/OpenIddictEntityFrameworkCoreBuilder.cs b/src/OpenIddict.EntityFrameworkCore/OpenIddictEntityFrameworkCoreBuilder.cs index 9f2022fc..418dd93c 100644 --- a/src/OpenIddict.EntityFrameworkCore/OpenIddictEntityFrameworkCoreBuilder.cs +++ b/src/OpenIddict.EntityFrameworkCore/OpenIddictEntityFrameworkCoreBuilder.cs @@ -121,13 +121,6 @@ namespace Microsoft.Extensions.DependencyInjection return Configure(options => options.DbContextType = type); } - /// - /// Returns a string that represents the current object. - /// - /// A string that represents the current object. - [EditorBrowsable(EditorBrowsableState.Never)] - public override string ToString() => base.ToString(); - /// /// Determines whether the specified object is equal to the current object. /// @@ -142,5 +135,12 @@ namespace Microsoft.Extensions.DependencyInjection /// A hash code for the current object. [EditorBrowsable(EditorBrowsableState.Never)] public override int GetHashCode() => base.GetHashCode(); + + /// + /// Returns a string that represents the current object. + /// + /// A string that represents the current object. + [EditorBrowsable(EditorBrowsableState.Never)] + public override string ToString() => base.ToString(); } } diff --git a/src/OpenIddict.MongoDb/OpenIddictMongoDbBuilder.cs b/src/OpenIddict.MongoDb/OpenIddictMongoDbBuilder.cs index 06b8a52e..bb932d85 100644 --- a/src/OpenIddict.MongoDb/OpenIddictMongoDbBuilder.cs +++ b/src/OpenIddict.MongoDb/OpenIddictMongoDbBuilder.cs @@ -198,13 +198,6 @@ namespace Microsoft.Extensions.DependencyInjection return Configure(options => options.Database = database); } - /// - /// Returns a string that represents the current object. - /// - /// A string that represents the current object. - [EditorBrowsable(EditorBrowsableState.Never)] - public override string ToString() => base.ToString(); - /// /// Determines whether the specified object is equal to the current object. /// @@ -219,5 +212,12 @@ namespace Microsoft.Extensions.DependencyInjection /// A hash code for the current object. [EditorBrowsable(EditorBrowsableState.Never)] public override int GetHashCode() => base.GetHashCode(); + + /// + /// Returns a string that represents the current object. + /// + /// A string that represents the current object. + [EditorBrowsable(EditorBrowsableState.Never)] + public override string ToString() => base.ToString(); } } diff --git a/src/OpenIddict.Mvc/OpenIddictMvcBuilder.cs b/src/OpenIddict.Mvc/OpenIddictMvcBuilder.cs index 58a0a7c7..c94a6b06 100644 --- a/src/OpenIddict.Mvc/OpenIddictMvcBuilder.cs +++ b/src/OpenIddict.Mvc/OpenIddictMvcBuilder.cs @@ -64,13 +64,6 @@ namespace Microsoft.Extensions.DependencyInjection public OpenIddictMvcBuilder DisableBindingExceptions() => Configure(options => options.DisableBindingExceptions = true); - /// - /// Returns a string that represents the current object. - /// - /// A string that represents the current object. - [EditorBrowsable(EditorBrowsableState.Never)] - public override string ToString() => base.ToString(); - /// /// Determines whether the specified object is equal to the current object. /// @@ -85,5 +78,12 @@ namespace Microsoft.Extensions.DependencyInjection /// A hash code for the current object. [EditorBrowsable(EditorBrowsableState.Never)] public override int GetHashCode() => base.GetHashCode(); + + /// + /// Returns a string that represents the current object. + /// + /// A string that represents the current object. + [EditorBrowsable(EditorBrowsableState.Never)] + public override string ToString() => base.ToString(); } } diff --git a/src/OpenIddict.Server/OpenIddictServerBuilder.cs b/src/OpenIddict.Server/OpenIddictServerBuilder.cs index d8f22ab4..6cfb3243 100644 --- a/src/OpenIddict.Server/OpenIddictServerBuilder.cs +++ b/src/OpenIddict.Server/OpenIddictServerBuilder.cs @@ -803,13 +803,6 @@ namespace Microsoft.Extensions.DependencyInjection public OpenIddictServerBuilder UseRollingTokens() => Configure(options => options.UseRollingTokens = true); - /// - /// Returns a string that represents the current object. - /// - /// A string that represents the current object. - [EditorBrowsable(EditorBrowsableState.Never)] - public override string ToString() => base.ToString(); - /// /// Determines whether the specified object is equal to the current object. /// @@ -824,5 +817,12 @@ namespace Microsoft.Extensions.DependencyInjection /// A hash code for the current object. [EditorBrowsable(EditorBrowsableState.Never)] public override int GetHashCode() => base.GetHashCode(); + + /// + /// Returns a string that represents the current object. + /// + /// A string that represents the current object. + [EditorBrowsable(EditorBrowsableState.Never)] + public override string ToString() => base.ToString(); } } diff --git a/src/OpenIddict.Validation/Internal/OpenIddictValidationConfiguration.cs b/src/OpenIddict.Validation/Internal/OpenIddictValidationConfiguration.cs index 5bd1612d..022d2e7b 100644 --- a/src/OpenIddict.Validation/Internal/OpenIddictValidationConfiguration.cs +++ b/src/OpenIddict.Validation/Internal/OpenIddictValidationConfiguration.cs @@ -19,6 +19,7 @@ namespace OpenIddict.Validation.Internal /// directly from your code. This API may change or be removed in future minor releases. /// public class OpenIddictValidationConfiguration : IConfigureOptions, + IPostConfigureOptions, IPostConfigureOptions { private readonly IDataProtectionProvider _dataProtectionProvider; @@ -52,6 +53,39 @@ namespace OpenIddict.Validation.Internal options.AddScheme(OpenIddictValidationDefaults.AuthenticationScheme, displayName: null); } + /// + /// Ensures that the authentication configuration is in a consistent and valid state. + /// + /// The authentication scheme associated with the handler instance. + /// The options instance to initialize. + public void PostConfigure([CanBeNull] string name, [NotNull] AuthenticationOptions options) + { + if (options == null) + { + throw new ArgumentNullException(nameof(options)); + } + + bool TryValidate(string scheme) + { + // If the scheme was not set or if it cannot be found in the map, return true. + if (string.IsNullOrEmpty(scheme) || !options.SchemeMap.TryGetValue(scheme, out var builder)) + { + return true; + } + + return builder.HandlerType != typeof(OpenIddictValidationHandler); + } + + if (!TryValidate(options.DefaultSignInScheme) || !TryValidate(options.DefaultSignOutScheme)) + { + throw new InvalidOperationException(new StringBuilder() + .AppendLine("The OpenIddict validation handler cannot be used as the default sign-in/out scheme handler.") + .Append("Make sure that neither DefaultSignInScheme nor DefaultSignOutScheme ") + .Append("point to an instance of the OpenIddict validation handler.") + .ToString()); + } + } + /// /// Populates the default OpenIddict validation options and ensures /// that the configuration is in a consistent and valid state. diff --git a/src/OpenIddict.Validation/OpenIddictValidationBuilder.cs b/src/OpenIddict.Validation/OpenIddictValidationBuilder.cs index 143f9ffd..9d19d868 100644 --- a/src/OpenIddict.Validation/OpenIddictValidationBuilder.cs +++ b/src/OpenIddict.Validation/OpenIddictValidationBuilder.cs @@ -203,13 +203,6 @@ namespace Microsoft.Extensions.DependencyInjection public OpenIddictValidationBuilder UseReferenceTokens() => Configure(options => options.UseReferenceTokens = true); - /// - /// Returns a string that represents the current object. - /// - /// A string that represents the current object. - [EditorBrowsable(EditorBrowsableState.Never)] - public override string ToString() => base.ToString(); - /// /// Determines whether the specified object is equal to the current object. /// @@ -224,5 +217,12 @@ namespace Microsoft.Extensions.DependencyInjection /// A hash code for the current object. [EditorBrowsable(EditorBrowsableState.Never)] public override int GetHashCode() => base.GetHashCode(); + + /// + /// Returns a string that represents the current object. + /// + /// A string that represents the current object. + [EditorBrowsable(EditorBrowsableState.Never)] + public override string ToString() => base.ToString(); } } diff --git a/src/OpenIddict.Validation/OpenIddictValidationExtensions.cs b/src/OpenIddict.Validation/OpenIddictValidationExtensions.cs index 486ed1fe..818a8430 100644 --- a/src/OpenIddict.Validation/OpenIddictValidationExtensions.cs +++ b/src/OpenIddict.Validation/OpenIddictValidationExtensions.cs @@ -49,6 +49,7 @@ namespace Microsoft.Extensions.DependencyInjection builder.Services.TryAddEnumerable(new[] { ServiceDescriptor.Singleton, OpenIddictValidationConfiguration>(), + ServiceDescriptor.Singleton, OpenIddictValidationConfiguration>(), ServiceDescriptor.Singleton, OpenIddictValidationConfiguration>(), ServiceDescriptor.Singleton, OAuthValidationInitializer>() }); diff --git a/test/OpenIddict.Validation.Tests/Internal/OpenIddictValidationConfigurationTests.cs b/test/OpenIddict.Validation.Tests/Internal/OpenIddictValidationConfigurationTests.cs index d596ab5d..755f00a0 100644 --- a/test/OpenIddict.Validation.Tests/Internal/OpenIddictValidationConfigurationTests.cs +++ b/test/OpenIddict.Validation.Tests/Internal/OpenIddictValidationConfigurationTests.cs @@ -15,6 +15,7 @@ using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.TestHost; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; using Moq; using Xunit; @@ -22,6 +23,33 @@ namespace OpenIddict.Validation.Internal.Tests { public class OpenIddictValidationConfigurationTests { + [Theory] + [InlineData(new object[] { new string[] { OpenIddictValidationDefaults.AuthenticationScheme, null } })] + [InlineData(new object[] { new string[] { null, OpenIddictValidationDefaults.AuthenticationScheme } })] + public void PostConfigure_ThrowsAnExceptionWhenDefaultSchemesPointToValidationHandler(string[] schemes) + { + // Arrange + var options = new AuthenticationOptions + { + DefaultSignInScheme = schemes[0], + DefaultSignOutScheme = schemes[1] + }; + + options.AddScheme(OpenIddictValidationDefaults.AuthenticationScheme, displayName: null); + + var configuration = new OpenIddictValidationConfiguration(Mock.Of()); + + // Act and assert + var exception = Assert.Throws(() => configuration.PostConfigure(Options.DefaultName, options)); + + // Assert + Assert.Equal(new StringBuilder() + .AppendLine("The OpenIddict validation handler cannot be used as the default sign-in/out scheme handler.") + .Append("Make sure that neither DefaultSignInScheme nor DefaultSignOutScheme ") + .Append("point to an instance of the OpenIddict validation handler.") + .ToString(), exception.Message); + } + [Fact] public void Configure_ThrowsAnExceptionWhenSchemeIsAlreadyRegisteredWithDifferentHandlerType() {