Blazor - when open the main page without being authenticated never redirect to login page

Viewed 44

I'm using Blazor with .net 6. In the app.razor page I have the defaults for AutorizedRouteView and NotAuthorized. It's working fine, except for main page. If does not have any authenticated, should redirect to login page, but it's always detecting the NotAuthorized page.

App.razor

<CascadingAuthenticationState>
    <Router AppAssembly="@typeof(Program).Assembly">
        <Found Context="routeData">
            <AuthorizeRouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)">
                <Authorizing>
                    <text> Please wait, we are authorizing the user. </text>
                </Authorizing>
                <NotAuthorized>
                    <div class="text-center">
                        <img src="/assets/img/restrito.png" class="rounded" alt="não encontrado">
                        <br /><br>
                        <h1 class="fw-bolder">Não possui acesso a esta página.</h1>
                    </div>
                </NotAuthorized>
            </AuthorizeRouteView>
        </Found>
        <NotFound>
            @{
                <div class="text-center">
                    <img src="/assets/img/404.png" class="rounded" alt="não encontrado">
                    <br /><br>
                    <h1 class="fw-bolder">Página não encontrada.</h1>

                    <a href="">Retornar à página principal</a>
                </div>
            }
        </NotFound>
    </Router>
</CascadingAuthenticationState>

AppRouteView.cs

public class AppRouteView : RouteView
    {
        [Inject]
        private NavigationManager _navigationManager { get; set; }

        [Inject]
        private IAccountService _accountService { get; set; }

        protected override void Render(RenderTreeBuilder builder)
        {
            // var authorize = Attribute.GetCustomAttribute(RouteData.PageType, typeof(AuthorizeAttribute)) != null;
            if (_accountService.User == null)
            {
                _navigationManager.NavigateTo("account/login");
            }
            else
            {
                base.Render(builder);
            }
        }
    }

Index.razor

@page "/"
@using VidaConfortoApplication.Client.Services.Interfaces
@attribute [Authorize]
@inject IAccountService _accountService

<div class="p-4">
    <div class="container">
        <h1>Olá @_accountService.User?.Name!</h1>
        <p>Está autenticado na aplicação GesSad!</p>
        <p><NavLink href="users">Gerir utilizadores</NavLink></p>
    </div>
</div>

Login.razor page does not have any [Authorize] attriute

1 Answers

You need to handle the redirect to the login page yourself, within the <NotAuthorized> tag. Check whether the user is Authenticated, and if not, redirect them to the login page. Here is an example:

<AuthorizeRouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)">
    <NotAuthorized>
        @if (!context.User.Identity.IsAuthenticated)
        {
            <RedirectToLogin />
        }
        else
        {
            <p>You are not authorized to access this resource.</p>
        }
    </NotAuthorized>
</AuthorizeRouteView>

Note that this also handles the difference between being Authenticated and being Authorized. A user may be logged in to a site (authenticated), without having permissions to access certain resources (authorized).

In your <RedirectToLogin /> component, just redirect the user in OnInitialized() or OnInitializedAsync(). Here is a simple example:

@inject NavigationManager _nav

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

If you want the user to be returned to the page they initially tried to enter, get the target uri before redirecting to login, and pass it as a query parameter to the login page (to handle the redirection after logging in). Then, the <RedirectToLogin /> component could look like this:

@inject NavigationManager _nav

@code {
    protected override void OnInitialized()
    {
        var path = _nav.ToBaseRelativePath(_nav.Uri);
        _nav.NavigateTo($"/account/login?returnUrl={path}");
    }
}
Related