v4: Allow wildcards in returnTo Allowed Logout URLs again
Checklist
- [x] The issue can be reproduced in the nextjs-auth0 sample app (or N/A).
- [x] I have looked into the Readme, Examples, and FAQ and have not found a suitable solution or answer.
- [x] I have looked into the API documentation and have not found a suitable solution or answer.
- [x] I have searched the issues and have not found a suitable solution or answer.
- [x] I have searched the Auth0 Community forums and have not found a suitable solution or answer.
- [x] I agree to the terms within the Auth0 Code of Conduct.
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
- Clone and set up repo
- In auth0 set up a
Regular Web Appwith NextJS as framework - Set
Allowed Callback URLs:http://localhost:3000/auth/callback - Set
Allowed Logout URLs:http://localhost:3000/*/about - Run the application
- Register a new user/Login with the one you already created
- 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
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
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:
-
Add
/logout-redirect-passthroughas an allowed logout url in our auth0 dashboard -
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. -
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
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.
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
@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.
Thats laughable that these hacks needs to be done instead of just supporting:
<protocol>:<domain>/*<----
There is no other way to describe it.
Hi 👋 As per the OAuth 2.1 draft, Redirect URIs must be compared using exact string matching.
To accomodate this, the new strict URI matching was implemented. However, to support backwards compatibility for customers migrating from v3.x.x we are planning to add a constructor parameter which can control which URI matching strategy will be used.
The PR will be up very shortly and we will promptly make a release that should fix this issue for our customers, making the old URI matching strategy an opt-in feature.