AuthZ PolicyEvalutor should take resource

This commit is contained in:
Hao Kung 2017-07-20 11:07:01 -07:00 коммит произвёл Hao Kung
Родитель ae63c32bff
Коммит 644f34e90d
3 изменённых файлов: 51 добавлений и 13 удалений

Просмотреть файл

@ -28,9 +28,13 @@ namespace Microsoft.AspNetCore.Authorization.Policy
/// <param name="policy">The <see cref="AuthorizationPolicy"/>.</param>
/// <param name="authenticationResult">The result of a call to <see cref="AuthenticateAsync(AuthorizationPolicy, HttpContext)"/>.</param>
/// <param name="context">The <see cref="HttpContext"/>.</param>
/// <param name="resource">
/// An optional resource the policy should be checked with.
/// If a resource is not required for policy evaluation you may pass null as the value.
/// </param>
/// <returns>Returns <see cref="PolicyAuthorizationResult.Success"/> if authorization succeeds.
/// Otherwise returns <see cref="PolicyAuthorizationResult.Forbid"/> if <see cref="AuthenticateResult.Succeeded"/>, otherwise
/// returns <see cref="PolicyAuthorizationResult.Challenge"/></returns>
Task<PolicyAuthorizationResult> AuthorizeAsync(AuthorizationPolicy policy, AuthenticateResult authenticationResult, HttpContext context);
Task<PolicyAuthorizationResult> AuthorizeAsync(AuthorizationPolicy policy, AuthenticateResult authenticationResult, HttpContext context, object resource);
}
}

Просмотреть файл

