CesarSP
CesarSP

Reputation: 21

Require authentication for entire Blazor Server app

I'm trying to add a custom authentication for my Blazor Server app and I can't get it to redirect an unauthorized user to the login page.

I've already tried this:

This is my app.razor component

<CascadingAuthenticationState>
    <Router AppAssembly="@typeof(App).Assembly">
        <Found Context="routeData">
            <AuthorizeRouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)">
                <NotAuthorized>
                    <RedirectToLogin />
                </NotAuthorized>
            </AuthorizeRouteView>
            <FocusOnNavigate RouteData="@routeData" Selector="h1" />
        </Found>
        <NotFound>
            <PageTitle>No encontrado</PageTitle>
            <LayoutView Layout="@typeof(MainLayout)">
                <p role="alert">Dirección inválida.</p>
            </LayoutView>
        </NotFound>
    </Router>
</CascadingAuthenticationState>

This is my RedirectToLogin component

@inject NavigationManager NavManager

@code {
    protected override async Task OnInitializedAsync()
    {
        NavManager.NavigateTo("/login", forceLoad: true);
    }
}

But it seems the <NotAuthorized> section is never reached as I set a breakpoint on the OnInitializedAsync method and the debugging never stopped.

I'm using cookies for authentication and it works as I added an <AuthorizeView> tag in my MainLayout to test it showing a text for not authenticated users.

Upvotes: 0

Views: 1702

Answers (2)

CesarSP
CesarSP

Reputation: 21

I could get it to work, I was missing an [Authorize] attribute.

I put @attribute [Authorize] right after my @using directives at my _Imports.razor file and the <NotAuthorized> tag under the Router was finally reached, and I just simply removed the RedirectToLogin component to render the Login one directly.

Also, as I used [Authorize] at that level, I had to add @attribute [AllowAnonymous] on my login component

Therefore, leaving my Router like this:

<CascadingAuthenticationState>
    <Router AppAssembly="@typeof(App).Assembly">
        <Found Context="routeData">
            <AuthorizeRouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)">
                <NotAuthorized>
                    <Login />
                </NotAuthorized>
            </AuthorizeRouteView>
            <FocusOnNavigate RouteData="@routeData" Selector="h1" />
        </Found>
        <NotFound>
            <PageTitle>No encontrado</PageTitle>
            <LayoutView Layout="@typeof(MainLayout)">
                <p role="alert">Dirección inválida.</p>
            </LayoutView>
        </NotFound>
    </Router>
</CascadingAuthenticationState>

And my MainLayout like this:

<AuthorizeView>
    <Authorized>
        @*Normal layout when authorized*@
        @Body
    </Authorized>
    <NotAuthorized>
        @Body
    </NotAuthorized>
</AuthorizeView>

The Login component is just a form with username and password fields

Upvotes: 1

Nb777
Nb777

Reputation: 2032

Combines the behaviors of AuthorizeView and RouteView, so that it displays the page matching the specified route but only if the user is authorized to see it.
This from Microsoft doc

You can try:
1- Keep you AuthorizeRouteView sample like this:
<AuthorizeRouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)"/>
2- Wrap your RedirectToLogin component with:

<AuthorizeView>
  <NotAuthorized>
     //something
  </NotAuthorized>
  <Authorized>
    //something
  </Authorized>
</AuthorizeView>

Upvotes: 0

Related Questions