16 changed files with 585 additions and 210 deletions
@ -1,47 +0,0 @@ |
|||
/* |
|||
* Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
|
|||
* See https://github.com/openiddict/openiddict-core for more information concerning
|
|||
* the license and the contributors participating to this project. |
|||
*/ |
|||
|
|||
using System; |
|||
using JetBrains.Annotations; |
|||
using Microsoft.AspNetCore.Mvc; |
|||
using OpenIddict.Mvc; |
|||
|
|||
namespace Microsoft.Extensions.DependencyInjection |
|||
{ |
|||
public static class OpenIddictExtensions |
|||
{ |
|||
/// <summary>
|
|||
/// Registers the ASP.NET Core MVC model binders used by OpenIddict.
|
|||
/// </summary>
|
|||
/// <param name="builder">The services builder used by OpenIddict to register new services.</param>
|
|||
/// <remarks>This extension can be safely called multiple times.</remarks>
|
|||
/// <returns>The <see cref="OpenIddictServerBuilder"/>.</returns>
|
|||
public static OpenIddictServerBuilder AddMvcBinders([NotNull] this OpenIddictServerBuilder builder) |
|||
{ |
|||
if (builder == null) |
|||
{ |
|||
throw new ArgumentNullException(nameof(builder)); |
|||
} |
|||
|
|||
builder.Services.Configure<MvcOptions>(options => |
|||
{ |
|||
// Skip the binder registration if it was already added to the providers collection.
|
|||
for (var index = 0; index < options.ModelBinderProviders.Count; index++) |
|||
{ |
|||
var provider = options.ModelBinderProviders[index]; |
|||
if (provider is OpenIddictModelBinder) |
|||
{ |
|||
return; |
|||
} |
|||
} |
|||
|
|||
options.ModelBinderProviders.Insert(0, new OpenIddictModelBinder()); |
|||
}); |
|||
|
|||
return builder; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,42 @@ |
|||
/* |
|||
* Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
|
|||
* See https://github.com/openiddict/openiddict-core for more information concerning
|
|||
* the license and the contributors participating to this project. |
|||
*/ |
|||
|
|||
using System; |
|||
using AspNet.Security.OpenIdConnect.Primitives; |
|||
using JetBrains.Annotations; |
|||
using Microsoft.AspNetCore.Mvc.ModelBinding; |
|||
using Microsoft.AspNetCore.Mvc.ModelBinding.Binders; |
|||
|
|||
namespace OpenIddict.Mvc |
|||
{ |
|||
/// <summary>
|
|||
/// Represents an ASP.NET Core MVC model binder provider that is
|
|||
/// able to provide instances of <see cref="OpenIddictMvcBinder"/>.
|
|||
/// </summary>
|
|||
public class OpenIddictMvcBinderProvider : IModelBinderProvider |
|||
{ |
|||
/// <summary>
|
|||
/// Tries to resolve the model binder corresponding to the given model.
|
|||
/// </summary>
|
|||
/// <param name="context">The model binding context.</param>
|
|||
/// <returns>The current instance or <c>null</c> if the model is not supported.</returns>
|
|||
public IModelBinder GetBinder([NotNull] ModelBinderProviderContext context) |
|||
{ |
|||
if (context == null) |
|||
{ |
|||
throw new ArgumentNullException(nameof(context)); |
|||
} |
|||
|
|||
if (context.Metadata.ModelType == typeof(OpenIdConnectRequest) || |
|||
context.Metadata.ModelType == typeof(OpenIdConnectResponse)) |
|||
{ |
|||
return new BinderTypeModelBinder(typeof(OpenIddictMvcBinder)); |
|||
} |
|||
|
|||
return null; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,67 @@ |
|||
/* |
|||
* Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
|
|||
* See https://github.com/openiddict/openiddict-core for more information concerning
|
|||
* the license and the contributors participating to this project. |
|||
*/ |
|||
|
|||
using System; |
|||
using System.ComponentModel; |
|||
using AspNet.Security.OpenIdConnect.Primitives; |
|||
using JetBrains.Annotations; |
|||
using OpenIddict.Mvc; |
|||
|
|||
namespace Microsoft.Extensions.DependencyInjection |
|||
{ |
|||
/// <summary>
|
|||
/// Exposes the necessary methods required to configure the OpenIddict MVC integration.
|
|||
/// </summary>
|
|||
public class OpenIddictMvcBuilder |
|||
{ |
|||
/// <summary>
|
|||
/// Initializes a new instance of <see cref="OpenIddictMvcBuilder"/>.
|
|||
/// </summary>
|
|||
/// <param name="services">The services collection.</param>
|
|||
public OpenIddictMvcBuilder([NotNull] IServiceCollection services) |
|||
{ |
|||
if (services == null) |
|||
{ |
|||
throw new ArgumentNullException(nameof(services)); |
|||
} |
|||
|
|||
Services = services; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the services collection.
|
|||
/// </summary>
|
|||
[EditorBrowsable(EditorBrowsableState.Never)] |
|||
public IServiceCollection Services { get; } |
|||
|
|||
/// <summary>
|
|||
/// Amends the default OpenIddict MVC configuration.
|
|||
/// </summary>
|
|||
/// <param name="configuration">The delegate used to configure the OpenIddict options.</param>
|
|||
/// <remarks>This extension can be safely called multiple times.</remarks>
|
|||
/// <returns>The <see cref="OpenIddictMvcBuilder"/>.</returns>
|
|||
public OpenIddictMvcBuilder Configure([NotNull] Action<OpenIddictMvcOptions> configuration) |
|||
{ |
|||
if (configuration == null) |
|||
{ |
|||
throw new ArgumentNullException(nameof(configuration)); |
|||
} |
|||
|
|||
Services.Configure(configuration); |
|||
|
|||
return this; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Configures the OpenIddict MVC binder to avoid throwing an exception
|
|||
/// when it is unable to bind <see cref="OpenIdConnectRequest"/>
|
|||
/// parameters (e.g because the endpoint is not an OpenID Connect endpoint).
|
|||
/// </summary>
|
|||
/// <returns>The <see cref="OpenIddictMvcBuilder"/>.</returns>
|
|||
public OpenIddictMvcBuilder DisableBindingExceptions() |
|||
=> Configure(options => options.DisableBindingExceptions = true); |
|||
} |
|||
} |
|||
@ -0,0 +1,157 @@ |
|||
/* |
|||
* Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
|
|||
* See https://github.com/openiddict/openiddict-core for more information concerning
|
|||
* the license and the contributors participating to this project. |
|||
*/ |
|||
|
|||
using System; |
|||
using JetBrains.Annotations; |
|||
using Microsoft.AspNetCore.Mvc; |
|||
using OpenIddict.Mvc; |
|||
|
|||
namespace Microsoft.Extensions.DependencyInjection |
|||
{ |
|||
public static class OpenIddictMvcExtensions |
|||
{ |
|||
/// <summary>
|
|||
/// Registers the ASP.NET Core MVC services used by OpenIddict.
|
|||
/// </summary>
|
|||
/// <param name="builder">The services builder used by OpenIddict to register new services.</param>
|
|||
/// <remarks>This extension can be safely called multiple times.</remarks>
|
|||
/// <returns>The <see cref="OpenIddictMvcBuilder"/>.</returns>
|
|||
public static OpenIddictMvcBuilder UseMvc([NotNull] this OpenIddictServerBuilder builder) |
|||
{ |
|||
if (builder == null) |
|||
{ |
|||
throw new ArgumentNullException(nameof(builder)); |
|||
} |
|||
|
|||
return RegisterMvcServices(builder.Services); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Registers the ASP.NET Core MVC model binders used by OpenIddict.
|
|||
/// </summary>
|
|||
/// <param name="builder">The services builder used by OpenIddict to register new services.</param>
|
|||
/// <param name="configuration">The configuration delegate used to configure the MVC services.</param>
|
|||
/// <remarks>This extension can be safely called multiple times.</remarks>
|
|||
/// <returns>The <see cref="OpenIddictServerBuilder"/>.</returns>
|
|||
public static OpenIddictServerBuilder UseMvc( |
|||
[NotNull] this OpenIddictServerBuilder builder, |
|||
[NotNull] Action<OpenIddictMvcBuilder> configuration) |
|||
{ |
|||
if (builder == null) |
|||
{ |
|||
throw new ArgumentNullException(nameof(builder)); |
|||
} |
|||
|
|||
configuration(builder.UseMvc()); |
|||
|
|||
return builder; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Registers the ASP.NET Core MVC services used by OpenIddict.
|
|||
/// </summary>
|
|||
/// <param name="builder">The services builder used by ASP.NET Core MVC to register new services.</param>
|
|||
/// <remarks>This extension can be safely called multiple times.</remarks>
|
|||
/// <returns>The <see cref="OpenIddictMvcBuilder"/>.</returns>
|
|||
public static OpenIddictMvcBuilder UseOpenIddict([NotNull] this IMvcCoreBuilder builder) |
|||
{ |
|||
if (builder == null) |
|||
{ |
|||
throw new ArgumentNullException(nameof(builder)); |
|||
} |
|||
|
|||
return RegisterMvcServices(builder.Services); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Registers the ASP.NET Core MVC model binders used by OpenIddict.
|
|||
/// </summary>
|
|||
/// <param name="builder">The services builder used by ASP.NET Core MVC to register new services.</param>
|
|||
/// <param name="configuration">The configuration delegate used to configure the MVC services.</param>
|
|||
/// <remarks>This extension can be safely called multiple times.</remarks>
|
|||
/// <returns>The <see cref="IMvcCoreBuilder"/>.</returns>
|
|||
public static IMvcCoreBuilder UseOpenIddict( |
|||
[NotNull] this IMvcCoreBuilder builder, |
|||
[NotNull] Action<OpenIddictMvcBuilder> configuration) |
|||
{ |
|||
if (builder == null) |
|||
{ |
|||
throw new ArgumentNullException(nameof(builder)); |
|||
} |
|||
|
|||
configuration(builder.UseOpenIddict()); |
|||
|
|||
return builder; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Registers the ASP.NET Core MVC services used by OpenIddict.
|
|||
/// </summary>
|
|||
/// <param name="builder">The services builder used by ASP.NET Core MVC to register new services.</param>
|
|||
/// <remarks>This extension can be safely called multiple times.</remarks>
|
|||
/// <returns>The <see cref="OpenIddictMvcBuilder"/>.</returns>
|
|||
public static OpenIddictMvcBuilder UseOpenIddict([NotNull] this IMvcBuilder builder) |
|||
{ |
|||
if (builder == null) |
|||
{ |
|||
throw new ArgumentNullException(nameof(builder)); |
|||
} |
|||
|
|||
return RegisterMvcServices(builder.Services); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Registers the ASP.NET Core MVC model binders used by OpenIddict.
|
|||
/// </summary>
|
|||
/// <param name="builder">The services builder used by ASP.NET Core MVC to register new services.</param>
|
|||
/// <param name="configuration">The configuration delegate used to configure the MVC services.</param>
|
|||
/// <remarks>This extension can be safely called multiple times.</remarks>
|
|||
/// <returns>The <see cref="IMvcBuilder"/>.</returns>
|
|||
public static IMvcBuilder UseOpenIddict( |
|||
[NotNull] this IMvcBuilder builder, |
|||
[NotNull] Action<OpenIddictMvcBuilder> configuration) |
|||
{ |
|||
if (builder == null) |
|||
{ |
|||
throw new ArgumentNullException(nameof(builder)); |
|||
} |
|||
|
|||
configuration(builder.UseOpenIddict()); |
|||
|
|||
return builder; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Registers the ASP.NET Core MVC services used by OpenIddict.
|
|||
/// </summary>
|
|||
/// <param name="services">The services collection.</param>
|
|||
/// <returns>The <see cref="OpenIddictMvcBuilder"/>.</returns>
|
|||
private static OpenIddictMvcBuilder RegisterMvcServices([NotNull] IServiceCollection services) |
|||
{ |
|||
if (services == null) |
|||
{ |
|||
throw new ArgumentNullException(nameof(services)); |
|||
} |
|||
|
|||
services.Configure<MvcOptions>(options => |
|||
{ |
|||
// Skip the binder registration if it was already added to the providers collection.
|
|||
for (var index = 0; index < options.ModelBinderProviders.Count; index++) |
|||
{ |
|||
var provider = options.ModelBinderProviders[index]; |
|||
if (provider is OpenIddictMvcBinderProvider) |
|||
{ |
|||
return; |
|||
} |
|||
} |
|||
|
|||
options.ModelBinderProviders.Insert(0, new OpenIddictMvcBinderProvider()); |
|||
}); |
|||
|
|||
return new OpenIddictMvcBuilder(services); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,24 @@ |
|||
/* |
|||
* Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
|
|||
* See https://github.com/openiddict/openiddict-core for more information concerning
|
|||
* the license and the contributors participating to this project. |
|||
*/ |
|||
|
|||
using AspNet.Security.OpenIdConnect.Primitives; |
|||
|
|||
namespace OpenIddict.Mvc |
|||
{ |
|||
/// <summary>
|
|||
/// Provides various settings needed to configure the OpenIddict MVC integration.
|
|||
/// </summary>
|
|||
public class OpenIddictMvcOptions |
|||
{ |
|||
/// <summary>
|
|||
/// Gets or sets a boolean indicating whether the OpenIddict MVC binder should throw
|
|||
/// an exception when it is unable to bind <see cref="OpenIdConnectRequest"/>
|
|||
/// parameters (e.g because the endpoint is not an OpenID Connect endpoint).
|
|||
/// If exceptions are disabled, the model is automatically set to <c>null</c>.
|
|||
/// </summary>
|
|||
public bool DisableBindingExceptions { get; set; } |
|||
} |
|||
} |
|||
@ -1,35 +0,0 @@ |
|||
/* |
|||
* Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
|
|||
* See https://github.com/openiddict/openiddict-core for more information concerning
|
|||
* the license and the contributors participating to this project. |
|||
*/ |
|||
|
|||
using Microsoft.AspNetCore.Mvc; |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using Microsoft.Extensions.Options; |
|||
using Xunit; |
|||
|
|||
namespace OpenIddict.Mvc.Tests |
|||
{ |
|||
public class OpenIddictExtensionsTests |
|||
{ |
|||
[Fact] |
|||
public void AddMvcBinders_RegistersModelBinderProvider() |
|||
{ |
|||
// Arrange
|
|||
var services = new ServiceCollection(); |
|||
services.AddOptions(); |
|||
|
|||
var builder = services.AddOpenIddict().AddServer(); |
|||
|
|||
// Act
|
|||
builder.AddMvcBinders(); |
|||
|
|||
var provider = services.BuildServiceProvider(); |
|||
var options = provider.GetRequiredService<IOptions<MvcOptions>>(); |
|||
|
|||
// Assert
|
|||
Assert.Contains(options.Value.ModelBinderProviders, binder => binder is OpenIddictModelBinder); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,43 @@ |
|||
/* |
|||
* Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
|
|||
* See https://github.com/openiddict/openiddict-core for more information concerning
|
|||
* the license and the contributors participating to this project. |
|||
*/ |
|||
|
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using Microsoft.Extensions.Options; |
|||
using Xunit; |
|||
|
|||
namespace OpenIddict.Mvc.Tests |
|||
{ |
|||
public class OpenIddictMvcBuilderTests |
|||
{ |
|||
[Fact] |
|||
public void Configure_OptionsAreCorrectlyAmended() |
|||
{ |
|||
// Arrange
|
|||
var services = CreateServices(); |
|||
var builder = CreateBuilder(services); |
|||
|
|||
// Act
|
|||
builder.Configure(configuration => configuration.DisableBindingExceptions = true); |
|||
|
|||
var options = GetOptions(services); |
|||
|
|||
// Assert
|
|||
Assert.True(options.DisableBindingExceptions); |
|||
} |
|||
|
|||
private static IServiceCollection CreateServices() |
|||
=> new ServiceCollection().AddOptions(); |
|||
|
|||
private static OpenIddictMvcBuilder CreateBuilder(IServiceCollection services) |
|||
=> new OpenIddictMvcBuilder(services); |
|||
|
|||
private static OpenIddictMvcOptions GetOptions(IServiceCollection services) |
|||
{ |
|||
var provider = services.BuildServiceProvider(); |
|||
return provider.GetRequiredService<IOptionsMonitor<OpenIddictMvcOptions>>().CurrentValue; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,75 @@ |
|||
/* |
|||
* Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
|
|||
* See https://github.com/openiddict/openiddict-core for more information concerning
|
|||
* the license and the contributors participating to this project. |
|||
*/ |
|||
|
|||
using Microsoft.AspNetCore.Mvc; |
|||
using Microsoft.AspNetCore.Mvc.ApplicationParts; |
|||
using Microsoft.AspNetCore.Mvc.Internal; |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using Microsoft.Extensions.Options; |
|||
using Xunit; |
|||
|
|||
namespace OpenIddict.Mvc.Tests |
|||
{ |
|||
public class OpenIddictMvcExtensionsTests |
|||
{ |
|||
[Fact] |
|||
public void UseMvc_RegistersModelBinderProvider() |
|||
{ |
|||
// Arrange
|
|||
var services = new ServiceCollection(); |
|||
services.AddOptions(); |
|||
|
|||
var builder = new OpenIddictServerBuilder(services); |
|||
|
|||
// Act
|
|||
builder.UseMvc(); |
|||
|
|||
var provider = services.BuildServiceProvider(); |
|||
var options = provider.GetRequiredService<IOptions<MvcOptions>>(); |
|||
|
|||
// Assert
|
|||
Assert.Contains(options.Value.ModelBinderProviders, binder => binder is OpenIddictMvcBinderProvider); |
|||
} |
|||
|
|||
[Fact] |
|||
public void UseOpenIddict_MvcCoreBuilder_RegistersModelBinderProvider() |
|||
{ |
|||
// Arrange
|
|||
var services = new ServiceCollection(); |
|||
services.AddOptions(); |
|||
|
|||
var builder = new MvcCoreBuilder(services, new ApplicationPartManager()); |
|||
|
|||
// Act
|
|||
builder.UseOpenIddict(); |
|||
|
|||
var provider = services.BuildServiceProvider(); |
|||
var options = provider.GetRequiredService<IOptions<MvcOptions>>(); |
|||
|
|||
// Assert
|
|||
Assert.Contains(options.Value.ModelBinderProviders, binder => binder is OpenIddictMvcBinderProvider); |
|||
} |
|||
|
|||
[Fact] |
|||
public void UseOpenIddict_MvcBuilder_RegistersModelBinderProvider() |
|||
{ |
|||
// Arrange
|
|||
var services = new ServiceCollection(); |
|||
services.AddOptions(); |
|||
|
|||
var builder = new MvcBuilder(services, new ApplicationPartManager()); |
|||
|
|||
// Act
|
|||
builder.UseOpenIddict(); |
|||
|
|||
var provider = services.BuildServiceProvider(); |
|||
var options = provider.GetRequiredService<IOptions<MvcOptions>>(); |
|||
|
|||
// Assert
|
|||
Assert.Contains(options.Value.ModelBinderProviders, binder => binder is OpenIddictMvcBinderProvider); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,63 @@ |
|||
/* |
|||
* Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
|
|||
* See https://github.com/openiddict/openiddict-core for more information concerning
|
|||
* the license and the contributors participating to this project. |
|||
*/ |
|||
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Threading.Tasks; |
|||
using AspNet.Security.OpenIdConnect.Primitives; |
|||
using AspNet.Security.OpenIdConnect.Server; |
|||
using Microsoft.AspNetCore.Http; |
|||
using Microsoft.AspNetCore.Http.Features; |
|||
using Microsoft.AspNetCore.Mvc; |
|||
using Microsoft.AspNetCore.Mvc.ModelBinding; |
|||
using Microsoft.AspNetCore.Mvc.ModelBinding.Binders; |
|||
using Microsoft.AspNetCore.Mvc.ModelBinding.Metadata; |
|||
using Microsoft.AspNetCore.Mvc.ModelBinding.Validation; |
|||
using Moq; |
|||
using Xunit; |
|||
|
|||
namespace OpenIddict.Mvc.Tests |
|||
{ |
|||
public class OpenIddictMvcModelBinderProviderTests |
|||
{ |
|||
[Theory] |
|||
[InlineData(typeof(object))] |
|||
[InlineData(typeof(IList<int>))] |
|||
[InlineData(typeof(int[]))] |
|||
public void GetBinder_ReturnsNullForUnsupportedTypes(Type type) |
|||
{ |
|||
// Arrange
|
|||
var provider = new OpenIddictMvcBinderProvider(); |
|||
|
|||
var metadata = new Mock<ModelMetadata>(ModelMetadataIdentity.ForType(type)); |
|||
|
|||
var context = new Mock<ModelBinderProviderContext>(); |
|||
context.Setup(mock => mock.Metadata) |
|||
.Returns(metadata.Object); |
|||
|
|||
// Act and assert
|
|||
Assert.Null(provider.GetBinder(context.Object)); |
|||
} |
|||
|
|||
[Theory] |
|||
[InlineData(typeof(OpenIdConnectRequest))] |
|||
[InlineData(typeof(OpenIdConnectResponse))] |
|||
public void GetBinder_ReturnsNonNullForSupportedTypes(Type type) |
|||
{ |
|||
// Arrange
|
|||
var provider = new OpenIddictMvcBinderProvider(); |
|||
|
|||
var metadata = new Mock<ModelMetadata>(ModelMetadataIdentity.ForType(type)); |
|||
|
|||
var context = new Mock<ModelBinderProviderContext>(); |
|||
context.Setup(mock => mock.Metadata) |
|||
.Returns(metadata.Object); |
|||
|
|||
// Act and assert
|
|||
Assert.NotNull((BinderTypeModelBinder) provider.GetBinder(context.Object)); |
|||
} |
|||
} |
|||
} |
|||
Loading…
Reference in new issue