Federated Logout with Google SSO Retains Session

I’m using Auth0 with a SAML (SSO) connection configured for Google Workspace in my Next.js application. While logging in and out works generally well, I’m encountering an issue where logging out of Auth0 does not fully terminate the session with Google.

Here’s the scenario:

  1. A user logs in with user1@domain.com via Google SSO.
  2. The user logs out using the federated parameter in the Auth0 logout URL (/v2/logout?federated).
  3. When attempting to log in with user2@domain.com, Google automatically logs in user1@domain.com without prompting for new credentials.

I’ve already:

  • Ensured prompt: 'login' is included in the login flow.
  • Configured the federated parameter in the logout URL.
  • Tested manually visiting https://accounts.google.com/Logout, which resolves the issue, but I need this behavior integrated automatically.

Despite these efforts, Google’s session remains active after logging out of Auth0. Is there a configuration or additional step required to ensure that federated logout properly terminates the Google session? Any insights or guidance would be appreciated!

Hi @ranchuk ,

You can look at this article and get an idea how to handle this scenario.

I would suggest you to implement custom logout handler that manages Google and Auth0 sessions

Let me know if this doesn’t work.

The attached thread says that there is “no solution”. What ideas could I get from it? is there any temporary workaround?

Hi @ranchuk

Welcome to the Auth0 Community!

Thank you again @sumansaurav for providing insight via our knowledge article.

As mentioned in our documentation regarding Federated Logouts endpoint, it does have some limitations regarding the alternative logout.

As mentioned in the documentation regarding federated logouts:

  • No validation is performed on any URL provided as a value to the returnTo parameter, nor any query string or hash information provided as part of the URL.

  • The behavior of federated logouts with social providers is inconsistent. Each provider will handle the returnTo parameter differently and for some, it will not work. Please check your social provider’s settings to determine how it will behave.

  • If you are working with social identity providers such as Google or Facebook, you must set your Client ID and Secret for these providers in the Dashboard for the logout to function properly.

  • If you are an Auth0 Enterprise user, you will typically have SSO enabled for multiple applications, for example, SharePoint, a few .NET applications, a few Java applications, Zendesk, etc. In this case, it’s very common that when users sign out, this needs to happen for all of their applications.

As advised above, a custom logout handler might do the trick regarding your use case.
At the moment there is no workaround on the matter, otherwise, these workaround would be mentioned in the knowledge article.

Please let us know if you have found a solution or if you have additional questions on the matter.

Kind Regards,
Nik

Can you advise on how to implement a custom logout handler? I’ve tried multiple attempts, with various of network request. Pardon my comments :smiley:

  if (action === 'logout') {
    const session = await appClient.getSession();

    const logoutUrl = [
      'https://',
      process.env.AUTH0_ISSUER_BASE_URL,
      '/v2/logout?',
      'client_id=',
      process.env.AUTH0_CLIENT_ID,
      '&returnTo=',
      process.env.AUTH0_BASE_URL,
      '&federated',
      '&id_token_hint=',
      session?.idToken,
    ];

    const googleLogoutUrls = [
      `https://mail.google.com/a/localhost:3000/?logout&hl=en`,
      `https://accounts.google.com/Logout`,
      `https://mail.google.com/a?logout&hl=en`,
      'https://www.google.com/accounts/Logout?continue=https://appengine.google.com/_ah/logout?continue=http://localhost:3000',
    ];

    await Promise.all(
      googleLogoutUrls.map(async (url) => {
        await fetch(url, {
          method: 'GET',
        }).then((res) => {
          console.log(`${url}:`, res.status, res.statusText);
        });
      })
    );

    // const logoutHintUrl = `https://${process.env.AUTH0_ISSUER_BASE_URL}/oidc/logout?clientId=${process.env.AUTH0_CLIENT_ID}&logout_hint=${session?.user.sid}
    //   &post_logout_redirect_uri=${process.env.AUTH0_BASE_URL}&id_token_hint=${session?.idToken}`;

    // await fetch(logoutHintUrl, {
    //   method: 'GET',
    // });

    // const googleLogoutUrl = 'https://accounts.google.com/Logout';
    // const workspaceRes = await fetch(googleLogoutUrl, { method: 'GET' });
    // console.log(workspaceRes);

    const handleLogout = appClient.handleLogout({
      returnTo: logoutUrl.join(''),
    });

    return handleLogout(req, { params });
  }

