Skip to content
This repository was archived by the owner on Dec 13, 2018. It is now read-only.

Commit 869d98e

Browse files
committed
AuthZ PolicyEvalutor should take resource
1 parent ba7739f commit 869d98e

File tree

3 files changed

+51
-13
lines changed

3 files changed

+51
-13
lines changed

src/Microsoft.AspNetCore.Authorization.Policy/IPolicyEvaluator.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,13 @@ public interface IPolicyEvaluator
2828
/// <param name="policy">The <see cref="AuthorizationPolicy"/>.</param>
2929
/// <param name="authenticationResult">The result of a call to <see cref="AuthenticateAsync(AuthorizationPolicy, HttpContext)"/>.</param>
3030
/// <param name="context">The <see cref="HttpContext"/>.</param>
31+
/// <param name="resource">
32+
/// An optional resource the policy should be checked with.
33+
/// If a resource is not required for policy evaluation you may pass null as the value.
34+
/// </param>
3135
/// <returns>Returns <see cref="PolicyAuthorizationResult.Success"/> if authorization succeeds.
3236
/// Otherwise returns <see cref="PolicyAuthorizationResult.Forbid"/> if <see cref="AuthenticateResult.Succeeded"/>, otherwise
3337
/// returns <see cref="PolicyAuthorizationResult.Challenge"/></returns>
34-
Task<PolicyAuthorizationResult> AuthorizeAsync(AuthorizationPolicy policy, AuthenticateResult authenticationResult, HttpContext context);
38+
Task<PolicyAuthorizationResult> AuthorizeAsync(AuthorizationPolicy policy, AuthenticateResult authenticationResult, HttpContext context, object resource);
3539
}
3640
}

