Browse Source

Update OpenIddictValidationConfiguration to validate the default sign-in/out schemes and ensure they don't point to the OpenIddict validation handler

pull/711/head
Kévin Chalet 7 years ago
parent
commit
313a4a92ec
  1. 14
      src/OpenIddict.Abstractions/OpenIddictBuilder.cs
  2. 14
      src/OpenIddict.Core/OpenIddictCoreBuilder.cs
  3. 10
      src/OpenIddict.EntityFramework/Configurations/OpenIddictApplicationConfiguration.cs
  4. 2
      src/OpenIddict.EntityFramework/Configurations/OpenIddictAuthorizationConfiguration.cs
  5. 14
      src/OpenIddict.EntityFramework/OpenIddictEntityFrameworkBuilder.cs
  6. 2
      src/OpenIddict.EntityFrameworkCore/Configurations/OpenIddictAuthorizationConfiguration.cs
  7. 14
      src/OpenIddict.EntityFrameworkCore/OpenIddictEntityFrameworkCoreBuilder.cs
  8. 14
      src/OpenIddict.MongoDb/OpenIddictMongoDbBuilder.cs
  9. 14
      src/OpenIddict.Mvc/OpenIddictMvcBuilder.cs
  10. 14
      src/OpenIddict.Server/OpenIddictServerBuilder.cs
  11. 34
      src/OpenIddict.Validation/Internal/OpenIddictValidationConfiguration.cs
  12. 14
      src/OpenIddict.Validation/OpenIddictValidationBuilder.cs
  13. 1
      src/OpenIddict.Validation/OpenIddictValidationExtensions.cs
  14. 28
      test/OpenIddict.Validation.Tests/Internal/OpenIddictValidationConfigurationTests.cs

14
src/OpenIddict.Abstractions/OpenIddictBuilder.cs

@ -35,13 +35,6 @@ namespace Microsoft.Extensions.DependencyInjection
[EditorBrowsable(EditorBrowsableState.Never)] [EditorBrowsable(EditorBrowsableState.Never)]
public IServiceCollection Services { get; } public IServiceCollection Services { get; }
/// <summary>
/// Returns a string that represents the current object.
/// </summary>
/// <returns>A string that represents the current object.</returns>
[EditorBrowsable(EditorBrowsableState.Never)]
public override string ToString() => base.ToString();
/// <summary> /// <summary>
/// Determines whether the specified object is equal to the current object. /// Determines whether the specified object is equal to the current object.
/// </summary> /// </summary>
@ -56,5 +49,12 @@ namespace Microsoft.Extensions.DependencyInjection
/// <returns>A hash code for the current object.</returns> /// <returns>A hash code for the current object.</returns>
[EditorBrowsable(EditorBrowsableState.Never)] [EditorBrowsable(EditorBrowsableState.Never)]
public override int GetHashCode() => base.GetHashCode(); public override int GetHashCode() => base.GetHashCode();
/// <summary>
/// Returns a string that represents the current object.
/// </summary>
/// <returns>A string that represents the current object.</returns>
[EditorBrowsable(EditorBrowsableState.Never)]
public override string ToString() => base.ToString();
} }
} }

14
src/OpenIddict.Core/OpenIddictCoreBuilder.cs

@ -805,13 +805,6 @@ namespace Microsoft.Extensions.DependencyInjection
return Configure(options => options.EntityCacheLimit = limit); return Configure(options => options.EntityCacheLimit = limit);
} }
/// <summary>
/// Returns a string that represents the current object.
/// </summary>
/// <returns>A string that represents the current object.</returns>
[EditorBrowsable(EditorBrowsableState.Never)]
public override string ToString() => base.ToString();
/// <summary> /// <summary>
/// Determines whether the specified object is equal to the current object. /// Determines whether the specified object is equal to the current object.
/// </summary> /// </summary>
@ -826,5 +819,12 @@ namespace Microsoft.Extensions.DependencyInjection
/// <returns>A hash code for the current object.</returns> /// <returns>A hash code for the current object.</returns>
[EditorBrowsable(EditorBrowsableState.Never)] [EditorBrowsable(EditorBrowsableState.Never)]
public override int GetHashCode() => base.GetHashCode(); public override int GetHashCode() => base.GetHashCode();
/// <summary>
/// Returns a string that represents the current object.
/// </summary>
/// <returns>A string that represents the current object.</returns>
[EditorBrowsable(EditorBrowsableState.Never)]
public override string ToString() => base.ToString();
} }
} }

10
src/OpenIddict.EntityFramework/Configurations/OpenIddictApplicationConfiguration.cs

