diff --git a/src/Microsoft.AspNetCore.Authorization.Policy/IPolicyEvaluator.cs b/src/Microsoft.AspNetCore.Authorization.Policy/IPolicyEvaluator.cs
index 1717a0ae0a..dd5e6fc038 100644
--- a/src/Microsoft.AspNetCore.Authorization.Policy/IPolicyEvaluator.cs
+++ b/src/Microsoft.AspNetCore.Authorization.Policy/IPolicyEvaluator.cs
@@ -28,9 +28,13 @@ namespace Microsoft.AspNetCore.Authorization.Policy
/// The .
/// The result of a call to .
/// The .
+ ///
+ /// 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.
+ ///
/// Returns if authorization succeeds.
/// Otherwise returns if , otherwise
/// returns
- Task AuthorizeAsync(AuthorizationPolicy policy, AuthenticateResult authenticationResult, HttpContext context);
+ Task AuthorizeAsync(AuthorizationPolicy policy, AuthenticateResult authenticationResult, HttpContext context, object resource);
}
}
\ No newline at end of file
diff --git a/src/Microsoft.AspNetCore.Authorization.Policy/PolicyEvaluator.cs b/src/Microsoft.AspNetCore.Authorization.Policy/PolicyEvaluator.cs
index f93c2d92a3..3100ff4d3e 100644
--- a/src/Microsoft.AspNetCore.Authorization.Policy/PolicyEvaluator.cs
+++ b/src/Microsoft.AspNetCore.Authorization.Policy/PolicyEvaluator.cs
@@ -67,17 +67,21 @@ namespace Microsoft.AspNetCore.Authorization.Policy
/// The .
/// The result of a call to .
/// The .
+ ///
+ /// 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.
+ ///
/// Returns if authorization succeeds.
/// Otherwise returns if , otherwise
/// returns
- public virtual async Task AuthorizeAsync(AuthorizationPolicy policy, AuthenticateResult authenticationResult, HttpContext context)
+ public virtual async Task 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();
diff --git a/test/Microsoft.AspNetCore.Authorization.Test/PolicyEvaluatorTests.cs b/test/Microsoft.AspNetCore.Authorization.Test/PolicyEvaluatorTests.cs
index 216fc1440e..2384e6db5f 100644
--- a/test/Microsoft.AspNetCore.Authorization.Test/PolicyEvaluatorTests.cs
+++ b/test/Microsoft.AspNetCore.Authorization.Test/PolicyEvaluatorTests.cs
@@ -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();
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();
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 setupServices = null)
+ {
+ var services = new ServiceCollection()
+ .AddAuthorization()
+ .AddAuthorizationPolicyEvaluator()
+ .AddLogging()
+ .AddOptions();
+ setupServices?.Invoke(services);
+ return services.BuildServiceProvider().GetRequiredService();
+ }
+
public class HappyAuthorization : IAuthorizationService
{
public Task AuthorizeAsync(ClaimsPrincipal user, object resource, IEnumerable requirements)