From f6936175374cba6d6ca373473dd7a09d5ec40fae Mon Sep 17 00:00:00 2001 From: Steve Sanderson Date: Tue, 16 Jul 2019 15:19:19 +0100 Subject: [PATCH 1/2] Ensure schemes aren't used on components authorization. Fixes #10570 --- .../Components/src/Auth/AuthorizeViewCore.cs | 17 +++++++++++++ .../Components/test/Auth/AuthorizeViewTest.cs | 24 +++++++++++++++++++ 2 files changed, 41 insertions(+) diff --git a/src/Components/Components/src/Auth/AuthorizeViewCore.cs b/src/Components/Components/src/Auth/AuthorizeViewCore.cs index 07e2cd1c487c..f11de40447f7 100644 --- a/src/Components/Components/src/Auth/AuthorizeViewCore.cs +++ b/src/Components/Components/src/Auth/AuthorizeViewCore.cs @@ -102,10 +102,27 @@ protected override async Task OnParametersSetAsync() private async Task IsAuthorizedAsync(ClaimsPrincipal user) { var authorizeData = GetAuthorizeData(); + EnsureNoAuthorizationSchemeSpecified(authorizeData); + var policy = await AuthorizationPolicy.CombineAsync( AuthorizationPolicyProvider, authorizeData); var result = await AuthorizationService.AuthorizeAsync(user, Resource, policy); return result.Succeeded; } + + private static void EnsureNoAuthorizationSchemeSpecified(IAuthorizeData[] authorizeData) + { + // It's not meaningful to specify a nonempty scheme, since by the time Components + // authorization runs, we already have a specific ClaimsPrincipal (we're stateful). + // To avoid any confusion, ensure the developer isn't trying to specify a scheme. + for (var i = 0; i < authorizeData.Length; i++) + { + var entry = authorizeData[i]; + if (!string.IsNullOrEmpty(entry.AuthenticationSchemes)) + { + throw new NotSupportedException($"The authorization data specifies an authentication scheme with value '{entry.AuthenticationSchemes}'. Authentication schemes cannot be specified for components."); + } + } + } } } diff --git a/src/Components/Components/test/Auth/AuthorizeViewTest.cs b/src/Components/Components/test/Auth/AuthorizeViewTest.cs index 36a83cd93555..83cbbd417f78 100644 --- a/src/Components/Components/test/Auth/AuthorizeViewTest.cs +++ b/src/Components/Components/test/Auth/AuthorizeViewTest.cs @@ -427,6 +427,24 @@ public void IncludesResourceInAuthorizeCall() }); } + [Fact] + public void RejectsNonemptyScheme() + { + // Arrange + var authorizationService = new TestAuthorizationService(); + var renderer = CreateTestRenderer(authorizationService); + var rootComponent = new TestAuthStateProviderComponent(builder => + { + builder.OpenComponent(0); + builder.CloseComponent(); + }); + renderer.AssignRootComponentId(rootComponent); + + // Act/Assert + var ex = Assert.Throws(rootComponent.TriggerRender); + Assert.Equal("The authorization data specifies an authentication scheme with value 'test scheme'. Authentication schemes cannot be specified for components.", ex.Message); + } + private static TestAuthStateProviderComponent WrapInAuthorizeView( RenderFragment childContent = null, RenderFragment authorizedContent = null, @@ -557,5 +575,11 @@ public class TestPolicyRequirement : IAuthorizationRequirement { public string PolicyName { get; set; } } + + public class AuthorizeViewCoreWithScheme : AuthorizeViewCore + { + protected override IAuthorizeData[] GetAuthorizeData() + => new[] { new AuthorizeAttribute { AuthenticationSchemes = "test scheme" } }; + } } } From d3eece512b22c4bf37ee4899877aa68a1ba7e121 Mon Sep 17 00:00:00 2001 From: Steve Sanderson Date: Tue, 16 Jul 2019 15:21:22 +0100 Subject: [PATCH 2/2] Rename method --- src/Components/Components/src/Auth/AuthorizeViewCore.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Components/Components/src/Auth/AuthorizeViewCore.cs b/src/Components/Components/src/Auth/AuthorizeViewCore.cs index f11de40447f7..4b1f2f581fe2 100644 --- a/src/Components/Components/src/Auth/AuthorizeViewCore.cs +++ b/src/Components/Components/src/Auth/AuthorizeViewCore.cs @@ -102,7 +102,7 @@ protected override async Task OnParametersSetAsync() private async Task IsAuthorizedAsync(ClaimsPrincipal user) { var authorizeData = GetAuthorizeData(); - EnsureNoAuthorizationSchemeSpecified(authorizeData); + EnsureNoAuthenticationSchemeSpecified(authorizeData); var policy = await AuthorizationPolicy.CombineAsync( AuthorizationPolicyProvider, authorizeData); @@ -110,7 +110,7 @@ private async Task IsAuthorizedAsync(ClaimsPrincipal user) return result.Succeeded; } - private static void EnsureNoAuthorizationSchemeSpecified(IAuthorizeData[] authorizeData) + private static void EnsureNoAuthenticationSchemeSpecified(IAuthorizeData[] authorizeData) { // It's not meaningful to specify a nonempty scheme, since by the time Components // authorization runs, we already have a specific ClaimsPrincipal (we're stateful).