Logout (delete Auth-Cookie) only possible via form!

perfect code 271 Reputation points
2023-01-28T13:26:22.5033333+00:00

I have a Blazor server application (see my post here: https://learn.microsoft.com/en-us/answers/questions/1164837/aspnet-authentication-works-but-value-for-user-ide). Now I have implemented a cookie authentication. This works very well via a login and logout form.

                @if (userParaMana.IsLogged)
                {
                    <form action="cookie" method="post">
                        <input type="hidden" name="email" />
                        <div style="display: flex; justify-content: center;">
                            <input type="submit" value="@_T_("k_logout")" />
                        </div>
                    </form>
                }
                else
                {
                    <form action="cookie" method="post">
                        <label>Email</label>
                        <input type="text" name="email" />
                        <label>Password</label>
                        <input type="password" name="password" />
                        <div style="display: flex; justify-content: center;">
                            <input type="submit" value="@_T_("k_login")" />
                        </div>
                    </form>
                }

My controller ()Note: I use the Login method for both login and logout depending on whether something comes from the Email field).

   [Route("/[controller]")]
    [Route("api/Logout")]
    [ApiController]
    public class CookieController : ControllerBase
    {
        [HttpPost]
        public async Task<ActionResult> Login([FromForm] string? email)
        {
            if (String.IsNullOrEmpty(email))
            {
                await HttpContext.SignOutAsync();
                return Redirect("/");

                //    //Response.Cookies.Append("calc3", string.Empty, new CookieOptions
                //    //{
                //    //    Path = Request.PathBase, // needed if running under virtual directory
                //    //    Secure = true,
                //    //    Expires = DateTimeOffset.UtcNow.AddDays(-2),
                //    //    IsEssential = true,
                //    //    SameSite = SameSiteMode.Lax // Match the same site settings of the cookie
                //    //});

                //    //Response.Cookies.Delete("calc3", new CookieOptions()
                //    //{
                //    //    Secure = true,
                //    //});

                //    //await HttpContext.SignOutAsync();
                //    return Redirect("/");
                //}
                //catch (Exception ex)
                //{

                //    throw;
                //}
            }
            else
            {
                ClaimsIdentity claimsIdentity = new ClaimsIdentity(new List<Claim>
                {
                    new Claim(ClaimTypes.Name, email),
                    new Claim(ClaimTypes.NameIdentifier, email),
                    new Claim(ClaimTypes.Email, email)
                }, "auth");
                ClaimsPrincipal claims = new ClaimsPrincipal(claimsIdentity);
                await HttpContext.SignInAsync(claims);
                return Redirect("/");
            }
        }

So this works fine, the user can log in, auth-cookie is created, and when the user logs out, the auth-cookie is deleted on the client.

My problem is that the next time I log in automatically (because cookie exists, it doesn't ask for email/password), I still need to verify the user in the database. So I read the user (email) from the cookie and go into the database to see if the user is still activated. If it is not activated, then I have to delete cookie on the client.

Exactly at this point I have a problem, because if I now call my controller method via

                                HttpClient Http = new HttpClient();
                                string baseUrl = "https://localhost:7169/api/Logout";
                                //var temp2 = await Http.GetStringAsync($"{baseUrl}Cookie/Login");
                                await Http.PostAsync(baseUrl, null);

then the code is actually executed from the controller without an error message, but the cookie still remains on the client!

I think I am making an error in reasoning somewhere. How do I delete the auth-cookie from the blazor-code? Probably I have to call controller (POST). I do that here too, but why doesn't that work?

Any ideas?

Thanks

ASP.NET Core
ASP.NET Core
A set of technologies in the .NET Framework for building web applications and XML web services.
2,831 questions
Blazor
Blazor
A free and open-source web framework that enables developers to create web apps using C# and HTML being developed by Microsoft.
882 questions
.NET MAUI
.NET MAUI
A Microsoft open-source framework for building native device applications spanning mobile, tablet, and desktop.
1,076 questions
ASP.NET MVC
ASP.NET MVC
A Microsoft web application framework that implements the model-view-controller (MVC) design pattern.
733 questions
C#
C#
An object-oriented and type-safe programming language that has its roots in the C family of languages and includes support for component-oriented programming.
7,562 questions
No comments
{count} votes

Accepted answer
  1. AgaveJoe 19,681 Reputation points
    2023-01-28T14:56:03.42+00:00

    If I understand, the issue is invalidating a cookie. Create a form in your main layout that points to the working logout action. Keep in mind, HTML forms cannot be nested.

    Check the email address when the Blazor application loads. If the email does not exist then submit the form. I would write a simple JavaScript function located in the layout page (or a separate file if you have other JavaScript logic to organize) then call the function using Blazor interop.

    Form submit() Method

    ASP.NET Core Blazor JavaScript interoperability (JS interop)

    1 person found this answer helpful.

1 additional answer

Sort by: Most helpful
  1. Bruce (SqlWork.com) 31,256 Reputation points
    2023-01-28T16:48:31.1933333+00:00

    As you are running blazor server, when it makes an HTTP client call, it’s the server calling the cookie api, not the client. You need to use JavaScript interop for the client to make the call.

    1 person found this answer helpful.