Skip to content

v4: Allow wildcards in returnTo Allowed Logout URLs again #1883

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
6 tasks done
larsEichler opened this issue Feb 5, 2025 · 5 comments
Open
6 tasks done

v4: Allow wildcards in returnTo Allowed Logout URLs again #1883

larsEichler opened this issue Feb 5, 2025 · 5 comments
Labels

Comments

@larsEichler
Copy link

larsEichler commented Feb 5, 2025

Checklist

Description

In v4 the returnTo param seems to be way more strict than it was in v3. In v3 you were able to configure wildcards http://localhost:3000/*/about, with v4 it seems you need to explicitly set URLs in full.

This is creating an issue for us, as our app has multiple languages, multiple environments (development, staging, production) AND we pass messages with the query parameters of the returnTo-URL.

Is it possible to allow wildcards in the Allowed Logout URLs again with v4? Also, you were not required to pass the full URL with host and protocol before, like href="/auth/logout?returnTo=/en/about?message=forced_logout". Now the full URL is required and has to be exactly like in the Allowed Logout URLs setting. Can't we go back to the old implementation?

Reproduction

It CAN NOT be reproduced with the example app, as the example app is not yet updated to v4. Here is an example-repo: https://github.com/larsEichler/nextjs-auth0-returnto-issue

  1. Clone and set up repo
  2. In auth0 set up a Regular Web App with NextJS as framework
  3. Set Allowed Callback URLs: http://localhost:3000/auth/callback
  4. Set Allowed Logout URLs: http://localhost:3000/*/about
  5. Run the application
  6. Register a new user/Login with the one you already created
  7. Click on Logout

Additional context

No response

nextjs-auth0 version

v4.0.0

Next.js version

v15.1.6, v14.2.23

Node.js version

v22.12.0

@DawnMD
Copy link

DawnMD commented Feb 10, 2025

Facing the same issue, as our website is like an e-commerce where user can apply coupon code. While auth is not an absolute mandatory and also coupon code can change drastically, so putting up the exact url with query params will be very much irrelevant.

Other way is to always reset the url and send them back to home page but that will be bad for ux as all the query params will be lost and user have to start again.

This seems not to be an issue with v3

@mvvmm
Copy link

mvvmm commented Feb 14, 2025

As a workaround, you can save the returnTo url for the user in storage somewhere (local storage, cookies, database, etc), and set a static url as your logout returnTo, and then redirect the user from your own static route. For example, we use local storage and this is what we do:

  1. Add /logout-redirect-passthrough as an allowed logout url in our auth0 dashboard

  2. When we need to provide the user with a returnTo logout, we set that dynamic url in local storage, CUSTOM_REDIRECT_URL, and then we log them out with the returnTo route of /logout-redirect-passthrough.

  3. Create a custom unauthenticated page /logout-redirect-passthrough. This page will look at the users local storage and redirect them to the CUSTOM_REDIRECT_URL link if it exists, and then remove the local storage value.

It's a little annoying doing that redirect on the client, so you may want to use some other type of storage, depending on your use case.

Let me know if there is a better way

@jeremy-aithon
Copy link

I am running into this issue using tenant subdomains matching the organization name. I am forced to defined every tenant subdomains in the application Allowed Logout URLs while previously http://*.localhost:3000 was sufficient.

In comparison, the Allowed Callback URLs is set to http://{organization_name}.localhost:3000/auth/callback and working as expected.

@larsEichler
Copy link
Author

As a workaround, you can save the returnTo url for the user in storage somewhere (local storage, cookies, database, etc), and set a static url as your logout returnTo, and then redirect the user from your own static route. For example, we use local storage and this is what we do:

1. Add `/logout-redirect-passthrough` as an allowed logout url in our auth0 dashboard

2. When we need to provide the user with a returnTo logout, we set that dynamic url in local storage, CUSTOM_REDIRECT_URL, and then we log them out with the returnTo route of `/logout-redirect-passthrough`.

3. Create a custom unauthenticated page `/logout-redirect-passthrough`. This page will look at the users local storage and redirect them to the CUSTOM_REDIRECT_URL link if it exists, and then remove the local storage value.

It's a little annoying doing that redirect on the client, so you may want to use some other type of storage, depending on your use case.

Let me know if there is a better way

He @mvvmm, do you mind sharing the code for the /logout-redirect-passthrough-Page? My implementation is triggered multiple times, and the second time the localstorage item is removed, therefore null, and the redirect goes to / instead of the redirect url:

'use client'
import React from "react"
import { redirect } from 'next/navigation'
import { NOTIFICATION_QUERY_PARAM } from "../components/Notification/types";

function Page() {
    if (typeof window !== "undefined") {
        const redirectData = localStorage.getItem('redirectAfterLogoutData');
        const parsedRedirectData = redirectData ? JSON.parse(redirectData) : null;
        localStorage.removeItem('redirectAfterLogoutData');

        if (!parsedRedirectData?.url) {
            redirect('/');
        }

        redirect(`${parsedRedirectData.url}?${new URLSearchParams({
            [NOTIFICATION_QUERY_PARAM]: JSON.stringify(parsedRedirectData.message)
        })}`);
    }

    return null
}

export default Page

@mvvmm
Copy link

mvvmm commented Feb 18, 2025

@larsEichler Sure, here you go:

"use client";

export default function Page() {
  useEffect(() => {
    try {
      const returnTo = localStorage.getItem(LOCAL_STORAGE.CUSTOM_REDIRECT_URL);

      if (!returnTo) {
        clientLogout();
        return;
      }

      localStorage.removeItem(LOCAL_STORAGE.CUSTOM_REDIRECT_URL);
      window.location.href = returnTo;
    } catch (error) {
      clientLogout();
    }
  }, []);

  return null;
}

The useEffect with empty dependency array guarantees it only gets ran once, on mount, I think that's your missing piece. The client logouts are basically just redirects to /auth/logout. In any happy path, the user will already be logged out when they reach this page, so those are just fail safes.

I should mention, we have to continue using v3 because of some of the other issues I have open with v4, so we haven't tested this extensively, but hope it helps.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

5 participants