Blazor Server AuthorizeView rendering NotAuthorized before AuthorizationHandler finishes executing
See original GitHub issueI’m trying to implement a custom AuthorizationHandler that uses business rules to determine whether or not a user has access to a certain page.
To do that I implemented the following:
CustomMemberHandler.cs
public sealed class CustomMemberHandler: AuthorizationHandler<CustomRequirement, long?>
{
public override async Task HandleAsync(AuthorizationHandlerContext context)
{
if (context.Resource == null || context.Resource is long)
{
foreach (var requirement in context.Requirements.OfType<CustomRequirement>())
{
await this.HandleRequirementAsync(context, requirement, (long?)context.Resource);
}
}
}
protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context, CustomRequirement requirement, long? resourceId)
{
var userId = context.User.GetUserId();
if (userId.HasValue && resourceId.HasValue && await <Database Invocation>)
{
context.Succeed(requirement);
}
else if (logId.HasValue == false)
{
context.Succeed(requirement);
}
else
{
context.Fail();
}
}
}
Startup.cs
services.AddAuthorization(options =>
{
options.AddPolicy(PolicyConstants.CUSTOM_POLICY, policy =>
{
policy.RequireAuthenticatedUser();
policy.Requirements.Add(new CustomRequirement());
policy.Build();
});
});
services.AddTransient<IAuthorizationHandler, CustomMemberHandler>();
And in my component I’m using the following:
BlazorPage.razor
@inherits OwningComponentBase
<AuthorizeView Policy="@PolicyConstants.CUSTOM_POLICY" Resource="@this.Id">
<Authorized>
<PageLayout/>
</Authorized>
<NotAuthorized>
<HandleNotAuthorized/>
</NotAuthorized>
</AuthorizeView>
The HandleNotAuthorized component redirects the user to the AccessDenied page.
I also have an AuthorizeRouteView that’s used in the App.razor file.
<CascadingAuthenticationState>
<Router AppAssembly="@typeof(Program).Assembly">
<Found Context="routeData">
<AuthorizeRouteView RouteData="@routeData">
<NotAuthorized>
<HandleNotAuthorized />
</NotAuthorized>
</AuthorizeRouteView>
</Found>
<NotFound>
<HandleNotFound />
</NotFound>
</Router>
</CascadingAuthenticationState>
What is happening is that the NotAuthorized fragment is being rendered even though the AuthorizationHandler hasn’t executed yet (or at least hasn’t finished executing). This causes the user to be redirected to the AccessDenied page even though the AuthorizationHandler executes succesfully.
Is this behaviour normal?
Further technical details
- ASP.NET Core 3.1.4
- Microsoft Visual Studio Community 2019 Version 16.6.2
.NET Core SDK (reflecting any global.json):
Version: 3.1.301
Commit: 7feb845744
Runtime Environment:
OS Name: Windows
OS Version: 10.0.18363
OS Platform: Windows
RID: win10-x64
Base Path: C:\Program Files\dotnet\sdk\3.1.301\
Host (useful for support):
Version: 3.1.5
Commit: 65cd789777
.NET Core SDKs installed:
3.0.103 [C:\Program Files\dotnet\sdk]
3.1.102 [C:\Program Files\dotnet\sdk]
3.1.300 [C:\Program Files\dotnet\sdk]
3.1.301 [C:\Program Files\dotnet\sdk]
.NET Core runtimes installed:
Microsoft.AspNetCore.All 2.1.19 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
Microsoft.AspNetCore.App 2.1.19 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 3.0.3 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 3.1.2 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 3.1.5 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.NETCore.App 2.1.19 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 3.0.3 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 3.1.2 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 3.1.5 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.WindowsDesktop.App 3.0.3 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 3.1.2 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 3.1.5 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Issue Analytics
- State:
- Created 3 years ago
- Reactions:3
- Comments:7 (5 by maintainers)
Top Results From Across the Web
c# - Why does Server Side Blazor's <AuthorizeView> not ...
I have created a Blazor server project using Windows Authentication ... after the app re-renders and displays the "NotAuthorized" content.
Read more >ASP.NET Core Blazor authentication and authorization
Client-side markup and methods associated with an AuthorizeView are only protected from view and execution in the rendered UI in Blazor ...
Read more >Configuring Policy-based Authorization with Blazor
In this post, I describe policy-based authorization and it's advantages over the more legacy role-based authorization.
Read more >Different ways of Authorization in Blazor + Redirect To Login ...
The first basic version of authorization in Blazor is using AuthorizeView for a simple user signed in check. AuthrozieView works base on the ......
Read more >Custom Authentication in Blazor WebAssembly - Step-By- ...
Let's a mode for our User. Since this Model will inherit from IdentityUser, we will be adding it to the Server Project. But...
Read more >
Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free
Top Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
This issue is quite painful. Please consider fixing this!
My custom AuthorizationHandler makes API calls and <NotAuthorized> is shown on the AuthorizeView instead of <Authorizing> while the handler is still processing. This is certainly a bug.
Had a similar issue to this. I ended up putting up a hack, as we’d briefly have “Not Authorized” flash up before the authorized content showed (in some scenarios), so I just put in a base wait period for my unauthorized view, like so:
It doesn’t solve the underlying problem but it does the trick for us, for now.