Reputation: 51
I have a blazor wasm application with prerendering and auth via oidc through an IdentityServer4. I pretty much have it all set up and things are looking good. The problem I have is with the oidc package from Microsoft.AspNetCore.Components.WebAssembly.Authentication there seems to be a mandatory "Authorizing" splash screen that I cannot disable. With prerendering on a page that does not need authentication this means that a user will see the data on the page and then after a second or two it will be replaced by a full screen authenticating screen and then the data on the page will come back. The UX on this is so terrible I am thinking I must have something setup wrong and that this cannot be the only way it works but for the life of me I cannot find a solution to this on my own or via google...
App.razor
<CascadingAuthenticationState>
<Router AppAssembly="@typeof(Program).Assembly">
<Found Context="routeData">
<AuthorizeRouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)">
<NotAuthorized>
<p>Not authorized.</p>
</NotAuthorized>
<Authorizing>
<p>Authorizing</p>
</Authorizing>
</AuthorizeRouteView>
</Found>
<NotFound>
<LayoutView Layout="@typeof(MainLayout)">
<p>Sorry, there's nothing at this address.</p>
</LayoutView>
</NotFound>
</Router>
</CascadingAuthenticationState>
The problem here is that I cannot simply remove the Authorizing tag. If I do a default page is shown anyway. I would really like it if I could get it to only show that splash screen if the page had an "@attribute [Authorize]" attribute or at least did not have a "@attribute [AllowAnonymous]".
Have I run up against a limitation of the package?
Thanks for any guidance on this.
Also might be useful but probably not. The service is setup like so.
builder.Services.AddOidcAuthentication<RemoteAuthenticationState, MyRemoteUserAccount>(options =>
{
builder.Configuration.Bind("OidcProviderOptions", options.ProviderOptions);
options.UserOptions.ScopeClaim = JwtClaimTypes.Scope;
options.UserOptions.RoleClaim = JwtClaimTypes.Role;
})
.AddAccountClaimsPrincipalFactory<RemoteAuthenticationState, MyRemoteUserAccount, MyUserFactory>();
Upvotes: 3
Views: 1675
Reputation: 16
I think you'll find the answer you're looking for in another thread here.
I also went searching only to discover just how easy the solution was:
<MudThemeProvider/>
<MudDialogProvider/>
<MudSnackbarProvider/>
<CascadingAuthenticationState>
<Router AppAssembly="@typeof(Program).Assembly" PreferExactMatches="@true">
<Found Context="routeData">
<AuthorizeRouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)">
<Authorizing>
@* YOUR CODE HERE *@
</Authorizing>
<NotAuthorized>
@if (!context.User.Identity.IsAuthenticated)
{
<RedirectToLogin />
}
else
{
<p>You know, I have no idea how you got here but this is not a place I let people into!</p>
}
</NotAuthorized>
</AuthorizeRouteView>
</Found>
<NotFound>
<LayoutView Layout="@typeof(MainLayout)">
<p>Sorry, there's nothing at this address, well, yet anyway!</p>
</LayoutView>
</NotFound>
</Router>
</CascadingAuthenticationState>
Upvotes: -1
Reputation: 51
Ok, I think I have come up with an acceptable solution. It is a little fiddly but gets the job done.
I have abandoned any attempt at displaying auth state at the root level.
My App.razor now looks like this
<CascadingAuthenticationState>
<Router AppAssembly="@typeof(Program).Assembly">
<Found Context="routeData">
<RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" />
</Found>
<NotFound>
<LayoutView Layout="@typeof(MainLayout)">
<p>Sorry, there's nothing at this address.</p>
</LayoutView>
</NotFound>
</Router>
</CascadingAuthenticationState>
Then in the root template of the app I have something like this
@if(AllowAnonymous)
{
@RootBody
}
else
{
<AuthorizeView>
<NotAuthorized>
<p>Not authorized to read page contents.</p>
</NotAuthorized>
<Authorizing>
<p>Authorizing.</p>
</Authorizing>
<Authorized>
@RootBody
</Authorized>
</AuthorizeView>
}
If I need to disable the auth status I pass AllowAnonymous=true to the component. I would like to eventually make this automatic depending on the parent page's authorization attribute but this works for now.
Upvotes: 2