Skip to content

Commit f4f5b16

Browse files
Ensure schemes aren't used on components authorization. Fixes #10570 (#12239)
1 parent 96f55fc commit f4f5b16

File tree

2 files changed

+41
-0
lines changed

2 files changed

+41
-0
lines changed

src/Components/Components/src/Auth/AuthorizeViewCore.cs

+17
Original file line numberDiff line numberDiff line change
@@ -102,10 +102,27 @@ protected override async Task OnParametersSetAsync()
102102
private async Task<bool> IsAuthorizedAsync(ClaimsPrincipal user)
103103
{
104104
var authorizeData = GetAuthorizeData();
105+
EnsureNoAuthenticationSchemeSpecified(authorizeData);
106+
105107
var policy = await AuthorizationPolicy.CombineAsync(
106108
AuthorizationPolicyProvider, authorizeData);
107109
var result = await AuthorizationService.AuthorizeAsync(user, Resource, policy);
108110
return result.Succeeded;
109111
}
112+
113+
private static void EnsureNoAuthenticationSchemeSpecified(IAuthorizeData[] authorizeData)
114+
{
115+
// It's not meaningful to specify a nonempty scheme, since by the time Components
116+
// authorization runs, we already have a specific ClaimsPrincipal (we're stateful).
117+
// To avoid any confusion, ensure the developer isn't trying to specify a scheme.
118+
for (var i = 0; i < authorizeData.Length; i++)
119+
{
120+
var entry = authorizeData[i];
121+
if (!string.IsNullOrEmpty(entry.AuthenticationSchemes))
122+
{
123+
throw new NotSupportedException($"The authorization data specifies an authentication scheme with value '{entry.AuthenticationSchemes}'. Authentication schemes cannot be specified for components.");
124+
}
125+
}
126+
}
110127
}
111128
}

src/Components/Components/test/Auth/AuthorizeViewTest.cs

+24
Original file line numberDiff line numberDiff line change
@@ -427,6 +427,24 @@ public void IncludesResourceInAuthorizeCall()
427427
});
428428
}
429429

430+
[Fact]
431+
public void RejectsNonemptyScheme()
432+
{
433+
// Arrange
434+
var authorizationService = new TestAuthorizationService();
435+
var renderer = CreateTestRenderer(authorizationService);
436+
var rootComponent = new TestAuthStateProviderComponent(builder =>
437+
{
438+
builder.OpenComponent<AuthorizeViewCoreWithScheme>(0);
439+
builder.CloseComponent();
440+
});
441+
renderer.AssignRootComponentId(rootComponent);
442+
443+
// Act/Assert
444+
var ex = Assert.Throws<NotSupportedException>(rootComponent.TriggerRender);
445+
Assert.Equal("The authorization data specifies an authentication scheme with value 'test scheme'. Authentication schemes cannot be specified for components.", ex.Message);
446+
}
447+
430448
private static TestAuthStateProviderComponent WrapInAuthorizeView(
431449
RenderFragment<AuthenticationState> childContent = null,
432450
RenderFragment<AuthenticationState> authorizedContent = null,
@@ -557,5 +575,11 @@ public class TestPolicyRequirement : IAuthorizationRequirement
557575
{
558576
public string PolicyName { get; set; }
559577
}
578+
579+
public class AuthorizeViewCoreWithScheme : AuthorizeViewCore
580+
{
581+
protected override IAuthorizeData[] GetAuthorizeData()
582+
=> new[] { new AuthorizeAttribute { AuthenticationSchemes = "test scheme" } };
583+
}
560584
}
561585
}

0 commit comments

Comments
 (0)