'Blazor @attribute [Authorize] tag is not working
I have a working .NET Core 3.0 MVC website, using AzureAD for authentication, this all works fine. I have started to migrate some of the front-end pages to Blazor (in same project) but cannot get authentication to work.
I have added the @attribute [Authorize] tag to the top of Index.razor but I do not get redirected to Azure to login as I would do when adding it to a standard ASP.NET MVC Controller.
Startup.ConfigureServices
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
})
.AddCookie()
.AddOpenIdConnect(options =>
{
Configuration.GetSection("OpenIdConnect").Bind(options);
});
services.AddAuthorizationCore(options =>
{
options.AddPolicy(Policies.AccessRole, Policies.IsAccessPolicy());
options.AddPolicy(Policies.AdminRole, Policies.IsAdminPolicy());
});
Startup.Configure
app.UseAuthentication();
app.UseAuthorization();
Index.razor
@page "/"
@attribute [Authorize(Policy = Policies.AccessRole)]
Policies
public static class Policies
{
public const string AccessRole = "Access";
public const string AdminRole = "Admin";
public static AuthorizationPolicy IsAccessPolicy()
{
return new AuthorizationPolicyBuilder().RequireAuthenticatedUser()
.RequireRole(AccessRole)
.Build();
}
public static AuthorizationPolicy IsAdminPolicy()
{
return new AuthorizationPolicyBuilder().RequireAuthenticatedUser()
.RequireRole(AdminRole)
.Build();
}
}
If I navigate to an MVC page I get authenticated by AzureAD, if I then return to the Blazor page I can use the following successfuly
<AuthorizeView Policy="@Policies.AccessRole">
<p>Is in Access policy.</p>
</AuthorizeView>
<AuthorizeView Policy="@Policies.AdminRole">
<p>Is in Admin policy.</p>
</AuthorizeView>
So to summarise, my Blazor page is not automatically issuing the auth challenge when using the [Authorize] attribute.
Does anyone know what I am doing wrong?
Update
It's as designed https://github.com/aspnet/AspNetCore/issues/13709
As a workaround I have added a component to redirect to a login page
App.razor
<Router AppAssembly="@typeof(Program).Assembly">
<Found Context="routeData">
<AuthorizeRouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)">
<NotAuthorized>
<AuthChallenge></AuthChallenge>
</NotAuthorized>
</AuthorizeRouteView>
</Found>
<NotFound>
<CascadingAuthenticationState>
<LayoutView Layout="@typeof(MainLayout)">
<p>Sorry, there's nothing at this address.</p>
</LayoutView>
</CascadingAuthenticationState>
</NotFound>
</Router>
AuthCallenge.razor
@inject NavigationManager Navigation
@code {
protected override void OnInitialized()
{
Navigation.NavigateTo("/Account/SignIn", true);
}
}
Solution 1:[1]
Take a look at your App.razor file. Do you use RouteView or AuthorizeRouteView?
You need to define an AuthorizeRouteView as described on the "ASP.NET Core Blazor authentication and authorization" page.
<Router AppAssembly="@typeof(Program).Assembly">
<Found Context="routeData">
<AuthorizeRouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)">
<NotAuthorized>
<h1>Sorry</h1>
<p>You're not authorized to reach this page.</p>
<p>You may need to log in as a different user.</p>
</NotAuthorized>
<Authorizing>
<h1>Authentication in progress</h1>
<p>Only visible while authentication is in progress.</p>
</Authorizing>
</AuthorizeRouteView>
</Found>
<NotFound>
<CascadingAuthenticationState>
<LayoutView Layout="@typeof(MainLayout)">
<h1>Sorry</h1>
<p>Sorry, there's nothing at this address.</p>
</LayoutView>
</CascadingAuthenticationState>
</NotFound>
Seems like the AuthorizeAttribute doesn't do all that much if that component is missing.
Solution 2:[2]
You must use CascadingAuthenticationState as root in the XML
<CascadingAuthenticationState>
<Router AppAssembly="@typeof(Program).Assembly">
<Found Context="routeData">
<AuthorizeRouteView RouteData="@routeData" DefaultLayout="@typeof(EmptyLayout)">
<NotAuthorized>
<RedirectLogin />
</NotAuthorized>
</AuthorizeRouteView>
</Found>
<NotFound>
<LayoutView Layout="@typeof(MainLayout)">
<h1>404 Error</h1>
<p>Sorry, there's nothing at this address.</p>
</LayoutView>
</NotFound>
</Router>
</CascadingAuthenticationState>
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Rames |
Solution 2 | Ornolis Vázquez Thompson |