AuthPolicy should use IPolicyProvider
This commit is contained in:
parent
e63f094a5f
commit
c7a46e4caf
|
|
@ -2,6 +2,7 @@
|
|||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Security.Claims;
|
||||
using System.Threading.Tasks;
|
||||
|
|
@ -29,14 +30,44 @@ namespace Microsoft.AspNetCore.Mvc.Authorization
|
|||
{
|
||||
throw new ArgumentNullException(nameof(policy));
|
||||
}
|
||||
|
||||
Policy = policy;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the authorization policy to be used.
|
||||
/// Initialize a new <see cref="AuthorizeFilter"/> instance.
|
||||
/// </summary>
|
||||
public AuthorizationPolicy Policy { get; }
|
||||
/// <param name="policyProvider">The <see cref="IAuthorizationPolicyProvider"/> to use to resolve policy names.</param>
|
||||
/// <param name="authorizeData">The <see cref="IAuthorizeData"/> to combine into an <see cref="IAuthorizeData"/>.</param>
|
||||
public AuthorizeFilter(IAuthorizationPolicyProvider policyProvider, IEnumerable<IAuthorizeData> authorizeData)
|
||||
{
|
||||
if (policyProvider == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(policyProvider));
|
||||
}
|
||||
if (authorizeData == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(authorizeData));
|
||||
}
|
||||
|
||||
PolicyProvider = policyProvider;
|
||||
AuthorizeData = authorizeData;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="IAuthorizationPolicyProvider"/> to use to resolve policy names.
|
||||
/// </summary>
|
||||
public IAuthorizationPolicyProvider PolicyProvider { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="IAuthorizeData"/> to combine into an <see cref="IAuthorizeData"/>.
|
||||
/// </summary>
|
||||
public IEnumerable<IAuthorizeData> AuthorizeData { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the authorization policy to be used. If null, the policy will be constructed via
|
||||
/// AuthorizePolicy.CombineAsync(PolicyProvider, AuthorizeData)
|
||||
/// </summary>
|
||||
public AuthorizationPolicy Policy { get; private set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual async Task OnAuthorizationAsync(AuthorizationFilterContext context)
|
||||
|
|
@ -46,11 +77,17 @@ namespace Microsoft.AspNetCore.Mvc.Authorization
|
|||
throw new ArgumentNullException(nameof(context));
|
||||
}
|
||||
|
||||
var effectivePolicy = Policy ?? await AuthorizationPolicy.CombineAsync(PolicyProvider, AuthorizeData);
|
||||
if (effectivePolicy == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Build a ClaimsPrincipal with the Policy's required authentication types
|
||||
if (Policy.AuthenticationSchemes != null && Policy.AuthenticationSchemes.Any())
|
||||
if (effectivePolicy.AuthenticationSchemes != null && effectivePolicy.AuthenticationSchemes.Any())
|
||||
{
|
||||
ClaimsPrincipal newPrincipal = null;
|
||||
foreach (var scheme in Policy.AuthenticationSchemes)
|
||||
foreach (var scheme in effectivePolicy.AuthenticationSchemes)
|
||||
{
|
||||
var result = await context.HttpContext.Authentication.AuthenticateAsync(scheme);
|
||||
if (result != null)
|
||||
|
|
@ -76,9 +113,9 @@ namespace Microsoft.AspNetCore.Mvc.Authorization
|
|||
var authService = httpContext.RequestServices.GetRequiredService<IAuthorizationService>();
|
||||
|
||||
// Note: Default Anonymous User is new ClaimsPrincipal(new ClaimsIdentity())
|
||||
if (!await authService.AuthorizeAsync(httpContext.User, context, Policy))
|
||||
if (!await authService.AuthorizeAsync(httpContext.User, context, effectivePolicy))
|
||||
{
|
||||
context.Result = new ChallengeResult(Policy.AuthenticationSchemes.ToArray());
|
||||
context.Result = new ChallengeResult(effectivePolicy.AuthenticationSchemes.ToArray());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,21 +2,22 @@
|
|||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc.ApplicationModels;
|
||||
using Microsoft.AspNetCore.Mvc.Authorization;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc.Internal
|
||||
{
|
||||
public class AuthorizationApplicationModelProvider : IApplicationModelProvider
|
||||
{
|
||||
private readonly AuthorizationOptions _authorizationOptions;
|
||||
private readonly IAuthorizationPolicyProvider _policyProvider;
|
||||
|
||||
public AuthorizationApplicationModelProvider(IOptions<AuthorizationOptions> authorizationOptionsAccessor)
|
||||
public AuthorizationApplicationModelProvider(IAuthorizationPolicyProvider policyProvider)
|
||||
{
|
||||
_authorizationOptions = authorizationOptionsAccessor.Value;
|
||||
_policyProvider = policyProvider;
|
||||
}
|
||||
|
||||
public int Order { get { return -1000 + 10; } }
|
||||
|
|
@ -33,18 +34,9 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
|||
throw new ArgumentNullException(nameof(context));
|
||||
}
|
||||
|
||||
AuthorizationPolicy policy;
|
||||
|
||||
foreach (var controllerModel in context.Result.Controllers)
|
||||
{
|
||||
policy = AuthorizationPolicy.Combine(
|
||||
_authorizationOptions,
|
||||
controllerModel.Attributes.OfType<IAuthorizeData>());
|
||||
if (policy != null)
|
||||
{
|
||||
controllerModel.Filters.Add(new AuthorizeFilter(policy));
|
||||
}
|
||||
|
||||
controllerModel.Filters.Add(new AuthorizeFilter(_policyProvider, controllerModel.Attributes.OfType<IAuthorizeData>()));
|
||||
foreach (var attribute in controllerModel.Attributes.OfType<IAllowAnonymous>())
|
||||
{
|
||||
controllerModel.Filters.Add(new AllowAnonymousFilter());
|
||||
|
|
@ -52,14 +44,7 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
|||
|
||||
foreach (var actionModel in controllerModel.Actions)
|
||||
{
|
||||
policy = AuthorizationPolicy.Combine(
|
||||
_authorizationOptions,
|
||||
actionModel.Attributes.OfType<IAuthorizeData>());
|
||||
if (policy != null)
|
||||
{
|
||||
actionModel.Filters.Add(new AuthorizeFilter(policy));
|
||||
}
|
||||
|
||||
actionModel.Filters.Add(new AuthorizeFilter(_policyProvider, actionModel.Attributes.OfType<IAuthorizeData>()));
|
||||
foreach (var attribute in actionModel.Attributes.OfType<IAllowAnonymous>())
|
||||
{
|
||||
actionModel.Filters.Add(new AllowAnonymousFilter());
|
||||
|
|
|
|||
|
|
@ -41,6 +41,31 @@ namespace Microsoft.AspNetCore.Mvc.Authorization
|
|||
Assert.Null(authorizationContext.Result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task AuthorizeFilterWillCallPolicyProviderOnAuthorization()
|
||||
{
|
||||
// Arrange
|
||||
var policyProvider = new Mock<IAuthorizationPolicyProvider>();
|
||||
var getPolicyCount = 0;
|
||||
policyProvider.Setup(p => p.GetPolicyAsync(It.IsAny<string>())).ReturnsAsync(new AuthorizationPolicyBuilder().RequireAssertion(_ => true).Build())
|
||||
.Callback(() => getPolicyCount++);
|
||||
var authorizeFilter = new AuthorizeFilter(policyProvider.Object, new AuthorizeAttribute[] { new AuthorizeAttribute("whatever") });
|
||||
var authorizationContext = GetAuthorizationContext(services => services.AddAuthorization());
|
||||
|
||||
// Act
|
||||
await authorizeFilter.OnAuthorizationAsync(authorizationContext);
|
||||
Assert.Equal(1, getPolicyCount);
|
||||
Assert.Null(authorizationContext.Result);
|
||||
|
||||
await authorizeFilter.OnAuthorizationAsync(authorizationContext);
|
||||
Assert.Equal(2, getPolicyCount);
|
||||
Assert.Null(authorizationContext.Result);
|
||||
|
||||
await authorizeFilter.OnAuthorizationAsync(authorizationContext);
|
||||
Assert.Equal(3, getPolicyCount);
|
||||
Assert.Null(authorizationContext.Result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task AuthorizeFilterCanAuthorizeNullUser()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
|||
public void CreateControllerModel_AuthorizeAttributeAddsAuthorizeFilter()
|
||||
{
|
||||
// Arrange
|
||||
var provider = new AuthorizationApplicationModelProvider(new TestOptionsManager<AuthorizationOptions>());
|
||||
var provider = new AuthorizationApplicationModelProvider(new DefaultAuthorizationPolicyProvider(new TestOptionsManager<AuthorizationOptions>()));
|
||||
var defaultProvider = new DefaultApplicationModelProvider(new TestOptionsManager<MvcOptions>());
|
||||
|
||||
var context = new ApplicationModelProviderContext(new[] { typeof(AccountController).GetTypeInfo() });
|
||||
|
|
@ -38,7 +38,7 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
|||
options.Value.AddPolicy("Base", policy => policy.RequireClaim("Basic").RequireClaim("Basic2"));
|
||||
options.Value.AddPolicy("Derived", policy => policy.RequireClaim("Derived"));
|
||||
|
||||
var provider = new AuthorizationApplicationModelProvider(options);
|
||||
var provider = new AuthorizationApplicationModelProvider(new DefaultAuthorizationPolicyProvider(options));
|
||||
var defaultProvider = new DefaultApplicationModelProvider(new TestOptionsManager<MvcOptions>());
|
||||
|
||||
var context = new ApplicationModelProviderContext(new[] { typeof(DerivedController).GetTypeInfo() });
|
||||
|
|
@ -56,14 +56,16 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
|||
Assert.Empty(attributeRoutes);
|
||||
var authorizeFilters = action.Filters.OfType<AuthorizeFilter>();
|
||||
Assert.Single(authorizeFilters);
|
||||
Assert.Equal(3, authorizeFilters.First().Policy.Requirements.Count);
|
||||
|
||||
Assert.NotNull(authorizeFilters.First().PolicyProvider);
|
||||
Assert.Equal(3, authorizeFilters.First().AuthorizeData.Count());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CreateControllerModelAndActionModel_AllowAnonymousAttributeAddsAllowAnonymousFilter()
|
||||
{
|
||||
// Arrange
|
||||
var provider = new AuthorizationApplicationModelProvider(new TestOptionsManager<AuthorizationOptions>());
|
||||
var provider = new AuthorizationApplicationModelProvider(new DefaultAuthorizationPolicyProvider(new TestOptionsManager<AuthorizationOptions>()));
|
||||
var defaultProvider = new DefaultApplicationModelProvider(new TestOptionsManager<MvcOptions>());
|
||||
|
||||
var context = new ApplicationModelProviderContext(new[] { typeof(AnonymousController).GetTypeInfo() });
|
||||
|
|
|
|||
Loading…
Reference in New Issue