In order to customize the logout flow, you will need to pass in the returnTo parameter to redirect the user to the target URL after logout. You can refer to our Logout Documentation.

Otherwise, regarding your implementation, it appears that you might be passing in the logoutUrl parameters incorrectly. You can attempt to do the following:

const logoutUrl = [
      process.env.AUTH0_ISSUER_BASE_URL,
      '/v2/logout?',
      'federated',
      '&client_id=',
      process.env.AUTH0_CLIENT_ID,
      '&returnTo=',
      process.env.AUTH0_BASE_URL,
      '&id_token_hint=',
      session?.idToken,
    ];

Alternatively, you can attempt to drop the federated parameter:

api/auth/[auth0]/route.ts

import { handleAuth, handleLogin, handleLogout } from '@auth0/nextjs-auth0';

const logoutUrl = [
  `${process.env.AUTH0_ISSUER_BASE_URL}/v2/logout?`,
  `client_id=${process.env.AUTH0_CLIENT_ID}`,
  `&returnTo=${process.env.AUTH0_BASE_URL}`,
];

export const GET = handleAuth({
  logout: handleLogout({ returnTo: logoutUrl.join('') }),
});

Otherwise, you can attempt to overwrite the /api/auth/[auth0]/route.ts:

import { handleAuth, handleLogout } from "@auth0/nextjs-auth0";
import { NextResponse } from "next/server";

export const GET = handleAuth({
  logout: async (req, res) => {
    return NextResponse.redirect(
      process.env.AUTH0_LOGOUT_OIDC +
        "?post_logout_redirect_uri=" +
        encodeURIComponent(process.env.AUTH0_BASE_URL)
    );
  },
});

If you still have further issues with your implementation or additional questions, feel free to leave another reply!

Kind Regards,
Nik

1 Like

Both does not work. AUTH0_LOGOUT_OIDC refers to the logout URL above? because I’m using SAML

Not sure if related or not, but I’m also using initAuth0 with these options:

import { initAuth0 } from '@auth0/nextjs-auth0';

export const appClient = initAuth0({
  clientID: process.env.AUTH0_CLIENT_ID,
  clientSecret: process.env.AUTH0_CLIENT_SECRET,
  baseURL: process.env.AUTH0_BASE_URL,
  issuerBaseURL: `https://${process.env.AUTH0_ISSUER_BASE_URL}`,
  secret: process.env.AUTH0_SECRET,
  idpLogout: true,
  auth0Logout: true,
});

Hi @ranchuk

I am sorry to hear you still experience issues with the federated logout.

If the above implementation did not help, I can advise you to attempt integrating Single Identity Logout for your application.
You can review our Knowledge Article about SAML SLO and also our documentation about it.

Otherwise, your implementation should do the trick in logging out the user and the issue might be on Google Workspace’s end due to the fact that they might not handle the returnTo parameter in order to logout the session with them. I would recommend to investigate this the documentation available on their website ( if they provide any).

Let us know if SLO did the trick or if you have any other questions.

Kind Regards,
Nik

Hi team!

This is a heads-up that we’re hosting an Ask Me Anything (AMA) session dedicated to Auth0 sessions, refresh tokens, and the Management API. Our product experts will be on hand February 12, 2025, from 8 AM to 10 AM PST to answer all your questions—no matter how basic or advanced they may be! You can submit your queries anytime from now until February 11, and we’ll provide detailed written answers during the live event.

This is a fantastic opportunity to learn best practices around session management, refresh token rotation, and the Management API. Plus, everyone who participates gets points and a special badge just for joining in on the fun. :tada:

If you have any burning questions (or even casual curiosities!), feel free to drop them in this thread. We can’t wait to see what you’re working on and how we can help you optimize your Auth0 setup. See you there!

Auth0 Community Ask Me Anything: Auth0 Sessions and Refresh Tokens

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.