Search code examples
javascriptreactjsnode.jsexpresssupabase

Unable to access authorisation cookie


I am trying to implement backend(express+node +supabase) authentication for my frontend(react)

/*BACKEND*/
//auth.js
import { supabase } from "../config/supabaseConfig.js";

export const checkMyAuthStatus = async (token) => {
  try {
    const { data, error } = await supabase.auth.getUser(token);
    if (error) {
      console.error("Failed to authenticate token:", error.message);
      return false;
    }
    return !!data.user;
  } catch (error) {
    console.error("Error checking authentication status:", error);
    return false;
  }
};
export const mySignInFunc = async (email, pass, token) => {
  try {
    const { data, error } = await supabase.auth.signInWithPassword({
      email: email,
      password: pass,
      options: {
        captchaToken: token,
      },
    });
    if (!error) {
      return { data };
    } else {
      return { error };
    }
  } catch (error) {
    console.log(error);
    return { error: "Internal server error" };
  }
};
//authRoutes.js
authRouter.get("/authStatus", async (req, res, next) => {
  const token = req.cookies.access_token;
  console.log("Cookies:", req.cookies); // Debug log

  if (!token) {
    return res.status(400).json({ error: "Authorization token is required" });
  }

  try {
    const isAuthenticated = await checkMyAuthStatus(token);
    if (isAuthenticated) {
      res.status(200).json({ message: "User is authenticated" });
    } else {
      res.status(401).json({ message: "User is not authenticated" });
    }
  } catch (err) {
    res.status(500).json({ error: "Server error" });
    console.error(err);
  }
});

Here req.cookies shows an empty object and error req._implicitHeader pops as error

authRouter.post("/signIn", async (req, res, next) => {
  const { mail, pass, tok } = req.body;
  const result = await mySignInFunc(mail, pass, tok);
  const sess = await result.data.session;
  if (result.error) {
    res.status(400).json({ error: result.error });
  } else {
    // res.status(200).json({ data: result.data });
    res.cookie("access_token", sess.access_token, {
      httpOnly: true, // Ensures the cookie is only accessible via HTTP(S), not JavaScript
      secure: true, // Ensures the cookie is only sent over HTTPS
      maxAge: sess.expires_in * 1000, // Sets the cookie expiration time
      sameSite: "strict",
      signed: true,
      partitioned: true,
    });
    res.status(200).json({ data: result.data });
  }
});

/signIn cookie response

//Frontend auth.ts
const isAuthenticated = async () => {
    try {
        const response = await axios.get(
            `${String(import.meta.env.VITE_BASE_URL)}/auth/authStatus`,
            {
                withCredentials: true,
            }
        );
        console.log("response", response.data);
        return response.data ? true : false;
    } catch (error) {
        console.log(error);
        return false;
    }
};

export const checkAuthStatus = async () => {
    try {
        const isAuthenticateds = await isAuthenticated();
        console.log("user is auth:", isAuthenticateds);
        return isAuthenticateds;
    } catch (error) {
        console.log(error);
        return false;
    }
};
export const signInWithEmail = async (
    mail: string,
    pass: string,
    tok: string,
    router: any
) => {
    try {
        const response = await axios.post(
            `${String(import.meta.env["VITE_BASE_URL"])}/auth/signIn`,
            { mail, pass, tok }
        );
        console.log(response.data);

        if (response.data && response.data.data && response.data.data.session) {
            // Navigate to the user home page
            router.navigate({ to: "/user/Home" });
        } else {
            console.error("Invalid response structure:", response.data);
        }
    } catch (error) {
        console.log(error);
    }
};
  1. when i click on signin button it works properly the nw request shows the following access token
{
   "access_token": {
      "expires": "2024-07-01T11:44:30.000Z",
      "httpOnly": true,
      "path": "/",
      "samesite": "Strict",
      "secure": true,
      "value": "s:eyJhbGciOiJIUzI1NiIsImtpZCI6IkdNWGkrd2h1azB1QTZsQkYiLCJ0eXAiOiJKV1QifQ.eyJhdWQiOiJhdXRoZW5...   }
}

But when I try to access this token in my /authStatus request it fails: enter image description here 2) auth token is created still authStatus is consoled as false and backend shows following error in /authStatus: res._implicitHeader is not a function and when I console req.cookies it is empty

so how to correct the code

PS:

  1. I have tried to create a simple cookie too without http,secure etc attributes: res.cookie("access", sess.access_token) it still gives same response 2)corsOptions have been set to forward credentials too
const corsOptions = {
  origin: "http://localhost:5173",
  credentials: true, //access-control-allow-credentials:true
  optionSuccessStatus: 200,
};
app.use(cors(corsOptions));

Solution

  • The missing of withCredentials: true in the below statement is the cause of failure. In this case, a cookie will be created and sent by the server to the client which you can see in the response. However the same cookie will not store in the Browser, consequently the subsequent request to server will not be able to include it. Please include withCredentials: true in the statement and try again.

      const response = await axios.post(
                `${String(import.meta.env["VITE_BASE_URL"])}/auth/signIn`,
                { mail, pass, tok }
            );
    

    Citation:

    I am unable to set the cookies received from the response

    Cookies not being saved in browser