Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Resolve Log authorization detail failure message by override ToString in each Requirement #10822

Closed
wants to merge 9 commits into from
Closed
Original file line number Diff line number Diff line change
Expand Up @@ -177,29 +177,34 @@ public AssertionRequirement(System.Func<Microsoft.AspNetCore.Authorization.Autho
public System.Func<Microsoft.AspNetCore.Authorization.AuthorizationHandlerContext, System.Threading.Tasks.Task<bool>> 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.Infrastructure.ClaimsAuthorizationRequirement>, Microsoft.AspNetCore.Authorization.IAuthorizationRequirement
{
public ClaimsAuthorizationRequirement(string claimType, System.Collections.Generic.IEnumerable<string> allowedValues) { }
public System.Collections.Generic.IEnumerable<string> 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.Infrastructure.DenyAnonymousAuthorizationRequirement>, 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.Infrastructure.NameAuthorizationRequirement>, 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
{
Expand All @@ -212,6 +217,7 @@ public partial class RolesAuthorizationRequirement : Microsoft.AspNetCore.Author
public RolesAuthorizationRequirement(System.Collections.Generic.IEnumerable<string> allowedRoles) { }
public System.Collections.Generic.IEnumerable<string> 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
Expand Down
5 changes: 5 additions & 0 deletions src/Security/Authorization/Core/src/AssertionRequirement.cs
Original file line number Diff line number Diff line change
Expand Up @@ -56,5 +56,10 @@ public async Task HandleAsync(AuthorizationHandlerContext context)
context.Succeed(this);
}
}

public override string ToString()
{
return $"{nameof(AssertionRequirement)}:{nameof(Handler)} return {bool.TrueString}";
wu-yafeng marked this conversation as resolved.
Show resolved Hide resolved
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -69,5 +70,14 @@ protected override Task HandleRequirementAsync(AuthorizationHandlerContext conte
}
return Task.CompletedTask;
}

public override string ToString()
{
var value = (AllowedValues == null || !AllowedValues.Any())
? string.Empty
: $" AND Claim.Value in ({string.Join("|", AllowedValues)})";
wu-yafeng marked this conversation as resolved.
Show resolved Hide resolved

return $"{nameof(ClaimsAuthorizationRequirement)}:Claim.Type={ClaimType}{value}";
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ public async Task<AuthorizationResult> AuthorizeAsync(ClaimsPrincipal user, obje
}
else
{
_logger.UserAuthorizationFailed();
_logger.UserAuthorizationFailed(result.Failure);
}
return result;
}
Expand Down Expand Up @@ -132,4 +132,4 @@ public async Task<AuthorizationResult> AuthorizeAsync(ClaimsPrincipal user, obje
return await this.AuthorizeAsync(user, resource, policy);
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,5 +29,10 @@ protected override Task HandleRequirementAsync(AuthorizationHandlerContext conte
}
return Task.CompletedTask;
}

public override string ToString()
{
return $"{nameof(DenyAnonymousAuthorizationRequirement)}:User authenticationted";
wu-yafeng marked this conversation as resolved.
Show resolved Hide resolved
}
}
}
17 changes: 12 additions & 5 deletions src/Security/Authorization/Core/src/LoggingExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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<ILogger, Exception> _userAuthorizationFailed;
private static Action<ILogger, string, Exception> _userAuthorizationFailed;
private static Action<ILogger, Exception> _userAuthorizationSucceeded;

static LoggingExtensions()
Expand All @@ -16,16 +17,22 @@ static LoggingExtensions()
eventId: new EventId(1, "UserAuthorizationSucceeded"),
logLevel: LogLevel.Information,
formatString: "Authorization was successful.");
_userAuthorizationFailed = LoggerMessage.Define(
_userAuthorizationFailed = LoggerMessage.Define<string>(
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
? "Explicit called fail"
wu-yafeng marked this conversation as resolved.
Show resolved Hide resolved
: "Following requirement not met " + Environment.NewLine + string.Join(Environment.NewLine, failure.FailedRequirements);
wu-yafeng marked this conversation as resolved.
Show resolved Hide resolved

_userAuthorizationFailed(logger, reason, null);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -48,5 +48,10 @@ protected override Task HandleRequirementAsync(AuthorizationHandlerContext conte
}
return Task.CompletedTask;
}

public override string ToString()
{
return $"{nameof(NameAuthorizationRequirement)}:User has `Name` equals {RequiredName}";
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,10 @@ public class OperationAuthorizationRequirement : IAuthorizationRequirement
/// The name of this instance of <see cref="IAuthorizationRequirement"/>.
/// </summary>
public string Name { get; set; }

public override string ToString()
{
return $"{nameof(OperationAuthorizationRequirement)}:Name={Name}";
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -64,5 +64,11 @@ protected override Task HandleRequirementAsync(AuthorizationHandlerContext conte
return Task.CompletedTask;
}

public override string ToString()
{
var roles = $"Roles in ({string.Join("|", AllowedRoles)})";

return $"{nameof(RolesAuthorizationRequirement)}:{roles}";
}
}
}
32 changes: 32 additions & 0 deletions src/Security/Authorization/test/AssertionRequirementsTests.cs
Original file line number Diff line number Diff line change
@@ -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("AssertionRequirement:Handler return True", formattedValue);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
// 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 in (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<string>());

// Act
var formattedValue = requirement.ToString();

// Assert
Assert.Equal("ClaimsAuthorizationRequirement:Claim.Type=Custom", formattedValue);
}
}
}
Loading