Versatile OpenID Connect stack for ASP.NET Core and Microsoft.Owin (compatible with ASP.NET 4.6.1)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

95 lines
3.8 KiB

using System;
using System.Threading.Tasks;
using AspNet.Security.OpenIdConnect.Primitives;
using JetBrains.Annotations;
using Microsoft.AspNetCore.Mvc.ModelBinding;
using Microsoft.AspNetCore.Mvc.ModelBinding.Validation;
using Microsoft.Extensions.DependencyInjection;
namespace OpenIddict.Mvc
{
/// <summary>
/// Represents an ASP.NET Core MVC model binder that is able to bind
/// <see cref="OpenIdConnectRequest"/> and
/// <see cref="OpenIdConnectResponse"/> instances.
/// </summary>
public class OpenIddictModelBinder : IModelBinder, IModelBinderProvider
{
/// <summary>
/// Tries to bind a model from the request.
/// </summary>
/// <param name="context">The model binding context.</param>
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
public Task BindModelAsync([NotNull] ModelBindingContext context)
{
if (context == null)
{
throw new ArgumentNullException(nameof(context));
}
if (context.ModelType == typeof(OpenIdConnectRequest))
{
var request = context.HttpContext.GetOpenIdConnectRequest();
if (request == null)
{
throw new InvalidOperationException("The OpenID Connect request cannot be retrieved from the ASP.NET context. " +
"Make sure that 'app.UseOpenIddict()' is called before 'app.UseMvc()' and " +
"that the action route corresponds to the endpoint path registered via " +
"'services.AddOpenIddict().Enable[...]Endpoint(...)'.");
}
// Add a new validation state entry to prevent the built-in
// model validators from validating the OpenID Connect request.
context.ValidationState.Add(request, new ValidationStateEntry
{
SuppressValidation = true
});
context.Result = ModelBindingResult.Success(request);
return Task.FromResult(0);
}
else if (context.ModelType == typeof(OpenIdConnectResponse))
{
var response = context.HttpContext.GetOpenIdConnectResponse();
if (response != null)
{
// Add a new validation state entry to prevent the built-in
// model validators from validating the OpenID Connect response.
context.ValidationState.Add(response, new ValidationStateEntry
{
SuppressValidation = true
});
}
context.Result = ModelBindingResult.Success(response);
return Task.FromResult(0);
}
throw new InvalidOperationException("The specified model type is not supported by this binder.");
}
/// <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 this;
}
return null;
}
}
}