@ -65,11 +65,17 @@ namespace OpenIddict.EntityFramework
HasMany(application => application.Authorizations) HasMany(application => application.Authorizations)
.WithOptional(authorization => authorization.Application) .WithOptional(authorization => authorization.Application)
.Map(association => association.MapKey("ApplicationId")); .Map(association =>
{
association.MapKey(nameof(OpenIddictAuthorization.Application) + nameof(OpenIddictApplication.Id));
});
HasMany(application => application.Tokens) HasMany(application => application.Tokens)
.WithOptional(token => token.Application) .WithOptional(token => token.Application)
.Map(association => association.MapKey("ApplicationId")); .Map(association =>
{
association.MapKey(nameof(OpenIddictToken.Application) + nameof(OpenIddictApplication.Id));
});
ToTable("OpenIddictApplications"); ToTable("OpenIddictApplications");
} }

2
src/OpenIddict.EntityFramework/Configurations/OpenIddictAuthorizationConfiguration.cs

@ -63,7 +63,7 @@ namespace OpenIddict.EntityFramework
HasMany(authorization => authorization.Tokens) HasMany(authorization => authorization.Tokens)
.WithOptional(token => token.Authorization) .WithOptional(token => token.Authorization)
.Map(association => association.MapKey("AuthorizationId")) .Map(association => association.MapKey(nameof(OpenIddictToken.Authorization) + nameof(OpenIddictAuthorization.Id)))
.WillCascadeOnDelete(); .WillCascadeOnDelete();
ToTable("OpenIddictAuthorizations"); ToTable("OpenIddictAuthorizations");

14
src/OpenIddict.EntityFramework/OpenIddictEntityFrameworkBuilder.cs

@ -112,13 +112,6 @@ namespace Microsoft.Extensions.DependencyInjection
return Configure(options => options.DbContextType = type); return Configure(options => options.DbContextType = type);
} }
/// <summary>
/// Returns a string that represents the current object.
/// </summary>
/// <returns>A string that represents the current object.</returns>
[EditorBrowsable(EditorBrowsableState.Never)]
public override string ToString() => base.ToString();
/// <summary> /// <summary>
/// Determines whether the specified object is equal to the current object. /// Determines whether the specified object is equal to the current object.
/// </summary> /// </summary>
@ -133,5 +126,12 @@ namespace Microsoft.Extensions.DependencyInjection
/// <returns>A hash code for the current object.</returns> /// <returns>A hash code for the current object.</returns>
[EditorBrowsable(EditorBrowsableState.Never)] [EditorBrowsable(EditorBrowsableState.Never)]
public override int GetHashCode() => base.GetHashCode(); public override int GetHashCode() => base.GetHashCode();
/// <summary>
/// Returns a string that represents the current object.
/// </summary>
/// <returns>A string that represents the current object.</returns>
[EditorBrowsable(EditorBrowsableState.Never)]
public override string ToString() => base.ToString();
} }
} }

2
src/OpenIddict.EntityFrameworkCore/Configurations/OpenIddictAuthorizationConfiguration.cs

@ -64,7 +64,7 @@ namespace OpenIddict.EntityFrameworkCore
builder.HasMany(authorization => authorization.Tokens) builder.HasMany(authorization => authorization.Tokens)
.WithOne(token => token.Authorization) .WithOne(token => token.Authorization)
.HasForeignKey("AuthorizationId") .HasForeignKey(nameof(OpenIddictToken.Authorization) + nameof(OpenIddictAuthorization.Id))
.IsRequired(required: false); .IsRequired(required: false);
builder.ToTable("OpenIddictAuthorizations"); builder.ToTable("OpenIddictAuthorizations");

14
src/OpenIddict.EntityFrameworkCore/OpenIddictEntityFrameworkCoreBuilder.cs

@ -121,13 +121,6 @@ namespace Microsoft.Extensions.DependencyInjection
return Configure(options => options.DbContextType = type); return Configure(options => options.DbContextType = type);
} }
/// <summary>
/// Returns a string that represents the current object.
/// </summary>
/// <returns>A string that represents the current object.</returns>
[EditorBrowsable(EditorBrowsableState.Never)]
public override string ToString() => base.ToString();
/// <summary> /// <summary>
/// Determines whether the specified object is equal to the current object. /// Determines whether the specified object is equal to the current object.
/// </summary> /// </summary>
@ -142,5 +135,12 @@ namespace Microsoft.Extensions.DependencyInjection
/// <returns>A hash code for the current object.</returns> /// <returns>A hash code for the current object.</returns>
[EditorBrowsable(EditorBrowsableState.Never)] [EditorBrowsable(EditorBrowsableState.Never)]
public override int GetHashCode() => base.GetHashCode(); public override int GetHashCode() => base.GetHashCode();
/// <summary>
/// Returns a string that represents the current object.
/// </summary>
/// <returns>A string that represents the current object.</returns>
[EditorBrowsable(EditorBrowsableState.Never)]
public override string ToString() => base.ToString();
} }
} }

