JackJack
JackJack

Reputation: 87

Blazor Server .Net 8 Cookie Authentication without Identity

I was trying to do a custom authentication using Blazor Server in .Net 8 but until now not succeed. I'm new to this Blazor framework and please check my work flow why I keep getting the error. I've read some of the article but things in Blazor are moving so fast and I've tried so many method but still unsuccessful.

My page tree:

My page tree

Program.cs

builder.Services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
    .AddCookie(x =>
    {
        x.LoginPath = "/login";
    });
builder.Services.AddAuthorization();
builder.Services.AddCascadingAuthenticationState();

///////////////////////////

app.UseAuthentication();
app.UseAuthorization();

Login.razor

@using Microsoft.AspNetCore.Authentication
@using Microsoft.AspNetCore.Authentication.Cookies
@using System.Security.Claims

@* some razor component *@

@code{
    [CascadingParameter]
    public HttpContext httpcontext { get; set; } = default!;

    public async Task ClickLogin()
    {
        _loginbtnLoading = true;
        if (!string.IsNullOrEmpty(_ntid) && !string.IsNullOrEmpty(_password))
        {
            await Task.Delay(2000);
            //I'm using LDAP for checking user signin
            var loginOK = ILoginServices.CheckLoginStatus(_ntid, _password);
            if (loginOK.success)
            {

                var claims = new List<Claim>();
                claims.Add(new Claim(ClaimTypes.Name, _ntid)); // add more claims

                var claimsIdentity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme);

                var principal = new ClaimsPrincipal(claimsIdentity);

                // Sign in the user
                await httpcontext.SignInAsync(principal);

                NavManager.NavigateTo("/home");
            }
            else
            {
                Snackbar.Add(loginOK.errorMessage, Severity.Error);
            }
        }
        else
        {
            Snackbar.Add("Please key in all the required info", Severity.Error);
        }
        _loginbtnLoading = false;
    }

}

The error produced was System.InvalidOperationException: Headers are read-only, response has already started.

Upvotes: 2

Views: 5067

Answers (1)

Brando Zhang
Brando Zhang

Reputation: 28192

According to your codes, I created a test demo on my side ,it works well. Since you don't post the related codes to show what's your make up for this blazor. I will post what I am doing on my side.

Please notice: You should make sure the login.razor is static SSR.

More details, you could refer to below codes:

@page "/login"
@using Microsoft.AspNetCore.Authentication
@using Microsoft.AspNetCore.Authentication.Cookies
@using System.Security.Claims
@inject NavigationManager NavManager

<h3>Login</h3>

<EditForm method="post" FormName="ClickLogin" OnSubmit="ClickLogin" Model="UserCredentials">
 
    <InputText @bind-Value="UserCredentials.Username" placeholder="Username"></InputText>
    <InputText @bind-Value="UserCredentials.Password" placeholder="Password" />

    <button type="submit" > SignIn</button>

</EditForm>


@code {
    [CascadingParameter]
    public HttpContext httpcontext { get; set; } = default!;

    [SupplyParameterFromForm]
    public Credential UserCredentials { get; set; } = new Credential();

    public async Task ClickLogin()
    {
        var claims = new List<Claim>();
        claims.Add(new Claim(ClaimTypes.Name, "test")); // add more claims

        var claimsIdentity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme);

        var principal = new ClaimsPrincipal(claimsIdentity);

        // Sign in the user
        await httpcontext.SignInAsync(principal);

        NavManager.NavigateTo("/");

    }
}

Prgram.cs:

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
builder.Services.AddRazorComponents()
    .AddInteractiveServerComponents();
builder.Services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
    .AddCookie(x =>
    {
        x.LoginPath = "/login";
    });
builder.Services.AddAuthorization();
builder.Services.AddCascadingAuthenticationState();
var app = builder.Build();

// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error", createScopeForErrors: true);
    // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
    app.UseHsts();
}

app.UseHttpsRedirection();

app.UseAuthentication();
app.UseAuthorization();
app.UseAntiforgery();
app.UseStaticFiles();


app.MapRazorComponents<App>()
    .AddInteractiveServerRenderMode();

app.Run();

Upvotes: 0

Related Questions