Add compat switch to opt out of breaking change in AuthZ (#23324)
This commit is contained in:
parent
197f156fcd
commit
1c27ba1bbd
|
|
@ -11,6 +11,9 @@ namespace Microsoft.AspNetCore.Authorization
|
||||||
{
|
{
|
||||||
public class AuthorizationMiddleware
|
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
|
// Property key is used by Endpoint routing to determine if Authorization has run
|
||||||
private const string AuthorizationMiddlewareInvokedWithEndpointKey = "__AuthorizationMiddlewareWithEndpointInvoked";
|
private const string AuthorizationMiddlewareInvokedWithEndpointKey = "__AuthorizationMiddlewareWithEndpointInvoked";
|
||||||
private static readonly object AuthorizationMiddlewareWithEndpointInvokedValue = new object();
|
private static readonly object AuthorizationMiddlewareWithEndpointInvokedValue = new object();
|
||||||
|
|
@ -18,7 +21,7 @@ namespace Microsoft.AspNetCore.Authorization
|
||||||
private readonly RequestDelegate _next;
|
private readonly RequestDelegate _next;
|
||||||
private readonly IAuthorizationPolicyProvider _policyProvider;
|
private readonly IAuthorizationPolicyProvider _policyProvider;
|
||||||
|
|
||||||
public AuthorizationMiddleware(RequestDelegate next, IAuthorizationPolicyProvider policyProvider)
|
public AuthorizationMiddleware(RequestDelegate next, IAuthorizationPolicyProvider policyProvider)
|
||||||
{
|
{
|
||||||
_next = next ?? throw new ArgumentNullException(nameof(next));
|
_next = next ?? throw new ArgumentNullException(nameof(next));
|
||||||
_policyProvider = policyProvider ?? throw new ArgumentNullException(nameof(policyProvider));
|
_policyProvider = policyProvider ?? throw new ArgumentNullException(nameof(policyProvider));
|
||||||
|
|
@ -61,8 +64,17 @@ namespace Microsoft.AspNetCore.Authorization
|
||||||
return;
|
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<IAuthorizationMiddlewareResultHandler>();
|
var authorizationMiddlewareResultHandler = context.RequestServices.GetRequiredService<IAuthorizationMiddlewareResultHandler>();
|
||||||
await authorizationMiddlewareResultHandler.HandleAsync(_next, context, policy, authorizeResult);
|
await authorizationMiddlewareResultHandler.HandleAsync(_next, context, policy, authorizeResult);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ using Microsoft.AspNetCore.Authorization.Policy;
|
||||||
using Microsoft.AspNetCore.Authorization.Test.TestObjects;
|
using Microsoft.AspNetCore.Authorization.Test.TestObjects;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Microsoft.Extensions.Options;
|
||||||
using Moq;
|
using Moq;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
|
|
@ -314,7 +315,7 @@ namespace Microsoft.AspNetCore.Authorization.Test
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task AuthZResourceShouldBeHttpContextAndHaveHEndpoint()
|
public async Task AuthZResourceCanBeHttpContextAndHaveEndpoint()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
HttpContext resource = null;
|
HttpContext resource = null;
|
||||||
|
|
@ -340,6 +341,33 @@ namespace Microsoft.AspNetCore.Authorization.Test
|
||||||
Assert.Equal(endpoint, resource.GetEndpoint());
|
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<IAuthorizationPolicyProvider>();
|
||||||
|
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]
|
[Fact]
|
||||||
public async Task Invoke_RequireUnknownRoleShouldForbid()
|
public async Task Invoke_RequireUnknownRoleShouldForbid()
|
||||||
{
|
{
|
||||||
|
|
@ -410,7 +438,6 @@ namespace Microsoft.AspNetCore.Authorization.Test
|
||||||
private AuthorizationMiddleware CreateMiddleware(RequestDelegate requestDelegate = null, IAuthorizationPolicyProvider policyProvider = null)
|
private AuthorizationMiddleware CreateMiddleware(RequestDelegate requestDelegate = null, IAuthorizationPolicyProvider policyProvider = null)
|
||||||
{
|
{
|
||||||
requestDelegate = requestDelegate ?? ((context) => Task.CompletedTask);
|
requestDelegate = requestDelegate ?? ((context) => Task.CompletedTask);
|
||||||
|
|
||||||
return new AuthorizationMiddleware(requestDelegate, policyProvider);
|
return new AuthorizationMiddleware(requestDelegate, policyProvider);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue