Home > front end >  Web API saves JWT in cookies, but can not remove it
Web API saves JWT in cookies, but can not remove it

Time:11-28

I have written a C# web api endpoints for login and logout. When some one logs in I save a jwt token in their browser cookies. But I am unable to remove the cookie when the user logout. The cookie gets removed only in POSTMAN. Here are my both login and logout methods:

Login

[Route("login")]
        [HttpPost]
        public async Task<IActionResult> login(PeiUser user)
        {
            var attemptedUser = await _db.PeiUsers.FirstOrDefaultAsync(u => u.UEmail == user.UEmail);
            if (attemptedUser == null)
            {
                return BadRequest(new { message = "Invalid credentials" });
            }
            else
            {
                if (!BCrypt.Net.BCrypt.Verify(user.UPassword, attemptedUser.UPassword))
                {
                    return BadRequest(new { message = "Invalid credentials" });
                }
                else
                {
                    var jwt = _jwtService.Generate(attemptedUser.UId); // Generate the Access token that expires in one day

                    Response.Cookies.Append("jwt", jwt, new CookieOptions //Save the JWT in the browser cookies, Key is "jwt"
                    {
                        HttpOnly = true,
                        SameSite = SameSiteMode.None,
                        Secure = true
                    });

                    return Ok(new { message = "You are now logged in" });
                }
            }
        }

Logout



[Route("logout")]
        [HttpGet]
        public async Task<IActionResult> logout()
        {
            Response.Cookies.Delete("jwt");

            return Ok(new { message = "Success" });

        }

Note: The success message prints out in the console perfectly after logging out. But the cookie is still there.

In the REACT frontend I am calling like this:

 const logout = async() => {
        try{
            const res = await fetch('https://localhost:44361/api/users/logout', {
                headers: {"Content-Type": 'application/json'},
                credentials: 'include'
            })
            var content  = await res.json();
            console.log(content);
        }catch(err){
            console.log(err);
        }
    }

Note: The tutorial I learned this from also added the cookies perfectly without any issues. But I had to add SameSite = SameSiteMode.None, Secure = true in the Cookies.append properties in Login endpoint to make it work. The cookie gets cleared in POSTMAN. So I guess I am missing some configurations. I tried the logout endpoint by changing the method to both GET and POST

Any help is appreciated. Please ask me for any additional information

CodePudding user response:

I found out the solution after reading the documentation. A little change in Cookies.Delete in Logout endpoint has done the trick.I do not know why it is working

Response.Cookies.Delete("jwt", new CookieOptions 
            {
                HttpOnly = true,
                SameSite = SameSiteMode.None,
                Secure = true
            });

CodePudding user response:

You need to pass the same CookieOptions to the Delete method as to the Append method you initially used to create this cookie. The reason for this is has to do with the quirky way deleting a cookie works: the server emits a new Set-Cookie command, but with an empty value and an expiry set in the past. Browsers interpret this is as a sign to delete the cookie. But in order for this to function it needs all the same options or else the browser won't understand the server is targeting the existing cookie.

You can take a look at the implementation of Response.Cookies.Delete to see how this works:

            Append(key, string.Empty, new CookieOptions
            {
                Path = options.Path,
                Domain = options.Domain,
                Expires = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc),
                Secure = options.Secure,
                HttpOnly = options.HttpOnly,
                SameSite = options.SameSite
            });
  • Related