Next-Auth server-side signout request to api/auth/signout
Asked Answered
P

1

8

I am using Next-Auth v4.22.1 and NextJS 13.

I am trying to sign out a user inside the [...nextauth].js jwt callback.

I know that signOut() is only available on the client side. If it is used on the server-side we will get a "ReferenceError: window is not defined" error.

My POST request to /api/auth/signout is not working.

I am getting the error

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.

My POST code from nextauth-signout-requests.js :

    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;

Anyone know what I am doing wrong? It's almost as if HTML is beign returned not JSON? I think that is what "Unexpected token E in JSON at position 0" means.

I' also not 100% on the CSRF token useage here? Never seen in a NextJS sevrer side POST req before.

Any help is appreciated!

Phony answered 29/4, 2023 at 7:32 Comment(2)
I did a postman POST request to /api/auth/signout and got the following response: "Error: This action with HTTP GET is not supported by NextAuth.js" It was a POST not a GET, so maybe malformed request? I am sending the wrong thing?Phony
I'm sorry 1000 people have viewed this question and still there's no answer. I suggest not using the Next-Auth library, it is just not ready for production...Phony
I
2

Unfortunately, next-auth seems to neglect server-side sign-out (as well as server-side redirect for authentication). The process is fairly straightforward to do yourself in an API endpoint, server-side render, etc.

For example, logout of next-auth (locally and AWS Cognito remotely) from an API endpoint:

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);
};

Warning: The above logic is vulnerable to next-auth changing their session cookie name prefix. Look out for this when upgrading next-auth versions.

Irita answered 26/11, 2023 at 23:30 Comment(3)
So just avoid using Next-Auth completely? We are deleting its cookies and then talking to the API ourselves directly. Yeah it will work but then why bother with Next Auth? Also we can't use any of next-auth's API features.Phony
next-auth is still adding lots of value. The auth redirect, callback and session cookie management are complex, and risky, flows that are made easy. Server side access token refresh should but built-in too, but they at least give a good example for DIY.Irita
Edited to correctly handle "__Secure-" prefixed session cookies over HTTPS. That will teach me to post to SO before I test off my local machine.Irita

© 2022 - 2024 — McMap. All rights reserved.