I'm learning Blazor, and I am trying to make authorization in my app. I use LiteDB, so I don't use the Entity Framework. After submitting the login form, I checked that AuthorisationState isAuthorized = true, but my and don't recognize that state was changed and still redirect via .
That is my code:
App.razor
<CascadingAuthenticationState>
<Router AppAssembly="@typeof(App).Assembly">
<Found Context="routeData">
<AuthorizeRouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)">
<NotAuthorized>
<ExternalWebWorklist.Pages.RedirectToLogin />
</NotAuthorized>
<Authorizing>
<p>Proszę czekać, trwa uwierzytelnianie...</p>
</Authorizing>
</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>
RedirectToLogin.razor
@using ExternalWebWorklist.Data
@inject NavigationManager Navigation
@inject UserAuthenticationStateProvider AuthenticationStateProvider
@code {
[CascadingParameter]
private Task<AuthenticationState> AuthenticationStateTask { get; set; }
protected override async Task OnInitializedAsync()
{
var authenticationState = await AuthenticationStateProvider.GetAuthenticationStateAsync();
if (authenticationState?.User?.Identity is null || !authenticationState.User.Identity.IsAuthenticated)
{
var returnUrl = Navigation.ToBaseRelativePath(Navigation.Uri);
if (string.IsNullOrWhiteSpace(returnUrl))
Navigation.NavigateTo("/login", true);
else
Navigation.NavigateTo($"/login?returnUrl={returnUrl}", true);
}
}
}
Program.cs
using ExternalWebWorklist;
using ExternalWebWorklist.Data;
using ExternalWebWorklist.Shared;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Authorization;
using Microsoft.AspNetCore.Components.Web;
using Microsoft.AspNetCore.Identity;
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddRazorPages();
builder.Services.AddServerSideBlazor();
builder.Services.AddAuthorizationCore();
builder.Services.AddSingleton<PatientWorklistService>();
builder.Services.AddSingleton<UserAuthenticationStateProvider>();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
}
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.MapControllers();
app.MapBlazorHub();
app.MapFallbackToPage("/_Host");
#if DEBUG
app.Run();
#elif RELEASE
string ip = ExternalWebWorklist.Database.IpServerAddress.Get(ConnectionString.Get());
app.Run($"http://{ip}:5000");
#endif
LoginForm.razor
@page "/login"
@using System.Security.Claims
@using ExternalWebWorklist.Data
@* @page "/login?returnUrl={returnUrl}" *@
@inject NavigationManager Navigation
@inject UserAuthenticationStateProvider AuthenticationStateProvider
<h3>Login</h3>
<AuthorizeView>
<NotAuthorized>
<p>Proszę zalogować się.</p>
<button class="btn btn-primary" @onclick="Login">Zaloguj się</button>
</NotAuthorized>
<Authorized>
<p>Jesteś już zalogowany. Przekierowywanie...</p>
@{ NavigateToUrl(); }
</Authorized>
</AuthorizeView>
@code {
[CascadingParameter]
private Task<AuthenticationState> AuthenticationStateTask { get; set; }
private AuthenticationState? _authenticationState;
protected override async Task OnInitializedAsync()
{
_authenticationState = AuthenticationStateProvider.GetAuthenticationStateAsync().GetAwaiter().GetResult();
}
protected async void NavigateToUrl()
{
_authenticationState = await AuthenticationStateTask;
if (_authenticationState?.User?.Identity is null || !_authenticationState.User.Identity.IsAuthenticated)
{
var returnUrl = Navigation.ToBaseRelativePath(Navigation.Uri);
if (returnUrl == null || returnUrl == string.Empty)
Navigation.NavigateTo("/", true);
else
Navigation.NavigateTo($"/{returnUrl}", true);
}
}
protected async void Login()
{
var identity = new ClaimsIdentity(new[]
{
new Claim(ClaimTypes.Name, "exampleUser"),
}, "custom");
var user = new ClaimsPrincipal(identity);
((UserAuthenticationStateProvider)AuthenticationStateProvider).SetAuthenticatedUser("JohnDoe");
_authenticationState = await AuthenticationStateProvider.GetAuthenticationStateAsync();
this.StateHasChanged();
var isAuthenticated = _authenticationState.User.Identity.IsAuthenticated;
if (isAuthenticated)
{
Navigation.NavigateTo("/", true);
}
else
{
Console.WriteLine("Błąd logowania");
}
}
}
UserAuthenticationStateProvider.cs
using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Components.Authorization;
namespace ExternalWebWorklist.Data
{
public class UserAuthenticationStateProvider : AuthenticationStateProvider
{
private ClaimsPrincipal _user;
public override Task<AuthenticationState> GetAuthenticationStateAsync()
{
var identity = _user?.Identity ?? new ClaimsIdentity();
var authenticationState = new AuthenticationState(new ClaimsPrincipal(identity));
return Task.FromResult(authenticationState);
}
public void SetAuthenticatedUser(string userName)
{
var identity = new ClaimsIdentity(new[] { new Claim(ClaimTypes.Name, userName) }, "custom");
_user = new ClaimsPrincipal(identity);
NotifyAuthenticationStateChanged(GetAuthenticationStateAsync());
}
public void SetAnonymous()
{
_user = null;
NotifyAuthenticationStateChanged(GetAuthenticationStateAsync());
}
public bool IsAuthenticated()
{
return _user != null && _user.Identity.IsAuthenticated;
}
public string GetAuthenticatedUserName()
{
return IsAuthenticated() ? _user.Identity.Name : string.Empty;
}
}
}