对 api/auth/signout 的 Next-Auth 服务器端注销请求

Sco*_*ile 8 next.js next-auth next.js13

我正在使用 Next-Auth v4.22.1 和 NextJS 13。

我正在尝试在 [...nextauth].js jwt 回调中注销用户。

我知道signOut()仅在客户端可用。如果在服务器端使用它,我们将收到“ReferenceError:窗口未定义”错误。

我对 /api/auth/signout 的 POST 请求不起作用。

我收到错误

nextauth-signout-requests.js - Fetch Error SyntaxError: Unexpected token E in JSON at position 0
API handler should not return a value, received object.
API resolved without sending a response for /api/nextauth-signout-requests, this may result in stalled requests.
Run Code Online (Sandbox Code Playgroud)

我来自 nextauth-signout-requests.js 的 POST 代码:

    const NextAuthSignOutReq = async (req, res) => {

        if (req.method === 'POST') {
            try {

                // Sign out the user
                const signOut = await fetch(`${HOMEPAGE_URL}/api/auth/signout?callbackUrl=${HOMEPAGE_URL}/api/auth/session`, {
                    method: 'POST',
                    headers: {
                        'Content-Type': 'application/json',
                        'Accept': 'application/json'
                    },
                    body: await fetch(`${HOMEPAGE_URL}/api/auth/csrf`).then(rs => rs.text())
                });


                const data = await signOut.json();

                if (signOut.status === 200) {
                
                    // Success
                    console.log('User Signed Out');

                    return res.status(200);

                } else {

                    // Fail

                    console.log(`nextauth-signout-requests.js - POST to /auth/signout failed`);

                    return res.status(500);
                }
            } catch(err) {

                // Fail

                console.log('nextauth-signout-requests.js - Fetch Error ' + err);

                return res.status(500);

            }
        } 
        else {
            // Error. Not a POST request. They tried GET or PUT etc.

            res.setHeader('Allow', ['POST']);
            return res.status(405).json({ 'error': `Method ${req.method} not allowed`});
        }

    }

    export default NextAuthSignOutReq;
Run Code Online (Sandbox Code Playgroud)

有人知道我做错了什么吗?就好像返回 HTML 而不是 JSON 一样?我认为这就是“JSON 中位置 0 处的意外标记 E”的含义。

我也不是 100% 同意这里的 CSRF 令牌使用情况?以前从未在 NextJS 服务器端 POST 请求中见过。

任何帮助表示赞赏!

小智 1

不幸的是,next-auth 似乎忽略了服务器端注销(以及用于身份验证的服务器端重定向)。这个过程非常简单,您可以在 API 端点、服务器端渲染等中自行完成。

例如,从 API 终端节点注销下一个身份验证(本地和 AWS Cognito 远程):

const logout = (req: NextApiRequest, res: NextApiResponse) => {
  // Clear all session cookies
  const isSecure = req.headers['x-forwarded-proto'] === 'https';
  const cookiePrefix = `${isSecure ? '__Secure-' : ''}next-auth.session-token`;
  const cookies: string[] = [];
  for (const cookie of Object.keys(req.cookies)) {
    if (cookie.startsWith(cookiePrefix)) {
      cookies.push(`${cookie}=deleted; Max-Age=0; path=/ ${isSecure ? '; Secure ' : ''}`);
    }
  }
  res.setHeader('Set-Cookie', cookies);
  // Redirect to AWS Cognito to logout
  const cognitoLogoutUrl = new URL('/logout', process.env.COGNITO_DOMAIN);
  cognitoLogoutUrl.searchParams.set('client_id', `${process.env.COGNITO_CLIENT_ID}`);
  cognitoLogoutUrl.searchParams.set('logout_uri', `${process.env.LOGOUT_URL}/`);
  res.redirect(307, cognitoLogoutUrl.href);
};
Run Code Online (Sandbox Code Playgroud)

警告: 上述逻辑很容易受到下一个身份验证更改其会话 cookie 名称前缀的影响。升级下一个身份验证版本时请注意这一点。