Best approach for hiding Blazor WebAssembly app behind login wall

493 Views Asked by At

I need to build an ASP.NET Core hosted Blazor Webassembly app (.NET 6) where all of the app functionality is hidden behind a login wall but I'm not sure how best to achieve this. For authentication/authorisation I'm using ASP.NET Identity and IdentityServer.

So far I've created a new Razor component called Login.razor which simply contains a link that triggers the built in authentication process:

<a href="authentication/login">Log in</a>

This component has the @page directive "/" so it's the first 'page' the user lands on when they go to the app.

This works fine, but once the user has then successfully logged in they are redirected to the return URL as part of the .NET Identity process, which in this case is a now useless login page.

I don't want to just replace the return URL in the Identity pages and redirect the user to another specific page because I think the return URL will be really useful in situations where the user has been sent a link to a specific page. For example, if I try and navigate to a protected resource like mywebsite.com/fetchdata without logging in first, it triggers whatever authentication magic Blazor comes shipped with, gets the user to log in and then redirects them to /fetchdata once they've successfully done so. I want to keep that functionality.

What do I need to do to get the server to redirect to another page (e.g. "/index") if the user has come from the Login.razor component? Or am I just approaching all of this in completely the wrong way? Any advice much appreciated.

1

There are 1 best solutions below

0
On

Create a new component called RedirectToLogin and add this code:

@inject NavigationManager Navigation

@code {
    protected override void OnInitialized()
    {
        Navigation.NavigateTo($"authentication/login?returnUrl={Uri.EscapeDataString(Navigation.Uri)}");
    }
}

Then change your App.razor to be like this:

<CascadingAuthenticationState>
    <Router AppAssembly="@typeof(App).Assembly">
        <Found Context="routeData">
            <AuthorizeRouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)">
                <NotAuthorized>
                    @if (context.User.Identity?.IsAuthenticated != true)
                    {
                        <RedirectToLogin />
                    }
                    else
                    {
                        <p role="alert">You are not authorized to access this resource.</p>
                    }
                </NotAuthorized>
            </AuthorizeRouteView>
            <FocusOnNavigate RouteData="@routeData" Selector="h1" />
        </Found>
        <NotFound>
            <PageTitle>Not found</PageTitle>
            <LayoutView Layout="@typeof(MainLayout)">
                <p role="alert">Sorry, there's nothing at this address.</p>
            </LayoutView>
        </NotFound>
    </Router>
</CascadingAuthenticationState>

Now when an unauthenticated user tries to access a protected page he will be automatically redirected to authentication/login?returnUrl=....

Documentation