How to use Radzen components with SignInAsync and SignOutAsync

Hi all,

I’m still new to blazor development but we have decided to use Blazor .NET8 Web Apps with Radzen Components.

I am trying to create an authentication cookie in the web browser using HttpContext.SignInAsync method but have noticed that I am unable to access HttpContext if I use @rendermode InteractiveServer in my login component file.

I tried accessing the httpcontext using an api controller method but it wasn’t working. In the end I had to strip out all Radzen components on my login form, remove @rendermode then I was able to create the cookie successfully. Code is the following:

@page "/login"
@using System.ComponentModel.DataAnnotations
@using System.Security.Claims
@using Microsoft.AspNetCore.Authentication
@using Microsoft.AspNetCore.Authentication.Cookies
@inject NavigationManager Nav
@inject UserService UserService

<div class="row">
	<div class="rz-col-lg-4 rz-offset-lg-4 rz-pt-4 rz-pb-4 rz-border">
		<EditForm Model="@loginModel" OnValidSubmit="LoginUser" FormName="LoginForm">
			<DataAnnotationsValidator />
			<div class="rz-mb-3 rz-text-align-center rz-flex-column">
				Login
			</div>
			<div class="rz-mb-3">
				<label>Username:</label>
				<InputText @bind-Value="loginModel.Username" placeholder="Username" />
				<ValidationMessage For="() => loginModel.Username" />
			</div>
			<div class="rz-mb-3">
				<label>Password:</label>
				<InputText type="password" @bind-Value="loginModel.Password" placeholder="Password" />
				<ValidationMessage For="() => loginModel.Password" />
			</div>
			@if (!string.IsNullOrEmpty(loginModel.ErrorMessage))
			{
				<div class="rz-mb-3">
					<span>@loginModel.ErrorMessage</span>
				</div>
			}
			<div class="rz-mb-3">
				<button type="submit">Login</button>
			</div>
		</EditForm>
	</div>
</div>

@code {
	[SupplyParameterFromForm]
	private LoginModel loginModel { get; set; } = new();

	[CascadingParameter]
	public HttpContext? HttpContext { get; set; }

	private async Task LoginUser()
	{
		loginModel = await UserService.LoginAsync(loginModel);
		switch (loginModel.Status)
		{
			case "success":
				var claims = new List<Claim>
				{
					new(ClaimTypes.NameIdentifier, loginModel.UserId),
					new(ClaimTypes.Name, loginModel.Username)
				};

				var identity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme);
				var principal = new ClaimsPrincipal(identity);

				var authProps = new AuthenticationProperties
					{
						IsPersistent = true,
						ExpiresUtc = DateTimeOffset.UtcNow.AddHours(loginModel.SessionTimeoutPeriod)
					};

				await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, principal, authProps);
				break;

			case "pwexpired":
				// Navigate to change-password page
				Nav.NavigateTo("/password-expired");
				break;
		}
	}
}

Now I am having difficulties adding a log out link to my mainlayout file since I am calling Radzen components in there:

@using Microsoft.Extensions.Caching.Memory
@using System.Security.Claims
@using Microsoft.AspNetCore.Authentication
@using Microsoft.AspNetCore.Authentication.Cookies
@inject UserService LoginService
@inject NavigationManager Nav
@inherits LayoutComponentBase
<RadzenComponents @rendermode="InteractiveServer" />
<RadzenLayout>
	<RadzenHeader>
		<button @onclick="Logout">Logout</button>
	</RadzenHeader>
	<RadzenBody>		
		@Body
	</RadzenBody>
</RadzenLayout>

<div id="blazor-error-ui">
	An unhandled error has occurred.
	<a href="" class="reload">Reload</a>
	<a class="dismiss">🗙</a>
</div>

@code {
	[CascadingParameter]
	public HttpContext? HttpContext { get; set; }

	private async Task Logout()
	{
		var userIdClaim = HttpContext.User.FindFirst(ClaimTypes.NameIdentifier)?.Value;
		if (int.TryParse(userIdClaim, out int userId))
		{
			bool success = LoginService.Logout(userId);
			if (success)
			{
				await HttpContext.SignOutAsync();
				Nav.NavigateTo("/login", true);
			}			
		}				
	}
}

The button click is doing nothing probably because I didn’t add a @rendermode I think? and I think I might have the same problem of not being able to access HttpContext to delete the cookie.

Can someone please provide the correct steps on how I can still use Radzen components and create/delete a cookie successfully in the web browser. Apologies if I missed an easy step to achieve this, I am still a noob at blazor and learning.

Hope to get some help with this, have been struggling for a while and would like to use these nice radzen components in my login form!

Hi @hdhani,

Indeed Radzen Blazor components require interactivity (@rendermode). You cannot use them in non-interactive pages (you can but they won't fire any events and certain features that require them won't work). We have been using controllers to perform login and logout. Here is a sample application.
AuthorizationApp.zip (253.3 KB)

1 Like

amazing, thanks for the sample project! Do you know what version of Visual Studio I need to be able to run it? Seems to want .NET 10 but I am using VS 2022 Community Edition which I think only goes up to .NET 9

To use .NET 10 you need Visual Studio 2026, I would suggest this since it's always good to start a new project up to date (10 came out a couple weeks ago). If you wish to use 9 or 8 instead, you would be fine using your Visual Studio 2022 installation.

1 Like

Thanks, downloading 2026 to hopefully get the sample project to build and run successfully so that I can understand how the code works

Hi all,

Slowly making progress with this. My GET method doesn’t seem to execute on page load compared to the sample application. I’m not sure what is triggering this method to run in the sample project provided?

[HttpGet]
public async Task<IActionResult> Login(string returnUrl)
{
    if (returnUrl != "/" && !string.IsNullOrEmpty(returnUrl))
    {
        return Redirect($"~/Login?redirectUrl={Uri.EscapeDataString(returnUrl)}");
    }

    return Redirect("~/Login");
}

Also is there a way I can set a breakpoint in code, debug the application without the web page timing out after 30 seconds and then stop working (can see a pop up appear on the webpage which says rejoining the server and then it times out).

The console in chrome shows this:

content-script.js:196 Keep-Alive mechanism ongoing
content-script.js:196 Keep-Alive mechanism ongoing
blazor.web.js:1 [2025-12-05T12:58:37.301Z] Error: Connection disconnected with error 'Error: WebSocket closed with status code: 1006 (no reason given).'.
log @ blazor.web.js:1
_stopConnection @ blazor.web.js:1
features.reconnect.transport.onclose @ blazor.web.js:1
_close @ blazor.web.js:1

Hi @hdhani,

This login method (the GET version) is called when an unauthorised user tries to access a page that needs authorisation (for example by navigating to this page URL in the browser). The method redirects the user to the login page. The actual login is done by the Login method which is decorated with HttpPost attribute.

Thanks. For some odd reason if the user is unauthorised my GET method does not get hit but my page still redirects to the login page. Maybe I don’t need the GET method in my project if its working without it! I’ve managed to successfully login and logout now with the cookie being created properly.

Do you know what the solution is to my second query? I think it is some sort of built in thing with blazor and signalR but I’m not sure how to set a longer timeout before the page loses connection while I am debugging code and sitting on a breakpoint.

Yes, it is a built-in thing with Blazor and server-side rendering mode. I suggest searching online how to increase the timeout.