elysiajs / elysia

Ergonomic Framework for Humans
https://elysiajs.com
MIT License
10.25k stars 219 forks source link

cookie.auth.remove() function is not working as expected #536

Open warcayac opened 7 months ago

warcayac commented 7 months ago

What version of Elysia.JS is running?

0.8.17

What platform is your computer?

Linux 6.7.9-zen1-1-zen x86_64 unknown

What steps can reproduce the bug?

I have this sample code:

import { Elysia, t } from "elysia";

import { users } from '../../utils/samples';
import { JWT } from "../../middleware/jwt";

export const authRoutes = new Elysia()
  .use(JWT)
  .post(
    '/login', 
    async ({body: {username,password}, set, myJWTNamespace, cookie: {auth}}) => {
      const user = users.find(user => user.username === username);
      const validPwd = user ? await Bun.password.verify(password, user.passwordHash) : false;

      if (auth && validPwd) {
        const token = await myJWTNamespace.sign({username});

        auth.set({
          value: token,
          httpOnly: true,
          maxAge: 600, // 10 min
          path: '/protected'
        });

        set.headers = {
          'HX-Refresh': 'true',
        };

        return `Sign in as ${auth.value}`;
      }

      set.status = 401;
      return 'Unauthorized';
    },
    {
      body: t.Object({
        username: t.String({minLength: 3}),
        password: t.String({minLength: 3}),
      })
    }
  )
  .get(
    '/logout', 
    ({set, cookie: {auth}}) => {
      if (!auth) {
        set.status = 400;
        return 'Bad Request';
      }

      auth.remove({path:'/protected'});

      set.headers = {
        'HX-Refresh': 'true',
      };

      return 'Logged out'
    },
  )
;

Endpoints:

What is the expected behavior?

when logout endpoint is called the cookie should ALWAYS delete the cookie on web browser client

What do you see instead?

Many times cookie is not removed from web browser client, in Chrome and derivatives at least.

Additional information

This workaround ALWAYS works for me:

      auth.set({
        httpOnly: true,
        maxAge: 1,
        path: '/protected',
      });

Bun version: 1.0.30+1424a196f

raggesilver commented 7 months ago

After upgrading to Elysia 1.0+ I noticed .remove() no longer takes any arguments. In my case, trying to remove the cookie doesn't work as the path is different.

If I set the path before removing the cookie it works again.

auth.path = "/protected";
auth.remove();
denis12301232 commented 6 months ago

Same problem

L3oJr commented 6 months ago

Since the .remove() method really not working, I solved this by setting the cookie maxAge to zero.

auth.set({
   maxAge: 0,
});
wirawanmahardika commented 6 months ago

I have the same issue, but once i set the cookie config in the main Elysia instance (in src/index.ts), and add the cookie name i used in sign property, Then it work as usual

new Elysia({
  cookie: {
    secrets: process.env.COOKIE_AUTH_SECRET,
    sign: ["auth"],
  },
})
  .use(corsConfig())
  .use(usersController)
  .onError(() => {
    return new Response("INTERNAL SERVER ERROR", { status: 500 });
  })
  .listen(port, () => console.log("Server is listening at port", port));

This is the login endpoint to create the cookie :

 .post(
    "/login",
    async ({ body, cookie, jwt }) => {
      const user = await usersServices.login.repository.getUser(body.username);

      if (!user)
        return new Response("username tidak pernah terdaftar", { status: 401 });

      if (user.password !== body.password) {
        return new Response("password salah", { status: 401 });
      }

      cookie.auth.set({
        httpOnly: true,
        maxAge: 3600 * 24,
        path: "/",
        priority: "high",
        value: await jwt.sign({ username: body.username, id: user.id }),
        sameSite: "strict",
        expires: new Date(Date.now() + 1000 * 3600 * 24),
        secure: process.env.IS_HTTPS ? true : false,
      });

      return "Berhasil login";
    },
    usersServices.login.schema
  );

And this endpoint would remove the cookie as we expected :

  .delete("/", ({ cookie }) => {
    cookie.auth.remove();
    return `Berhasil logout`;
  })
warcayac commented 4 months ago

I've tried with every suggestion made up to now in this thread but they don't work for me, except for my workaround and this:

      cookie.auth!.set({
        value: '',
        maxAge: 0,
        path: "/protected",
      })

My current Bun is v1.1.9 and Elysia is v1.0.22

qprqpr commented 4 months ago

Same problem. The suggested workaround works for me.

huilensolis commented 4 months ago

Hi, I'm working on this issue. If the path on set cookie doesn't match the path of the old cookie, the browser does not update the cookie.

huilensolis commented 4 months ago

@SaltyAom I'm thinking of taking the path as an argument on cookie.name.remove(), and setting its default to the defined in the Elysia instance, or "/", what do you think? tell me and I will open a pr!

before

new Elysia().get("/sign-out", ( { cookie: { access_token }, set } ) => {
      access_token.remove()
}),

after:

new Elysia( { cookie: { path: "/my-path"} } ).get("/sign-out", ( { cookie: { access_token }, set } ) => {
      access_token.remove({path: "/the-cookie-path") // default to path defined in Elysia instance || "/"
}),