@ -67,17 +67,21 @@ namespace Microsoft.AspNetCore.Authorization.Policy
/// <param name="policy">The <see cref="AuthorizationPolicy"/>.</param>
/// <param name="authenticationResult">The result of a call to <see cref="AuthenticateAsync(AuthorizationPolicy, HttpContext)"/>.</param>
/// <param name="context">The <see cref="HttpContext"/>.</param>
/// <param name="resource">
/// An optional resource the policy should be checked with.
/// If a resource is not required for policy evaluation you may pass null as the value.
/// </param>
/// <returns>Returns <see cref="PolicyAuthorizationResult.Success"/> if authorization succeeds.
/// Otherwise returns <see cref="PolicyAuthorizationResult.Forbid"/> if <see cref="AuthenticateResult.Succeeded"/>, otherwise
/// returns <see cref="PolicyAuthorizationResult.Challenge"/></returns>
public virtual async Task<PolicyAuthorizationResult> AuthorizeAsync(AuthorizationPolicy policy, AuthenticateResult authenticationResult, HttpContext context)
public virtual async Task<PolicyAuthorizationResult> AuthorizeAsync(AuthorizationPolicy policy, AuthenticateResult authenticationResult, HttpContext context, object resource)
{
if (policy == null)
{
throw new ArgumentNullException(nameof(policy));
}
var result = await _authorization.AuthorizeAsync(context.User, context, policy);
var result = await _authorization.AuthorizeAsync(context.User, resource, policy);
if (result.Succeeded)
{
return PolicyAuthorizationResult.Success();

Просмотреть файл

@ -1,6 +1,7 @@
// Copyright (c) .NET Foundation. All rights reserved.
// 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;
@ -18,7 +19,7 @@ namespace Microsoft.AspNetCore.Authorization.Policy.Test
public async Task AuthenticateFailsIfNoPrincipalReturned()
{
// Arrange
var evaluator = new PolicyEvaluator(new HappyAuthorization());
var evaluator = BuildEvaluator();
var context = new DefaultHttpContext();
var services = new ServiceCollection().AddSingleton<IAuthenticationService, SadAuthentication>();
context.RequestServices = services.BuildServiceProvider();
@ -35,7 +36,7 @@ namespace Microsoft.AspNetCore.Authorization.Policy.Test
public async Task AuthenticateMergeSchemes()
{
// Arrange
var evaluator = new PolicyEvaluator(new HappyAuthorization());
var evaluator = BuildEvaluator();
var context = new DefaultHttpContext();
var services = new ServiceCollection().AddSingleton<IAuthenticationService, EchoAuthentication>();
context.RequestServices = services.BuildServiceProvider();
@ -54,12 +55,12 @@ namespace Microsoft.AspNetCore.Authorization.Policy.Test
public async Task AuthorizeSucceedsEvenIfAuthenticationFails()
{
// Arrange
var evaluator = new PolicyEvaluator(new HappyAuthorization());
var evaluator = BuildEvaluator();
var context = new DefaultHttpContext();
var policy = new AuthorizationPolicyBuilder().RequireAssertion(_ => true).Build();
// Act
var result = await evaluator.AuthorizeAsync(policy, AuthenticateResult.Fail("Nooo"), context);
var result = await evaluator.AuthorizeAsync(policy, AuthenticateResult.Fail("Nooo"), context, resource: null);
// Assert
Assert.True(result.Succeeded);
@ -67,16 +68,34 @@ namespace Microsoft.AspNetCore.Authorization.Policy.Test
Assert.False(result.Forbidden);
}
[Fact]
public async Task AuthorizeSucceedsOnlyIfResourceSpecified()
{
// Arrange
var evaluator = BuildEvaluator();
var context = new DefaultHttpContext();
var policy = new AuthorizationPolicyBuilder().RequireAssertion(c => c.Resource != null).Build();
var success = AuthenticateResult.Success(new AuthenticationTicket(new ClaimsPrincipal(), "whatever"));
// Act
var result = await evaluator.AuthorizeAsync(policy, success, context, resource: null);
var result2 = await evaluator.AuthorizeAsync(policy, success, context, resource: new object());
// Assert
Assert.False(result.Succeeded);
Assert.True(result2.Succeeded);
}
[Fact]
public async Task AuthorizeChallengesIfAuthenticationFails()
{
// Arrange
var evaluator = new PolicyEvaluator(new SadAuthorization());
var evaluator = BuildEvaluator();
var context = new DefaultHttpContext();
var policy = new AuthorizationPolicyBuilder().RequireAssertion(_ => true).Build();
var policy = new AuthorizationPolicyBuilder().RequireAssertion(_ => false).Build();
// Act
var result = await evaluator.AuthorizeAsync(policy, AuthenticateResult.Fail("Nooo"), context);
var result = await evaluator.AuthorizeAsync(policy, AuthenticateResult.Fail("Nooo"), context, resource: null);
// Assert
Assert.False(result.Succeeded);
@ -88,12 +107,12 @@ namespace Microsoft.AspNetCore.Authorization.Policy.Test
public async Task AuthorizeForbidsIfAuthenticationSuceeds()
{
// Arrange
var evaluator = new PolicyEvaluator(new SadAuthorization());
var evaluator = BuildEvaluator();
var context = new DefaultHttpContext();
var policy = new AuthorizationPolicyBuilder().RequireAssertion(_ => true).Build();
var policy = new AuthorizationPolicyBuilder().RequireAssertion(_ => false).Build();
// Act
var result = await evaluator.AuthorizeAsync(policy, AuthenticateResult.Success(new AuthenticationTicket(new ClaimsPrincipal(), "scheme")), context);
var result = await evaluator.AuthorizeAsync(policy, AuthenticateResult.Success(new AuthenticationTicket(new ClaimsPrincipal(), "scheme")), context, resource: null);
// Assert
Assert.False(result.Succeeded);
@ -101,6 +120,17 @@ namespace Microsoft.AspNetCore.Authorization.Policy.Test
Assert.True(result.Forbidden);
}
private IPolicyEvaluator BuildEvaluator(Action<IServiceCollection> setupServices = null)
{
var services = new ServiceCollection()
.AddAuthorization()
.AddAuthorizationPolicyEvaluator()
.AddLogging()
.AddOptions();
setupServices?.Invoke(services);
return services.BuildServiceProvider().GetRequiredService<IPolicyEvaluator>();
}
public class HappyAuthorization : IAuthorizationService
{
public Task<AuthorizationResult> AuthorizeAsync(ClaimsPrincipal user, object resource, IEnumerable<IAuthorizationRequirement> requirements)