Blazor Server-side without EF authorisation problem (AuthView)

39 Views Asked by At

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;
        }
    }
}
0

There are 0 best solutions below