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.
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.
"URI is not local".
To solve this...
Do the following:
@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...
<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...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With