简体   繁体   中英

Remix Auth - `destroySession` returning [object Promise] instead of clearing the session

I'm trying to implement User Authentication in a Remix app and have been going around in circles trying to figure out why destroying the session is returning [object Promise] instead of clearing it.

在此处输入图像描述

My auth.server.js file contains functions that manage anything relating to creating, retrieving and destroying the Session Cookie, as well as a function to login .

import { hash, compare } from "bcryptjs";
import { prisma } from "./database.server";
import { createCookieSessionStorage, redirect } from "@remix-run/node";

export const sessionStorage = createCookieSessionStorage({
  cookie: {
    secure: process.env.NODE_ENV === "production",
    path: "/",
    secrets: [process.env.SESSION_SECRET],
    sameSite: "lax",
    maxAge: 30 * 24 * 60 * 60, // 30 days
    httpOnly: true
  }
});

async function createUserSession(userId, redirectPath) {
  const session = await sessionStorage.getSession();
  session.set("userId", userId);
  return redirect(redirectPath, {
    headers: {
      "Set-Cookie": await sessionStorage.commitSession(session)
    }
  });
}

export async function getUserFromSession(request) {
  const session = await sessionStorage.getSession(
    request.headers.get("Cookie")
  );

  const userId = session.get("userId");
  return userId ? userId : null;
}

export function destroyUserSession(request) {
  const session = sessionStorage.getSession(request.headers.get("Cookie"));

  return redirect("/", {
    headers: {
      "Set-Cookie": sessionStorage.destroySession(session)
    }
  });
}

export async function login({ email, password }) {
  const existingUser = await prisma.user.findFirst({ where: { email } });
  if (!existingUser) {
    return throwError(
      "Could not log you in, please check provided email.",
      401
    );
  }

  const passwordCorrect = await compare(password, existingUser.password);
  if (!passwordCorrect) {
    return throwError(
      "Could not log you in, please check provided password.",
      401
    );
  }

  return createUserSession(existingUser.id, "/");
}

function throwError(text, code) {
  const error = new Error(text);
  error.status = code; // authentication error code
  throw error; // this triggers ErrorBoundary, as it's not an error response
}

My logout function is in a separate .js file located inside the /routes folder.

import { json } from "@remix-run/node";
import { destroyUserSession } from "~/data/auth.server";

export function action({ request }) {
  if (request.method !== "POST") {
    throw json({ message: "Invalid request method" }, { status: 400 });
  }

  return destroyUserSession(request);
}

Finally, the Logout button is inside the navigation bar and contained within a <Form> element.

<Form method="post" action="/logout">
   <button type="submit">Logout</button>
</Form>

SOLVED
I was somehow able to solve it by moving the logout function into auth.server.js and leaving the following in the logout.js route:

import { redirect } from "@remix-run/node";
import { logout } from "~/data/auth.server";

export const action = ({ request }) => logout(request);
export const loader = () => redirect("/auth");

The session functions are all async . The reason you had [object Promise] was that you were returning the promise directly. You need to use await .

export function destroyUserSession(request) {
  const session = sessionStorage.getSession(request.headers.get("Cookie"));

  return redirect("/", {
    headers: {
      // use await on session functions
      "Set-Cookie": await sessionStorage.destroySession(session)
    }
  });
}

PS That's one of the benefits of TypeScript. It would have told you that headers required a string value and would not allow the Promise return.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM