Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I pass returnUrl to Login page in Blazor Server application?

I have a simple Blazor server application, with Identity using Individual Authentication. I created the app from the VS 2019 standard dotnet new template.

In some parts of the app I would like to direct the user to the login page, while passing along a returnUrl parameter. I've tried the following variations of code to pass this parameter (counter is the page I want to return to):

NavigationManager.NavigateTo("Identity/Account/Login?returnUrl=counter", forceLoad: true);
NavigationManager.NavigateTo("Identity/Account/Login?returnUrl='/counter'", forceLoad: true);
NavigationManager.NavigateTo("Identity/Account/Login?returnUrl='./counter'", forceLoad: true);
NavigationManager.NavigateTo("Identity/Account/Login?returnUrl='~/counter'", forceLoad: true);

However, with all of these, I get an error message that the "URI is not local". Error message is:

"InvalidOperationException: The supplied URL is not local. A URL with an absolute path is considered local if it does not have a host/authority part. URLs using virtual paths ('~/') are also local."

Can anyone suggest the proper formatting of the returnUrl parameter in this situation? For further background, I am following suggestions from @iambacon (thanks to Colin!), in his blog post about redirecting to the login page for Blazor apps. It's a great article and accomplishes part of what I want: redirect to login when the user is not authenticated. I would just like to add the extra feature of returning back to that URL after the auth is complete.

like image 466
Randy Gamage Avatar asked Jan 14 '20 05:01

Randy Gamage


People also ask

How do I add authentication to Blazor?

There is an option available to enable authentication for the Blazor app when you create the application. To enable authentication for Blazor server app, click on “Change” under “Authentication section and select “Individual User Accounts” option and then click on “Ok” button when you create a new Blazor server app.


1 Answers

"URI is not local".

To solve this...

Do the following:

  1. Create in the Pages folder a component named RedirectToLogin with the following code:

RedirectToLogin.razor

@inject NavigationManager NavigationManager

@code{
  [Parameter]
  public string ReturnUrl {get; set;}
  protected override  void OnInitialized()
  {
        ReturnUrl = "~/" + ReturnUrl;
        NavigationManager.NavigateTo($"Identity/Account/Login?returnUrl={ReturnUrl}", 
           forceLoad:true);
  }
}

Open App.razor and add the following code to AuthorizeRouteView.NotAuthorized

<NotAuthorized>
@{
    var returnUrl = 
    NavigationManager.ToBaseRelativePath(NavigationManager.Uri);
    <RedirectToLogin ReturnUrl="@returnUrl"/>
    
 }
</NotAuthorized>

Also inject the NavigationManager at the top of the App component like this:

@inject NavigationManager NavigationManager

To test this, at the top of the Fetchdata (or Counter if you like) component page add the @attribute directive for the Authorize attribute, like this: @attribute [Authorize] When an unauthenticated user tries to access the Fetchdata page, the AuthorizeRouteView.NotAuthorized delegate property is executed, and the RedirectToLogin component is rendered with its parameter attribute set to the current url.

Update

The following addition is to add a login and logout buttons to your App...

  1. Create a component named LoginDisplay.razor in the Shared folder, and add the following code into it:
     <AuthorizeView>
      <Authorized>
        <a href="Identity/Account/Manage">Hello, 
        @context.User.Identity.Name!</a>
        <form method="post" action="Identity/Account/LogOut">
            <button type="submit" class="nav-link btn btn-link">Log 
        out</button>
        </form>
      </Authorized>
         <NotAuthorized>
            <a href="Identity/Account/Register">Register</a>
            <a href="Identity/Account/Login">Log in</a>
         </NotAuthorized>
      </AuthorizeView>

In the MainLayout component add the LoginDisplay element as follows:

<div class="top-row px-4 auth">
    <LoginDisplay />
    <a href="https://docs.microsoft.com/aspnet/" 
         target="_blank">About</a>
</div>

Run your app and test the login and logout button...

like image 112
enet Avatar answered Oct 02 '22 05:10

enet