src/Microsoft.AspNetCore.Authorization.Policy/PolicyEvaluator.cs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,17 +67,21 @@ public virtual async Task<AuthenticateResult> AuthenticateAsync(AuthorizationPol
6767
/// <param name="policy">The <see cref="AuthorizationPolicy"/>.</param>
6868
/// <param name="authenticationResult">The result of a call to <see cref="AuthenticateAsync(AuthorizationPolicy, HttpContext)"/>.</param>
6969
/// <param name="context">The <see cref="HttpContext"/>.</param>
70+
/// <param name="resource">
71+
/// An optional resource the policy should be checked with.
72+
/// If a resource is not required for policy evaluation you may pass null as the value.
73+
/// </param>
7074
/// <returns>Returns <see cref="PolicyAuthorizationResult.Success"/> if authorization succeeds.
7175
/// Otherwise returns <see cref="PolicyAuthorizationResult.Forbid"/> if <see cref="AuthenticateResult.Succeeded"/>, otherwise
7276
/// returns <see cref="PolicyAuthorizationResult.Challenge"/></returns>
73-
public virtual async Task<PolicyAuthorizationResult> AuthorizeAsync(AuthorizationPolicy policy, AuthenticateResult authenticationResult, HttpContext context)
77+
public virtual async Task<PolicyAuthorizationResult> AuthorizeAsync(AuthorizationPolicy policy, AuthenticateResult authenticationResult, HttpContext context, object resource)
7478
{
7579
if (policy == null)
7680
{
7781
throw new ArgumentNullException(nameof(policy));
7882
}
7983

80-
var result = await _authorization.AuthorizeAsync(context.User, context, policy);
84+
var result = await _authorization.AuthorizeAsync(context.User, resource, policy);
8185
if (result.Succeeded)
8286
{
8387
return PolicyAuthorizationResult.Success();

test/Microsoft.AspNetCore.Authorization.Test/PolicyEvaluatorTests.cs

Lines changed: 40 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// Copyright (c) .NET Foundation. All rights reserved.
22
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
33

4+
using System;
45
using System.Collections.Generic;
56
using System.Linq;
67
using System.Security.Claims;
@@ -18,7 +19,7 @@ public class PolicyEvaluatorTests
1819
public async Task AuthenticateFailsIfNoPrincipalReturned()
1920
{
2021
// Arrange
21-
var evaluator = new PolicyEvaluator(new HappyAuthorization());
22+
var evaluator = BuildEvaluator();
2223
var context = new DefaultHttpContext();
2324
var services = new ServiceCollection().AddSingleton<IAuthenticationService, SadAuthentication>();
2425
context.RequestServices = services.BuildServiceProvider();
@@ -35,7 +36,7 @@ public async Task AuthenticateFailsIfNoPrincipalReturned()
3536
public async Task AuthenticateMergeSchemes()
3637
{
3738
// Arrange
38-
var evaluator = new PolicyEvaluator(new HappyAuthorization());
39+
var evaluator = BuildEvaluator();
3940
var context = new DefaultHttpContext();
4041
var services = new ServiceCollection().AddSingleton<IAuthenticationService, EchoAuthentication>();
4142
context.RequestServices = services.BuildServiceProvider();
@@ -54,29 +55,47 @@ public async Task AuthenticateMergeSchemes()
5455
public async Task AuthorizeSucceedsEvenIfAuthenticationFails()
5556
{
5657
// Arrange
57-
var evaluator = new PolicyEvaluator(new HappyAuthorization());
58+
var evaluator = BuildEvaluator();
5859
var context = new DefaultHttpContext();
5960
var policy = new AuthorizationPolicyBuilder().RequireAssertion(_ => true).Build();
6061

6162
// Act
62-
var result = await evaluator.AuthorizeAsync(policy, AuthenticateResult.Fail("Nooo"), context);
63+
var result = await evaluator.AuthorizeAsync(policy, AuthenticateResult.Fail("Nooo"), context, resource: null);
6364

6465
// Assert
6566
Assert.True(result.Succeeded);
6667
Assert.False(result.Challenged);
6768
Assert.False(result.Forbidden);
6869
}
6970

71+
[Fact]
72+
public async Task AuthorizeSucceedsOnlyIfResourceSpecified()
73+
{
74+
// Arrange
75+
var evaluator = BuildEvaluator();
76+
var context = new DefaultHttpContext();
77+
var policy = new AuthorizationPolicyBuilder().RequireAssertion(c => c.Resource != null).Build();
78+
var success = AuthenticateResult.Success(new AuthenticationTicket(new ClaimsPrincipal(), "whatever"));
79+
80+
// Act
81+
var result = await evaluator.AuthorizeAsync(policy, success, context, resource: null);
82+
var result2 = await evaluator.AuthorizeAsync(policy, success, context, resource: new object());
83+
84+
// Assert
85+
Assert.False(result.Succeeded);
86+
Assert.True(result2.Succeeded);
87+
}
88+
7089
[Fact]
7190
public async Task AuthorizeChallengesIfAuthenticationFails()
7291
{
7392
// Arrange
74-
var evaluator = new PolicyEvaluator(new SadAuthorization());
93+
var evaluator = BuildEvaluator();
7594
var context = new DefaultHttpContext();
76-
var policy = new AuthorizationPolicyBuilder().RequireAssertion(_ => true).Build();
95+
var policy = new AuthorizationPolicyBuilder().RequireAssertion(_ => false).Build();
7796

7897
// Act
79-
var result = await evaluator.AuthorizeAsync(policy, AuthenticateResult.Fail("Nooo"), context);
98+
var result = await evaluator.AuthorizeAsync(policy, AuthenticateResult.Fail("Nooo"), context, resource: null);
8099

81100
// Assert
82101
Assert.False(result.Succeeded);
@@ -88,19 +107,30 @@ public async Task AuthorizeChallengesIfAuthenticationFails()
88107
public async Task AuthorizeForbidsIfAuthenticationSuceeds()
89108
{
90109
// Arrange
91-
var evaluator = new PolicyEvaluator(new SadAuthorization());
110+
var evaluator = BuildEvaluator();
92111
var context = new DefaultHttpContext();
93-
var policy = new AuthorizationPolicyBuilder().RequireAssertion(_ => true).Build();
112+
var policy = new AuthorizationPolicyBuilder().RequireAssertion(_ => false).Build();
94113

95114
// Act
96-
var result = await evaluator.AuthorizeAsync(policy, AuthenticateResult.Success(new AuthenticationTicket(new ClaimsPrincipal(), "scheme")), context);
115+
var result = await evaluator.AuthorizeAsync(policy, AuthenticateResult.Success(new AuthenticationTicket(new ClaimsPrincipal(), "scheme")), context, resource: null);
97116

98117
// Assert
99118
Assert.False(result.Succeeded);
100119
Assert.False(result.Challenged);
101120
Assert.True(result.Forbidden);
102121
}
103122

123+
private IPolicyEvaluator BuildEvaluator(Action<IServiceCollection> setupServices = null)
124+
{
125+
var services = new ServiceCollection()
126+
.AddAuthorization()
127+
.AddAuthorizationPolicyEvaluator()
128+
.AddLogging()
129+
.AddOptions();
130+
setupServices?.Invoke(services);
131+
return services.BuildServiceProvider().GetRequiredService<IPolicyEvaluator>();
132+
}
133+
104134
public class HappyAuthorization : IAuthorizationService
105135
{
106136
public Task<AuthorizationResult> AuthorizeAsync(ClaimsPrincipal user, object resource, IEnumerable<IAuthorizationRequirement> requirements)

0 commit comments

Comments
 (0)