14
src/OpenIddict.MongoDb/OpenIddictMongoDbBuilder.cs

@ -198,13 +198,6 @@ namespace Microsoft.Extensions.DependencyInjection
return Configure(options => options.Database = database); return Configure(options => options.Database = database);
} }
/// <summary>
/// Returns a string that represents the current object.
/// </summary>
/// <returns>A string that represents the current object.</returns>
[EditorBrowsable(EditorBrowsableState.Never)]
public override string ToString() => base.ToString();
/// <summary> /// <summary>
/// Determines whether the specified object is equal to the current object. /// Determines whether the specified object is equal to the current object.
/// </summary> /// </summary>
@ -219,5 +212,12 @@ namespace Microsoft.Extensions.DependencyInjection
/// <returns>A hash code for the current object.</returns> /// <returns>A hash code for the current object.</returns>
[EditorBrowsable(EditorBrowsableState.Never)] [EditorBrowsable(EditorBrowsableState.Never)]
public override int GetHashCode() => base.GetHashCode(); public override int GetHashCode() => base.GetHashCode();
/// <summary>
/// Returns a string that represents the current object.
/// </summary>
/// <returns>A string that represents the current object.</returns>
[EditorBrowsable(EditorBrowsableState.Never)]
public override string ToString() => base.ToString();
} }
} }

14
src/OpenIddict.Mvc/OpenIddictMvcBuilder.cs

@ -64,13 +64,6 @@ namespace Microsoft.Extensions.DependencyInjection
public OpenIddictMvcBuilder DisableBindingExceptions() public OpenIddictMvcBuilder DisableBindingExceptions()
=> Configure(options => options.DisableBindingExceptions = true); => Configure(options => options.DisableBindingExceptions = true);
/// <summary>
/// Returns a string that represents the current object.
/// </summary>
/// <returns>A string that represents the current object.</returns>
[EditorBrowsable(EditorBrowsableState.Never)]
public override string ToString() => base.ToString();
/// <summary> /// <summary>
/// Determines whether the specified object is equal to the current object. /// Determines whether the specified object is equal to the current object.
/// </summary> /// </summary>
@ -85,5 +78,12 @@ namespace Microsoft.Extensions.DependencyInjection
/// <returns>A hash code for the current object.</returns> /// <returns>A hash code for the current object.</returns>
[EditorBrowsable(EditorBrowsableState.Never)] [EditorBrowsable(EditorBrowsableState.Never)]
public override int GetHashCode() => base.GetHashCode(); public override int GetHashCode() => base.GetHashCode();
/// <summary>
/// Returns a string that represents the current object.
/// </summary>
/// <returns>A string that represents the current object.</returns>
[EditorBrowsable(EditorBrowsableState.Never)]
public override string ToString() => base.ToString();
} }
} }

14
src/OpenIddict.Server/OpenIddictServerBuilder.cs

@ -803,13 +803,6 @@ namespace Microsoft.Extensions.DependencyInjection
public OpenIddictServerBuilder UseRollingTokens() public OpenIddictServerBuilder UseRollingTokens()
=> Configure(options => options.UseRollingTokens = true); => Configure(options => options.UseRollingTokens = true);
/// <summary>
/// Returns a string that represents the current object.
/// </summary>
/// <returns>A string that represents the current object.</returns>
[EditorBrowsable(EditorBrowsableState.Never)]
public override string ToString() => base.ToString();
/// <summary> /// <summary>
/// Determines whether the specified object is equal to the current object. /// Determines whether the specified object is equal to the current object.
/// </summary> /// </summary>
@ -824,5 +817,12 @@ namespace Microsoft.Extensions.DependencyInjection
/// <returns>A hash code for the current object.</returns> /// <returns>A hash code for the current object.</returns>
[EditorBrowsable(EditorBrowsableState.Never)] [EditorBrowsable(EditorBrowsableState.Never)]
public override int GetHashCode() => base.GetHashCode(); public override int GetHashCode() => base.GetHashCode();
/// <summary>
/// Returns a string that represents the current object.
/// </summary>
/// <returns>A string that represents the current object.</returns>
[EditorBrowsable(EditorBrowsableState.Never)]
public override string ToString() => base.ToString();
} }
} }

