Open kjkrum opened 3 weeks ago
I think this is known. This SO answer describes similar behavior:
The way `AuthorizeAttribute works ... will block the page from rendering, so this should prevent Blazor from starting altogether - you will get redirected away to authenticate.
So maybe not a bug per se, but an area that could be improved. What if there were an attribute similar Authorize
, but only recognized by Blazor?
Thanks for contacting us.
Calling MapRazorComponents<App>().AllowAnonymous()
might also work if you have the <AuthorizeRouteView>
set up correctly. Take a look at https://github.com/dotnet/aspnetcore/issues/53732#issuecomment-2021878231 for more details.
@mkArtakMSFT Thanks for the link. That's a convenient way of avoiding some of the redundancy. But for full consistency, you still need to ensure that HandleChallengeAsync
displays or redirects to the same content as AuthorizeRouteView.NotAuthorized
.
If it weren't for the edge case of [Authorize]
on the first page, some apps might not need an AuthenticationHandler
at all. AuthorizeView
works fine without one, as does AuthorizeAttribute
anywhere but the first page.
That's a convenient way of avoiding some of the redundancy. But for full consistency, you still need to ensure that
HandleChallengeAsync
displays or redirects to the same content asAuthorizeRouteView.NotAuthorized
.
It would be nice to get rid of this redundancy. Since the AuthenticationHandler
is more generic and works for non-Blazor endpoints, that should probably be the source of truth for how to handle unauthorized requests. It might be a good idea to introduce a new default behavior where <AuthorizeRouteView>
does a hard refresh whenever there is no explicit <NotAuthorized>
content in order to let the authorization middleware observe the request to the [Authorize]
endpoint and issue a challenge via the AuthenticationHandler
. We'd have to be careful to not get stuck in an infinite refresh loop in the event the authorization middleware doesn't issue a challenge, but it seems doable.
If it weren't for the edge case of
[Authorize]
on the first page, some apps might not need anAuthenticationHandler
at all.AuthorizeView
works fine without one, as doesAuthorizeAttribute
anywhere but the first page.
That's what the MapRazorComponents<App>().AddInteractiveServerRenderMode().AllowAnonymous()
suggestion was supposed to fix. Does that not work for you?
If you add that, you shouldn't need an AuthenticationHandler
at all unless you have non-Blazor endpoints. That tells the authorization middleware to treat all Blazor endpoints as if they don't require an authenticated user, so it never needs an IAuthenticationService
.
Blazor's <AuthorizeRouteView>
will still check if the user is authenticated when rendering a page with the [Authorize]
attribute, and it will render the <NotAuthorized>
content on the first page load just like it does during interactive navigation if you configure MapRazorComponents<App>()
with AllowAnonymous()
.
@halter73 Aha! I followed that link and saw the AuthenticationHandler
wrapping AuthenticationStateProvider
but overlooked the significance of the other suggestion. That does neatly solve the problem.
I'm not sure why the authentication middleware is involved in the first place since I'm not calling AddAuthentication
/UseAuthentication
, but that's probably a rabbit hole for another day.
Is there an existing issue for this?
Describe the bug
To learn how auth works in Blazor, I'm writing a minimal implementation from scratch. In the process, I've encountered a strange error.
If the first page loaded in a circuit does not have
[Authorize]
, everything works perfectly. You can freely navigate to a page that does have[Authorize]
, and the page is displayed as expected. That is, you get either the page content or a "not authorized" message depending on whether the user is authenticated.However, if the first page loaded in a circuit does have
[Authorize]
, then the app crashes with an error about not being able to find anIAuthenticationService
.This only affects
AuthorizeAttribute
. There is no error if the first page loaded in the circuit contains an<AuthorizeView>
.Expected Behavior
AuthorizeAttribute
should have the same effect on the first page loaded in a circuit as it does on subsequent pages.Steps To Reproduce
This repo contains the Blazor Web App template and my changes in separate commits for easy review. The README contains instructions for an easy way to see the problem.
https://github.com/kjkrum/BlazorAuthWtf
Exceptions (if any)
.NET Version
8.0
Anything else?
No response