Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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);
    }
}
like image 878
Dave Avatar asked Oct 11 '19 08:10

Dave


People also ask

How to fix Blazor authorize attribute not working?

Blazor authorize attribute not working 1 For the authorization to work as expected, along with the [Authorize] attribute we must also use AuthorizeRouteView... 2 In App.razor file, use AuthorizeRouteView component instead of RouteView component. More ...

What is authorizeview component in Blazor?

Blazor authorize attribute In our previous video we discussed AuthorizeView component. This component is used to authorize the display of specific parts within a page, including child components. We use

When do Blazor server apps know the authentication state?

Blazor Server apps know the authentication state as soon as the state is established. Authorizing content can be provided in a Blazor Server app's AuthorizeView component, but the content is never displayed. Only use [Authorize] on @page components reached via the Blazor Router.

When should I use [authorize] in Blazor router?

Only use [Authorize] on @page components reached via the Blazor Router. Authorization is only performed as an aspect of routing and not for child components rendered within a page. To authorize the display of specific parts within a page, use AuthorizeView instead. The [Authorize] attribute also supports role-based or policy-based authorization.


1 Answers

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.

like image 155
Rames Avatar answered Sep 28 '22 08:09

Rames