From c376e833e46497fbec4bd7b39632f8c8e13360b2 Mon Sep 17 00:00:00 2001 From: Hao Kung Date: Fri, 25 Oct 2019 14:28:13 -0700 Subject: [PATCH] Merge AuthZ ToString PR (#15350) Rebased verison of https://github.com/aspnet/AspNetCore/pull/10822 --- ...oft.AspNetCore.Authorization.netcoreapp.cs | 6 + ...AspNetCore.Authorization.netstandard2.0.cs | 6 + .../Core/src/AssertionRequirement.cs | 5 + .../src/ClaimsAuthorizationRequirement.cs | 10 ++ .../Core/src/DefaultAuthorizationService.cs | 4 +- .../DenyAnonymousAuthorizationRequirement.cs | 5 + .../Core/src/LoggingExtensions.cs | 17 ++- .../Core/src/NameAuthorizationRequirement.cs | 5 + .../src/OperationAuthorizationRequirement.cs | 5 + .../Core/src/RolesAuthorizationRequirement.cs | 6 + .../test/AssertionRequirementsTests.cs | 32 ++++++ .../ClaimsAuthorizationRequirementTests.cs | 58 ++++++++++ .../test/DefaultAuthorizationServiceTests.cs | 107 +++++++++++++++++- ...yAnonymousAuthorizationRequirementTests.cs | 32 ++++++ .../test/NameAuthorizationRequirementTests.cs | 32 ++++++ .../OperationAuthorizationRequirementTests.cs | 35 ++++++ .../RolesAuthorizationRequirementTests.cs | 45 ++++++++ 17 files changed, 400 insertions(+), 10 deletions(-) create mode 100644 src/Security/Authorization/test/AssertionRequirementsTests.cs create mode 100644 src/Security/Authorization/test/ClaimsAuthorizationRequirementTests.cs create mode 100644 src/Security/Authorization/test/DenyAnonymousAuthorizationRequirementTests.cs create mode 100644 src/Security/Authorization/test/NameAuthorizationRequirementTests.cs create mode 100644 src/Security/Authorization/test/OperationAuthorizationRequirementTests.cs create mode 100644 src/Security/Authorization/test/RolesAuthorizationRequirementTests.cs diff --git a/src/Security/Authorization/Core/ref/Microsoft.AspNetCore.Authorization.netcoreapp.cs b/src/Security/Authorization/Core/ref/Microsoft.AspNetCore.Authorization.netcoreapp.cs index ab30a7c6d5..52785b8c3c 100644 --- a/src/Security/Authorization/Core/ref/Microsoft.AspNetCore.Authorization.netcoreapp.cs +++ b/src/Security/Authorization/Core/ref/Microsoft.AspNetCore.Authorization.netcoreapp.cs @@ -177,6 +177,7 @@ namespace Microsoft.AspNetCore.Authorization.Infrastructure public System.Func> Handler { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } } [System.Diagnostics.DebuggerStepThroughAttribute] public System.Threading.Tasks.Task HandleAsync(Microsoft.AspNetCore.Authorization.AuthorizationHandlerContext context) { throw null; } + public override string ToString() { throw null; } } public partial class ClaimsAuthorizationRequirement : Microsoft.AspNetCore.Authorization.AuthorizationHandler, Microsoft.AspNetCore.Authorization.IAuthorizationRequirement { @@ -184,22 +185,26 @@ namespace Microsoft.AspNetCore.Authorization.Infrastructure public System.Collections.Generic.IEnumerable AllowedValues { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } } public string ClaimType { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } } protected override System.Threading.Tasks.Task HandleRequirementAsync(Microsoft.AspNetCore.Authorization.AuthorizationHandlerContext context, Microsoft.AspNetCore.Authorization.Infrastructure.ClaimsAuthorizationRequirement requirement) { throw null; } + public override string ToString() { throw null; } } public partial class DenyAnonymousAuthorizationRequirement : Microsoft.AspNetCore.Authorization.AuthorizationHandler, Microsoft.AspNetCore.Authorization.IAuthorizationRequirement { public DenyAnonymousAuthorizationRequirement() { } protected override System.Threading.Tasks.Task HandleRequirementAsync(Microsoft.AspNetCore.Authorization.AuthorizationHandlerContext context, Microsoft.AspNetCore.Authorization.Infrastructure.DenyAnonymousAuthorizationRequirement requirement) { throw null; } + public override string ToString() { throw null; } } public partial class NameAuthorizationRequirement : Microsoft.AspNetCore.Authorization.AuthorizationHandler, Microsoft.AspNetCore.Authorization.IAuthorizationRequirement { public NameAuthorizationRequirement(string requiredName) { } public string RequiredName { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } } protected override System.Threading.Tasks.Task HandleRequirementAsync(Microsoft.AspNetCore.Authorization.AuthorizationHandlerContext context, Microsoft.AspNetCore.Authorization.Infrastructure.NameAuthorizationRequirement requirement) { throw null; } + public override string ToString() { throw null; } } public partial class OperationAuthorizationRequirement : Microsoft.AspNetCore.Authorization.IAuthorizationRequirement { public OperationAuthorizationRequirement() { } public string Name { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } + public override string ToString() { throw null; } } public partial class PassThroughAuthorizationHandler : Microsoft.AspNetCore.Authorization.IAuthorizationHandler { @@ -212,6 +217,7 @@ namespace Microsoft.AspNetCore.Authorization.Infrastructure public RolesAuthorizationRequirement(System.Collections.Generic.IEnumerable allowedRoles) { } public System.Collections.Generic.IEnumerable AllowedRoles { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } } protected override System.Threading.Tasks.Task HandleRequirementAsync(Microsoft.AspNetCore.Authorization.AuthorizationHandlerContext context, Microsoft.AspNetCore.Authorization.Infrastructure.RolesAuthorizationRequirement requirement) { throw null; } + public override string ToString() { throw null; } } } namespace Microsoft.Extensions.DependencyInjection diff --git a/src/Security/Authorization/Core/ref/Microsoft.AspNetCore.Authorization.netstandard2.0.cs b/src/Security/Authorization/Core/ref/Microsoft.AspNetCore.Authorization.netstandard2.0.cs index ab30a7c6d5..52785b8c3c 100644 --- a/src/Security/Authorization/Core/ref/Microsoft.AspNetCore.Authorization.netstandard2.0.cs +++ b/src/Security/Authorization/Core/ref/Microsoft.AspNetCore.Authorization.netstandard2.0.cs @@ -177,6 +177,7 @@ namespace Microsoft.AspNetCore.Authorization.Infrastructure public System.Func> Handler { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } } [System.Diagnostics.DebuggerStepThroughAttribute] public System.Threading.Tasks.Task HandleAsync(Microsoft.AspNetCore.Authorization.AuthorizationHandlerContext context) { throw null; } + public override string ToString() { throw null; } } public partial class ClaimsAuthorizationRequirement : Microsoft.AspNetCore.Authorization.AuthorizationHandler, Microsoft.AspNetCore.Authorization.IAuthorizationRequirement { @@ -184,22 +185,26 @@ namespace Microsoft.AspNetCore.Authorization.Infrastructure public System.Collections.Generic.IEnumerable AllowedValues { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } } public string ClaimType { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } } protected override System.Threading.Tasks.Task HandleRequirementAsync(Microsoft.AspNetCore.Authorization.AuthorizationHandlerContext context, Microsoft.AspNetCore.Authorization.Infrastructure.ClaimsAuthorizationRequirement requirement) { throw null; } + public override string ToString() { throw null; } } public partial class DenyAnonymousAuthorizationRequirement : Microsoft.AspNetCore.Authorization.AuthorizationHandler, Microsoft.AspNetCore.Authorization.IAuthorizationRequirement { public DenyAnonymousAuthorizationRequirement() { } protected override System.Threading.Tasks.Task HandleRequirementAsync(Microsoft.AspNetCore.Authorization.AuthorizationHandlerContext context, Microsoft.AspNetCore.Authorization.Infrastructure.DenyAnonymousAuthorizationRequirement requirement) { throw null; } + public override string ToString() { throw null; } } public partial class NameAuthorizationRequirement : Microsoft.AspNetCore.Authorization.AuthorizationHandler, Microsoft.AspNetCore.Authorization.IAuthorizationRequirement { public NameAuthorizationRequirement(string requiredName) { } public string RequiredName { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } } protected override System.Threading.Tasks.Task HandleRequirementAsync(Microsoft.AspNetCore.Authorization.AuthorizationHandlerContext context, Microsoft.AspNetCore.Authorization.Infrastructure.NameAuthorizationRequirement requirement) { throw null; } + public override string ToString() { throw null; } } public partial class OperationAuthorizationRequirement : Microsoft.AspNetCore.Authorization.IAuthorizationRequirement { public OperationAuthorizationRequirement() { } public string Name { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } + public override string ToString() { throw null; } } public partial class PassThroughAuthorizationHandler : Microsoft.AspNetCore.Authorization.IAuthorizationHandler { @@ -212,6 +217,7 @@ namespace Microsoft.AspNetCore.Authorization.Infrastructure public RolesAuthorizationRequirement(System.Collections.Generic.IEnumerable allowedRoles) { } public System.Collections.Generic.IEnumerable AllowedRoles { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } } protected override System.Threading.Tasks.Task HandleRequirementAsync(Microsoft.AspNetCore.Authorization.AuthorizationHandlerContext context, Microsoft.AspNetCore.Authorization.Infrastructure.RolesAuthorizationRequirement requirement) { throw null; } + public override string ToString() { throw null; } } } namespace Microsoft.Extensions.DependencyInjection diff --git a/src/Security/Authorization/Core/src/AssertionRequirement.cs b/src/Security/Authorization/Core/src/AssertionRequirement.cs index 5fa452b733..0c31f57105 100644 --- a/src/Security/Authorization/Core/src/AssertionRequirement.cs +++ b/src/Security/Authorization/Core/src/AssertionRequirement.cs @@ -56,5 +56,10 @@ namespace Microsoft.AspNetCore.Authorization.Infrastructure context.Succeed(this); } } + + public override string ToString() + { + return $"{nameof(Handler)} assertion should evaluate to true."; + } } } diff --git a/src/Security/Authorization/Core/src/ClaimsAuthorizationRequirement.cs b/src/Security/Authorization/Core/src/ClaimsAuthorizationRequirement.cs index 93b1deea6d..f77b74fd74 100644 --- a/src/Security/Authorization/Core/src/ClaimsAuthorizationRequirement.cs +++ b/src/Security/Authorization/Core/src/ClaimsAuthorizationRequirement.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Security.Claims; using System.Threading.Tasks; namespace Microsoft.AspNetCore.Authorization.Infrastructure @@ -69,5 +70,14 @@ namespace Microsoft.AspNetCore.Authorization.Infrastructure } return Task.CompletedTask; } + + public override string ToString() + { + var value = (AllowedValues == null || !AllowedValues.Any()) + ? string.Empty + : $" and Claim.Value is one of the following values: ({string.Join("|", AllowedValues)})"; + + return $"{nameof(ClaimsAuthorizationRequirement)}:Claim.Type={ClaimType}{value}"; + } } } diff --git a/src/Security/Authorization/Core/src/DefaultAuthorizationService.cs b/src/Security/Authorization/Core/src/DefaultAuthorizationService.cs index bc5d571c47..475dea3330 100644 --- a/src/Security/Authorization/Core/src/DefaultAuthorizationService.cs +++ b/src/Security/Authorization/Core/src/DefaultAuthorizationService.cs @@ -102,7 +102,7 @@ namespace Microsoft.AspNetCore.Authorization } else { - _logger.UserAuthorizationFailed(); + _logger.UserAuthorizationFailed(result.Failure); } return result; } @@ -132,4 +132,4 @@ namespace Microsoft.AspNetCore.Authorization return await this.AuthorizeAsync(user, resource, policy); } } -} \ No newline at end of file +} diff --git a/src/Security/Authorization/Core/src/DenyAnonymousAuthorizationRequirement.cs b/src/Security/Authorization/Core/src/DenyAnonymousAuthorizationRequirement.cs index e88cce7aac..35828735a5 100644 --- a/src/Security/Authorization/Core/src/DenyAnonymousAuthorizationRequirement.cs +++ b/src/Security/Authorization/Core/src/DenyAnonymousAuthorizationRequirement.cs @@ -29,5 +29,10 @@ namespace Microsoft.AspNetCore.Authorization.Infrastructure } return Task.CompletedTask; } + + public override string ToString() + { + return $"{nameof(DenyAnonymousAuthorizationRequirement)}:Requires an authenticated user."; + } } } diff --git a/src/Security/Authorization/Core/src/LoggingExtensions.cs b/src/Security/Authorization/Core/src/LoggingExtensions.cs index e31d88161d..ef57f8c09f 100644 --- a/src/Security/Authorization/Core/src/LoggingExtensions.cs +++ b/src/Security/Authorization/Core/src/LoggingExtensions.cs @@ -2,12 +2,13 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using Microsoft.AspNetCore.Authorization; namespace Microsoft.Extensions.Logging { internal static class LoggingExtensions { - private static Action _userAuthorizationFailed; + private static Action _userAuthorizationFailed; private static Action _userAuthorizationSucceeded; static LoggingExtensions() @@ -16,16 +17,22 @@ namespace Microsoft.Extensions.Logging eventId: new EventId(1, "UserAuthorizationSucceeded"), logLevel: LogLevel.Information, formatString: "Authorization was successful."); - _userAuthorizationFailed = LoggerMessage.Define( + _userAuthorizationFailed = LoggerMessage.Define( eventId: new EventId(2, "UserAuthorizationFailed"), logLevel: LogLevel.Information, - formatString: "Authorization failed."); + formatString: "Authorization failed for {0}"); } public static void UserAuthorizationSucceeded(this ILogger logger) => _userAuthorizationSucceeded(logger, null); - public static void UserAuthorizationFailed(this ILogger logger) - => _userAuthorizationFailed(logger, null); + public static void UserAuthorizationFailed(this ILogger logger, AuthorizationFailure failure) + { + var reason = failure.FailCalled + ? "Fail() was explicitly called." + : "These requirements were not met:" + Environment.NewLine + string.Join(Environment.NewLine, failure.FailedRequirements); + + _userAuthorizationFailed(logger, reason, null); + } } } diff --git a/src/Security/Authorization/Core/src/NameAuthorizationRequirement.cs b/src/Security/Authorization/Core/src/NameAuthorizationRequirement.cs index 02ab946fad..36cee10aac 100644 --- a/src/Security/Authorization/Core/src/NameAuthorizationRequirement.cs +++ b/src/Security/Authorization/Core/src/NameAuthorizationRequirement.cs @@ -48,5 +48,10 @@ namespace Microsoft.AspNetCore.Authorization.Infrastructure } return Task.CompletedTask; } + + public override string ToString() + { + return $"{nameof(NameAuthorizationRequirement)}:Requires a user identity with Name equal to {RequiredName}"; + } } } diff --git a/src/Security/Authorization/Core/src/OperationAuthorizationRequirement.cs b/src/Security/Authorization/Core/src/OperationAuthorizationRequirement.cs index c3f16356d3..0e2a6fcf3f 100644 --- a/src/Security/Authorization/Core/src/OperationAuthorizationRequirement.cs +++ b/src/Security/Authorization/Core/src/OperationAuthorizationRequirement.cs @@ -13,5 +13,10 @@ namespace Microsoft.AspNetCore.Authorization.Infrastructure /// The name of this instance of . /// public string Name { get; set; } + + public override string ToString() + { + return $"{nameof(OperationAuthorizationRequirement)}:Name={Name}"; + } } } diff --git a/src/Security/Authorization/Core/src/RolesAuthorizationRequirement.cs b/src/Security/Authorization/Core/src/RolesAuthorizationRequirement.cs index 811e17aacd..c3a11cdc47 100644 --- a/src/Security/Authorization/Core/src/RolesAuthorizationRequirement.cs +++ b/src/Security/Authorization/Core/src/RolesAuthorizationRequirement.cs @@ -64,5 +64,11 @@ namespace Microsoft.AspNetCore.Authorization.Infrastructure return Task.CompletedTask; } + public override string ToString() + { + var roles = $"User.IsInRole must be true for one of the following roles: ({string.Join("|", AllowedRoles)})"; + + return $"{nameof(RolesAuthorizationRequirement)}:{roles}"; + } } } diff --git a/src/Security/Authorization/test/AssertionRequirementsTests.cs b/src/Security/Authorization/test/AssertionRequirementsTests.cs new file mode 100644 index 0000000000..d197860329 --- /dev/null +++ b/src/Security/Authorization/test/AssertionRequirementsTests.cs @@ -0,0 +1,32 @@ +// 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.Text; +using Microsoft.AspNetCore.Authorization.Infrastructure; +using Xunit; + +namespace Microsoft.AspNetCore.Authorization.Test +{ + public class AssertionRequirementsTests + { + private AssertionRequirement CreateRequirement() + { + return new AssertionRequirement(context => true); + } + + [Fact] + public void ToString_ShouldReturnFormatValue() + { + // Arrange + var requirement = new AssertionRequirement(context => true); + + // Act + var formattedValue = requirement.ToString(); + + // Assert + Assert.Equal("Handler assertion should evaluate to true.", formattedValue); + } + } +} diff --git a/src/Security/Authorization/test/ClaimsAuthorizationRequirementTests.cs b/src/Security/Authorization/test/ClaimsAuthorizationRequirementTests.cs new file mode 100644 index 0000000000..d1bbe69a64 --- /dev/null +++ b/src/Security/Authorization/test/ClaimsAuthorizationRequirementTests.cs @@ -0,0 +1,58 @@ +// 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.Text; +using Microsoft.AspNetCore.Authorization.Infrastructure; +using Xunit; + +namespace Microsoft.AspNetCore.Authorization.Test +{ + public class ClaimsAuthorizationRequirementTests + { + public ClaimsAuthorizationRequirement CreateRequirement(string claimType, params string[] allowedValues) + { + return new ClaimsAuthorizationRequirement(claimType, allowedValues); + } + + [Fact] + public void ToString_ShouldReturnAndDescriptionWhenAllowedValuesNotNull() + { + // Arrange + var requirement = CreateRequirement("Custom", "CustomValue1", "CustomValue2"); + + // Act + var formattedValue = requirement.ToString(); + + // Assert + Assert.Equal("ClaimsAuthorizationRequirement:Claim.Type=Custom and Claim.Value is one of the following values: (CustomValue1|CustomValue2)", formattedValue); + } + + [Fact] + public void ToString_ShouldReturnWithoutAllowedDescriptionWhenAllowedValuesIsNull() + { + // Arrange + var requirement = CreateRequirement("Custom", (string[])null); + + // Act + var formattedValue = requirement.ToString(); + + // Assert + Assert.Equal("ClaimsAuthorizationRequirement:Claim.Type=Custom", formattedValue); + } + + [Fact] + public void ToString_ShouldReturnWithoutAllowedDescriptionWhenAllowedValuesIsEmpty() + { + // Arrange + var requirement = CreateRequirement("Custom", Array.Empty()); + + // Act + var formattedValue = requirement.ToString(); + + // Assert + Assert.Equal("ClaimsAuthorizationRequirement:Claim.Type=Custom", formattedValue); + } + } +} diff --git a/src/Security/Authorization/test/DefaultAuthorizationServiceTests.cs b/src/Security/Authorization/test/DefaultAuthorizationServiceTests.cs index d0fe9a62e9..ecd55a4acc 100644 --- a/src/Security/Authorization/test/DefaultAuthorizationServiceTests.cs +++ b/src/Security/Authorization/test/DefaultAuthorizationServiceTests.cs @@ -8,6 +8,7 @@ using System.Security.Claims; using System.Threading.Tasks; using Microsoft.AspNetCore.Authorization.Infrastructure; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using Xunit; @@ -64,7 +65,8 @@ namespace Microsoft.AspNetCore.Authorization.Test { services.AddAuthorization(options => { - options.AddPolicy("Basic", policy => { + options.AddPolicy("Basic", policy => + { policy.AddAuthenticationSchemes("Basic"); policy.RequireClaim("Permission", "CanViewPage"); }); @@ -710,7 +712,8 @@ namespace Microsoft.AspNetCore.Authorization.Test protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, PassThroughRequirement requirement) { - if (Succeed) { + if (Succeed) + { context.Succeed(requirement); } return Task.FromResult(0); @@ -926,7 +929,6 @@ namespace Microsoft.AspNetCore.Authorization.Test Assert.True((await authorizationService.AuthorizeAsync(user, 2, Operations.Edit)).Succeeded); } - [Fact] public async Task DoesNotCallHandlerWithWrongResourceType() { @@ -1174,5 +1176,104 @@ namespace Microsoft.AspNetCore.Authorization.Test Assert.False((await authorizationService.AuthorizeAsync(null, "Success")).Succeeded); } + public class LogRequirement : IAuthorizationRequirement + { + public override string ToString() + { + return "LogRequirement"; + } + } + + public class DefaultAuthorizationServiceTestLogger : ILogger + { + private Action> _assertion; + + public DefaultAuthorizationServiceTestLogger(Action> assertion) + { + _assertion = assertion; + } + + public IDisposable BeginScope(TState state) + { + throw new NotImplementedException(); + } + + public bool IsEnabled(LogLevel logLevel) + { + return true; + } + + public void Log(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func formatter) + { + _assertion(logLevel, eventId, state, exception, (s, e) => formatter?.Invoke((TState)s, e)); + } + } + + [Fact] + public async Task Authorize_ShouldLogRequirementDetailWhenUnHandled() + { + // Arrange + + static void Assertion(LogLevel level, EventId eventId, object state, Exception exception, Func formatter) + { + Assert.Equal(LogLevel.Information, level); + Assert.Equal(2, eventId.Id); + Assert.Equal("UserAuthorizationFailed", eventId.Name); + var message = formatter(state, exception); + + Assert.Equal("Authorization failed for These requirements were not met:" + Environment.NewLine + "LogRequirement" + Environment.NewLine + "LogRequirement", message); + } + + var authorizationService = BuildAuthorizationService(services => + { + services.AddSingleton>(new DefaultAuthorizationServiceTestLogger(Assertion)); + services.AddAuthorization(options => options.AddPolicy("Log", p => + { + p.Requirements.Add(new LogRequirement()); + p.Requirements.Add(new LogRequirement()); + })); + }); + + var user = new ClaimsPrincipal(); + + // Act + var result = await authorizationService.AuthorizeAsync(user, "Log"); + + // Assert + } + + [Fact] + public async Task Authorize_ShouldLogExplicitFailedWhenFailedCall() + { + // Arrange + + static void Assertion(LogLevel level, EventId eventId, object state, Exception exception, Func formatter) + { + Assert.Equal(LogLevel.Information, level); + Assert.Equal(2, eventId.Id); + Assert.Equal("UserAuthorizationFailed", eventId.Name); + var message = formatter(state, exception); + + Assert.Equal("Authorization failed for Fail() was explicitly called.", message); + } + + var authorizationService = BuildAuthorizationService(services => + { + services.AddSingleton(); + services.AddSingleton>(new DefaultAuthorizationServiceTestLogger(Assertion)); + services.AddAuthorization(options => options.AddPolicy("Log", p => + { + p.Requirements.Add(new LogRequirement()); + p.Requirements.Add(new LogRequirement()); + })); + }); + + var user = new ClaimsPrincipal(); + + // Act + var result = await authorizationService.AuthorizeAsync(user, "Log"); + + // Assert + } } } diff --git a/src/Security/Authorization/test/DenyAnonymousAuthorizationRequirementTests.cs b/src/Security/Authorization/test/DenyAnonymousAuthorizationRequirementTests.cs new file mode 100644 index 0000000000..3d35634758 --- /dev/null +++ b/src/Security/Authorization/test/DenyAnonymousAuthorizationRequirementTests.cs @@ -0,0 +1,32 @@ +// 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.Text; +using Microsoft.AspNetCore.Authorization.Infrastructure; +using Xunit; + +namespace Microsoft.AspNetCore.Authorization.Test +{ + public class DenyAnonymousAuthorizationRequirementTests + { + private DenyAnonymousAuthorizationRequirement CreateRequirement() + { + return new DenyAnonymousAuthorizationRequirement(); + } + + [Fact] + public void ToString_ShouldReturnFormatValue() + { + // Arrange + var requirement = CreateRequirement(); + + // Act + var formattedValue = requirement.ToString(); + + // Assert + Assert.Equal("DenyAnonymousAuthorizationRequirement:Requires an authenticated user.", formattedValue); + } + } +} diff --git a/src/Security/Authorization/test/NameAuthorizationRequirementTests.cs b/src/Security/Authorization/test/NameAuthorizationRequirementTests.cs new file mode 100644 index 0000000000..73a9a98144 --- /dev/null +++ b/src/Security/Authorization/test/NameAuthorizationRequirementTests.cs @@ -0,0 +1,32 @@ +// 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.Text; +using Microsoft.AspNetCore.Authorization.Infrastructure; +using Xunit; + +namespace Microsoft.AspNetCore.Authorization.Test +{ + public class NameAuthorizationRequirementTests + { + public NameAuthorizationRequirement CreateRequirement(string requiredName) + { + return new NameAuthorizationRequirement(requiredName); + } + + [Fact] + public void ToString_ShouldReturnFormatValue() + { + // Arrange + var requirement = CreateRequirement("Custom"); + + // Act + var formattedValue = requirement.ToString(); + + // Assert + Assert.Equal("NameAuthorizationRequirement:Requires a user identity with Name equal to Custom", formattedValue); + } + } +} diff --git a/src/Security/Authorization/test/OperationAuthorizationRequirementTests.cs b/src/Security/Authorization/test/OperationAuthorizationRequirementTests.cs new file mode 100644 index 0000000000..623d01c98e --- /dev/null +++ b/src/Security/Authorization/test/OperationAuthorizationRequirementTests.cs @@ -0,0 +1,35 @@ +// 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.Text; +using Microsoft.AspNetCore.Authorization.Infrastructure; +using Xunit; + +namespace Microsoft.AspNetCore.Authorization.Test +{ + public class OperationAuthorizationRequirementTests + { + private OperationAuthorizationRequirement CreateRequirement(string name) + { + return new OperationAuthorizationRequirement() + { + Name = name + }; + } + + [Fact] + public void ToString_ShouldReturnFormatValue() + { + // Arrange + var requirement = CreateRequirement("Custom"); + + // Act + var formattedValue = requirement.ToString(); + + // Assert + Assert.Equal("OperationAuthorizationRequirement:Name=Custom", formattedValue); + } + } +} diff --git a/src/Security/Authorization/test/RolesAuthorizationRequirementTests.cs b/src/Security/Authorization/test/RolesAuthorizationRequirementTests.cs new file mode 100644 index 0000000000..1b8d5b09c7 --- /dev/null +++ b/src/Security/Authorization/test/RolesAuthorizationRequirementTests.cs @@ -0,0 +1,45 @@ +// 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.Text; +using Microsoft.AspNetCore.Authorization.Infrastructure; +using Xunit; + +namespace Microsoft.AspNetCore.Authorization.Test +{ + public class RolesAuthorizationRequirementTests + { + private RolesAuthorizationRequirement CreateRequirement(params string[] allowedRoles) + { + return new RolesAuthorizationRequirement(allowedRoles); + } + + [Fact] + public void ToString_ShouldReturnSplitByBarWhenHasTwoAllowedRoles() + { + // Arrange + var requirement = CreateRequirement("Custom1", "Custom2"); + + // Act + var formattedValue = requirement.ToString(); + + // Assert + Assert.Equal("RolesAuthorizationRequirement:User.IsInRole must be true for one of the following roles: (Custom1|Custom2)", formattedValue); + } + + [Fact] + public void ToString_ShouldReturnUnSplitStringWhenOnlyOneAllowedRoles() + { + // Arrange + var requirement = CreateRequirement("Custom1"); + + // Act + var formattedValue = requirement.ToString(); + + // Assert + Assert.Equal("RolesAuthorizationRequirement:User.IsInRole must be true for one of the following roles: (Custom1)",formattedValue); + } + } +}