34
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. /// directly from your code. This API may change or be removed in future minor releases.
/// </summary> /// </summary>
public class OpenIddictValidationConfiguration : IConfigureOptions<AuthenticationOptions>, public class OpenIddictValidationConfiguration : IConfigureOptions<AuthenticationOptions>,
IPostConfigureOptions<AuthenticationOptions>,
IPostConfigureOptions<OpenIddictValidationOptions> IPostConfigureOptions<OpenIddictValidationOptions>
{ {
private readonly IDataProtectionProvider _dataProtectionProvider; private readonly IDataProtectionProvider _dataProtectionProvider;
@ -52,6 +53,39 @@ namespace OpenIddict.Validation.Internal
options.AddScheme<OpenIddictValidationHandler>(OpenIddictValidationDefaults.AuthenticationScheme, displayName: null); options.AddScheme<OpenIddictValidationHandler>(OpenIddictValidationDefaults.AuthenticationScheme, displayName: null);
} }
/// <summary>
/// Ensures that the authentication configuration is in a consistent and valid state.
/// </summary>
/// <param name="name">The authentication scheme associated with the handler instance.</param>
/// <param name="options">The options instance to initialize.</param>
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());
}
}
/// <summary> /// <summary>
/// Populates the default OpenIddict validation options and ensures /// Populates the default OpenIddict validation options and ensures
/// that the configuration is in a consistent and valid state. /// that the configuration is in a consistent and valid state.

14
src/OpenIddict.Validation/OpenIddictValidationBuilder.cs

@ -203,13 +203,6 @@ namespace Microsoft.Extensions.DependencyInjection
public OpenIddictValidationBuilder UseReferenceTokens() public OpenIddictValidationBuilder UseReferenceTokens()
=> Configure(options => options.UseReferenceTokens = true); => Configure(options => options.UseReferenceTokens = true);
/// <summary>
/// Returns a string that represents the current object.
/// </summary>
/// <returns>A string that represents the current object.</returns>
[EditorBrowsable(EditorBrowsableState.Never)]
public override string ToString() => base.ToString();
/// <summary> /// <summary>
/// Determines whether the specified object is equal to the current object. /// Determines whether the specified object is equal to the current object.
/// </summary> /// </summary>
@ -224,5 +217,12 @@ namespace Microsoft.Extensions.DependencyInjection
/// <returns>A hash code for the current object.</returns> /// <returns>A hash code for the current object.</returns>
[EditorBrowsable(EditorBrowsableState.Never)] [EditorBrowsable(EditorBrowsableState.Never)]
public override int GetHashCode() => base.GetHashCode(); public override int GetHashCode() => base.GetHashCode();
/// <summary>
/// Returns a string that represents the current object.
/// </summary>
/// <returns>A string that represents the current object.</returns>
[EditorBrowsable(EditorBrowsableState.Never)]
public override string ToString() => base.ToString();
} }
} }

1
src/OpenIddict.Validation/OpenIddictValidationExtensions.cs

@ -49,6 +49,7 @@ namespace Microsoft.Extensions.DependencyInjection
builder.Services.TryAddEnumerable(new[] builder.Services.TryAddEnumerable(new[]
{ {
ServiceDescriptor.Singleton<IConfigureOptions<AuthenticationOptions>, OpenIddictValidationConfiguration>(), ServiceDescriptor.Singleton<IConfigureOptions<AuthenticationOptions>, OpenIddictValidationConfiguration>(),
ServiceDescriptor.Singleton<IPostConfigureOptions<AuthenticationOptions>, OpenIddictValidationConfiguration>(),
ServiceDescriptor.Singleton<IPostConfigureOptions<OpenIddictValidationOptions>, OpenIddictValidationConfiguration>(), ServiceDescriptor.Singleton<IPostConfigureOptions<OpenIddictValidationOptions>, OpenIddictValidationConfiguration>(),
ServiceDescriptor.Singleton<IPostConfigureOptions<OpenIddictValidationOptions>, OAuthValidationInitializer>() ServiceDescriptor.Singleton<IPostConfigureOptions<OpenIddictValidationOptions>, OAuthValidationInitializer>()
}); });

28
test/OpenIddict.Validation.Tests/Internal/OpenIddictValidationConfigurationTests.cs

@ -15,6 +15,7 @@ using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.TestHost; using Microsoft.AspNetCore.TestHost;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Moq; using Moq;
using Xunit; using Xunit;
@ -22,6 +23,33 @@ namespace OpenIddict.Validation.Internal.Tests
{ {
public class OpenIddictValidationConfigurationTests 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<OpenIddictValidationHandler>(OpenIddictValidationDefaults.AuthenticationScheme, displayName: null);
var configuration = new OpenIddictValidationConfiguration(Mock.Of<IDataProtectionProvider>());
// Act and assert
var exception = Assert.Throws<InvalidOperationException>(() => 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] [Fact]
public void Configure_ThrowsAnExceptionWhenSchemeIsAlreadyRegisteredWithDifferentHandlerType() public void Configure_ThrowsAnExceptionWhenSchemeIsAlreadyRegisteredWithDifferentHandlerType()
{ {

Loading…
Cancel
Save