簡體   English   中英

快速會話發送的 Set-Cookie 未在瀏覽器上設置,但在本地開發中有效

[英]Set-Cookie sent by express-sessions is not being set on browser but works in local development

我有一個當前托管在 Vercel 上的 nextjs 13 應用程序,以及一個 node.js 快遞后端

我正在使用 express-sessions 和 google oauth flow,但是 express-sessions 發送的 set-cookie 沒有在瀏覽器上設置。

流程如下:

  1. Nextjs 應用程序請求 google auth uri,后端以 auth uri 響應
  2. 重定向到 google auth uri
  3. 成功登錄后,它會重定向到 nextjs 應用程序上的路由,該路由會重定向到后端(這樣查詢參數仍然是 url 的一部分
  4. 后端處理查詢參數,並將信息存儲在req.session上,並使用set-cookie再次重定向到 nextjs 應用程序

這是后端發送的響應:

在此處輸入圖像描述

在此處輸入圖像描述

快速會話中間件的設置:

app.use(
    session({
        name: 'sessionID',
        cookie: {
            maxAge: SESSION_LIFETIME as number,
            sameSite: 'lax',
            secure: NODE_ENV === 'production',
            httpOnly: true
        },
        resave: false,
        secret: SESSION_SECRET as string,
        saveUninitialized: false,
        store: redisStore
    })
);

谷歌 OAuth 回調代碼:

    try {
        const query = url.parse(request.url, true).query as {
            code: string;
        };

        const { tokens } = await googleOauth.getToken(query.code);
        const { access_token, refresh_token } = tokens;
        const userInfoResponse = await fetch(
            `https://www.googleapis.com/oauth2/v1/userinfo?alt=json&access_token=${access_token}`
        );

        const { email } = await userInfoResponse.json();

        let user = await getUserByEmail(email);

        if (user === undefined) {
            response.writeHead(307, { Location: process.env.WEB_URL + '?error=failed' });
            response.end();
            return;
        }

        // If it's the first time user logged in, create an account
        if (user === null) {
            user = await createUser({ email });

            // Something went wrong when creating the user
            if (!user) {
                response.writeHead(307, { Location: process.env.WEB_URL + '?error=failed' });
                response.end();
                return;
            }
        }

        const userToken = await saveUserTokens(
            user.id,
            access_token as string,
            refresh_token as string,
            OAuthProvider.google
        );

        if (!userToken) {
            response.writeHead(307, { Location: process.env.WEB_URL + '/?error=true' });
            response.end();
            return;
        }

        request.session.userId = user.id.toString();
        response.redirect(307, process.env.WEB_URL as string);

    } catch (error) {
        logger.error('Error while logging in with google', error);

        response.writeHead(307, { Location: process.env.WEB_URL + '/?error=true' });
        response.end();
    }

我認為這可能是由於發生了幾次重定向? 我有另一個端點用於使用 email 和帶有快速會話的密碼進行身份驗證,並且成功設置了該響應發送的 set-cookie。 這是 email 和密碼驗證的 /login 路由的響應:

在此處輸入圖像描述 在此處輸入圖像描述

登錄處理程序(電子郵件 + 通行證)代碼:

const loginHandler: RequestHandler = async (request, response) => {
    const { email, password } = request.body;

    const isValid = is(email, Email) && is(password, Password);

    if (!isValid) {
        return response
            .status(StatusCodes.BAD_REQUEST)
            .send({ message: 'Invalid Request: Missing or invalid email and password.' });
    }

    const user = await getUserByEmail(email);

    if (!user) {
        return response.sendStatus(401);
    }

    // Check if user logged in previously with another provider
    if (!user.password) {
        return response
            .status(StatusCodes.BAD_REQUEST)
            .send({ message: 'Please login with the login provider you used previously' });
    }

    const isPasswordCorrect = await compare(password, user.password);

    if (!isPasswordCorrect) {
        return response.sendStatus(StatusCodes.UNAUTHORIZED);
    }

    request.session.userId = user.id.toString();

    response.sendStatus(StatusCodes.OK);
};

如果您的前端和后端是獨立的域,請嘗試像這樣再次設置您的 cookie:

app.use(
    session({
        name: 'sessionID',
        cookie: {
            maxAge: SESSION_LIFETIME as number,
            sameSite: 'none', // in order to response to both first-party and cross-site requests
            secure: 'auto', // it should set automatically to secure if is https.
            httpOnly: true
        },
        resave: false,
        secret: SESSION_SECRET as string,
        saveUninitialized: false,
        store: redisStore
    })
);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM