Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AuthorizeRouteView Authorizing and NotAuthorized parameters settings

I wanted to use the NotAuthorized attribute in the <AuthorizeRouteView> tag to redirect to the login page every time a non logged-in user try to access a page.

Howewer, it requires a RenderFragment<AuthentificationState> typed parameter. What shoud I put to set this parameter to render the login page ?

Edit : Code is pretty simple. I used the Blazor server side project template with identity stored in application, just added the RedirectToLogin.razor like this :

@inject NavigationManager NavigationManager
@code { 
    protected override void OnAfterRender()
    {
        NavigationManager.NavigateTo("counter"); //for an unknown reason, the "Identity/Account/Login" redirect doesn't work.
    }
}

And modified the App.razor :

<CascadingAuthenticationState>
    <Router AppAssembly="@typeof(Program).Assembly">
        <Found Context="routeData">
            <AuthorizeRouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)">
                <NotAuthorized>
                    @if(true) { } //Used for breakpoint.
                    <RedirectToLogin />
                </NotAuthorized>
                <Authorizing>
                    @if(true) { } //Used for breakpoint.
                </Authorizing>
            </AuthorizeRouteView>
        </Found>
        <NotFound>
            <LayoutView Layout="@typeof(MainLayout)">
                <p>Sorry, there's nothing at this address.</p>
            </LayoutView>
        </NotFound>
    </Router>
</CascadingAuthenticationState>

I didn't touch the Startup.cs so it look like this :

public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddDbContext<ApplicationDbContext>(options =>
                options.UseSqlServer(
                    Configuration.GetConnectionString("DefaultConnection")));
            services.AddDefaultIdentity<IdentityUser>()
                .AddEntityFrameworkStores<ApplicationDbContext>();
            services.AddRazorPages();
            services.AddServerSideBlazor();
            services.AddScoped<AuthenticationStateProvider, RevalidatingIdentityAuthenticationStateProvider<IdentityUser>>();
            services.AddSingleton<WeatherForecastService>();
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
                app.UseDatabaseErrorPage();
            }
            else
            {
                app.UseExceptionHandler("/Error");
                // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
                app.UseHsts();
            }

            app.UseHttpsRedirection();
            app.UseStaticFiles();

            app.UseRouting();

            app.UseAuthentication();
            app.UseAuthorization();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();
                endpoints.MapBlazorHub();
                endpoints.MapFallbackToPage("/_Host");
            });
        }
    }
like image 741
PepperTiger Avatar asked Nov 22 '19 13:11

PepperTiger


People also ask

How do I use authorizerouteview in Blazor?

What you can do in Blazor is use the information associated with the user through the authentication process to authorize what a user is (or isn't) allowed to do. ... You do that by, back in the App.cs file, replacing the RouteView component inside the Router's Found element with an AuthorizeRouteView component.

What is notauthorized and authorizing elements?

A NotAuthorized element that allows you to control what part of the UI is delivered to the user when they're not authorized An Authorizing element that displays a message if the user's information isn't available yet

What is the authorizerouteview component?

Unlike the RouteView component, the AuthorizeRouteView looks at who's allowed to use a component and won't let users access components they're not authorized for. Here's the markup inside an App.cs file that does that:

How to initialize a new instance of an authorizerouteview?

Initialize a new instance of a AuthorizeRouteView. The content that will be displayed while asynchronous authorization is in progress. Gets or sets the type of a layout to be used if the page does not declare any layout. If specified, the type must implement IComponent and accept a parameter named Body.


2 Answers

I struggled with a similar issue where my <NotAuthorized> part in app.razor was not being displayed for a user that was not authorized. After 3 days of pulling my hair out, I also was going for the solution in the MainLayout.razor as mentioned in other answers. One last attempt with a clean project, made my aware of how poor a programmer I am because I finally found the answer.

I did not read the documentation entirely, in which I could find the cause of the problem. On the following page: https://docs.microsoft.com/en-us/aspnet/core/blazor/security/?view=aspnetcore-5.0#customize-unauthorized-content-with-the-router-component you find how the NotAuthorized part is invoked. I totally missed the second bullet point:

The Router component, in conjunction with the AuthorizeRouteView component, allows the app to specify custom content if:

  • Content isn't found.
  • The user fails an [Authorize] condition applied to the component. The [Authorize] attribute is covered in the [Authorize] attribute section.
  • Asynchronous authentication is in progress.

This means the <NotAuthorized> part is only invoked/displayed when the route endpoint has a Authorize tag. In my case the route was going to my index page, without an Authorize tag....

like image 138
MartinH Avatar answered Sep 28 '22 00:09

MartinH


Thanks to MartinH, I did not spend 3 days pulling my hair out.

For anyone else requiring clarification on the 'Authorize attrtibute', here's an example...

VerifyAuth.razor

@page "/verifyauth"
@attribute [Authorize]    @*<--RIGHT HERE!!!*@

<div class="container">

    <h3 class="text-center">Verify Auth</h3>

</div>

@code {

}

App.razor

<Router AppAssembly="@typeof(Program).Assembly" PreferExactMatches="@true">
    <Found Context="routeData">
        <AuthorizeRouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" >
            <Authorizing>
                <text>Please wait, we are authorizing you...</text>
            </Authorizing>
            <NotAuthorized>
                @if (context.User.Identity.IsAuthenticated == false)
                {
                    <RedirectToLogin />
                }
                else
                {
                    <p>You are not authorized to access this resource.</p>
                }
            </NotAuthorized>
        </AuthorizeRouteView>
    </Found>
    <NotFound>
        <CascadingAuthenticationState>
            <LayoutView Layout="@typeof(MainLayout)">
                <p>Sorry, there is nothing at this address.</p>
            </LayoutView>
        </CascadingAuthenticationState>
    </NotFound>
</Router>

RedirectToLogin.razor

@inject NavigationManager NavManager

@code {
    protected override void OnInitialized()
    {
        NavManager.NavigateTo("/login");
    }
}

Reference: https://docs.microsoft.com/en-us/aspnet/core/blazor/security/?view=aspnetcore-5.0#customize-unauthorized-content-with-the-router-component

like image 25
Brian Avatar answered Sep 27 '22 23:09

Brian