diff --git a/src/Security/Authorization/Policy/src/AuthorizationMiddleware.cs b/src/Security/Authorization/Policy/src/AuthorizationMiddleware.cs index 119cc75c92..d876781f96 100644 --- a/src/Security/Authorization/Policy/src/AuthorizationMiddleware.cs +++ b/src/Security/Authorization/Policy/src/AuthorizationMiddleware.cs @@ -11,6 +11,9 @@ namespace Microsoft.AspNetCore.Authorization { public class AuthorizationMiddleware { + // AppContext switch used to control whether HttpContext or endpoint is passed as a resource to AuthZ + private const string SuppressUseHttpContextAsAuthorizationResource = "Microsoft.AspNetCore.Authorization.SuppressUseHttpContextAsAuthorizationResource"; + // Property key is used by Endpoint routing to determine if Authorization has run private const string AuthorizationMiddlewareInvokedWithEndpointKey = "__AuthorizationMiddlewareWithEndpointInvoked"; private static readonly object AuthorizationMiddlewareWithEndpointInvokedValue = new object(); @@ -18,7 +21,7 @@ namespace Microsoft.AspNetCore.Authorization private readonly RequestDelegate _next; private readonly IAuthorizationPolicyProvider _policyProvider; - public AuthorizationMiddleware(RequestDelegate next, IAuthorizationPolicyProvider policyProvider) + public AuthorizationMiddleware(RequestDelegate next, IAuthorizationPolicyProvider policyProvider) { _next = next ?? throw new ArgumentNullException(nameof(next)); _policyProvider = policyProvider ?? throw new ArgumentNullException(nameof(policyProvider)); @@ -61,8 +64,17 @@ namespace Microsoft.AspNetCore.Authorization return; } - var authorizeResult = await policyEvaluator.AuthorizeAsync(policy, authenticateResult, context, resource: context); - + object? resource; + if (AppContext.TryGetSwitch(SuppressUseHttpContextAsAuthorizationResource, out var useEndpointAsResource) && useEndpointAsResource) + { + resource = endpoint; + } + else + { + resource = context; + } + + var authorizeResult = await policyEvaluator.AuthorizeAsync(policy, authenticateResult, context, resource); var authorizationMiddlewareResultHandler = context.RequestServices.GetRequiredService(); await authorizationMiddlewareResultHandler.HandleAsync(_next, context, policy, authorizeResult); } diff --git a/src/Security/Authorization/test/AuthorizationMiddlewareTests.cs b/src/Security/Authorization/test/AuthorizationMiddlewareTests.cs index effe426a3b..89de50e3d4 100644 --- a/src/Security/Authorization/test/AuthorizationMiddlewareTests.cs +++ b/src/Security/Authorization/test/AuthorizationMiddlewareTests.cs @@ -9,6 +9,7 @@ using Microsoft.AspNetCore.Authorization.Policy; using Microsoft.AspNetCore.Authorization.Test.TestObjects; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Options; using Moq; using Xunit; @@ -314,7 +315,7 @@ namespace Microsoft.AspNetCore.Authorization.Test } [Fact] - public async Task AuthZResourceShouldBeHttpContextAndHaveHEndpoint() + public async Task AuthZResourceCanBeHttpContextAndHaveEndpoint() { // Arrange HttpContext resource = null; @@ -340,6 +341,33 @@ namespace Microsoft.AspNetCore.Authorization.Test Assert.Equal(endpoint, resource.GetEndpoint()); } + [Fact] + public async Task AuthZResourceShouldBeEndpointByDefaultWithCompatSwitch() + { + AppContext.SetSwitch("Microsoft.AspNetCore.Authorization.SuppressUseHttpContextAsAuthorizationResource", isEnabled: true); + + // Arrange + object resource = null; + var policy = new AuthorizationPolicyBuilder().RequireAssertion(c => + { + resource = c.Resource; + return true; + }).Build(); + var policyProvider = new Mock(); + policyProvider.Setup(p => p.GetDefaultPolicyAsync()).ReturnsAsync(policy); + var next = new TestRequestDelegate(); + + var middleware = CreateMiddleware(next.Invoke, policyProvider.Object); + var endpoint = CreateEndpoint(new AuthorizeAttribute()); + var context = GetHttpContext(endpoint: endpoint); + + // Act + await middleware.Invoke(context); + + // Assert + Assert.Equal(endpoint, resource); + } + [Fact] public async Task Invoke_RequireUnknownRoleShouldForbid() { @@ -410,7 +438,6 @@ namespace Microsoft.AspNetCore.Authorization.Test private AuthorizationMiddleware CreateMiddleware(RequestDelegate requestDelegate = null, IAuthorizationPolicyProvider policyProvider = null) { requestDelegate = requestDelegate ?? ((context) => Task.CompletedTask); - return new AuthorizationMiddleware(requestDelegate, policyProvider); }