I am trying to preserve the originally requested route after authentication
While searching for ‘prior art’ I see that this may be in .38 ?
redwoodjs:main
← dthyresson:dt-auth0-login-redirect
opened 02:24PM - 22 Jul 20 UTC
# Overview
See: https://community.redwoodjs.com/t/accessing-the-target-url-from… -the-unauthenticated-redirect/913
# Background
bennet asked the RW Community
> Would it be possible to add the ability to access the url the user was trying to reach if they are blocked by a Private route? It would be nice if there was an easy way to redirect the user back to the url they were trying to access once they successfully authenticate. Even if we just had access to the name of the original target url after being redirected to the unauthenticated route I think that would be enough.
# Proposed Solution
I found that
https://community.redwoodjs.com/t/accessing-the-target-url-from-the-unauthenticated-redirect/913/9
* the Auth0 client `restoreAuthState` already had a mechanism in place to redirect to a `targerUrl`, it simply needed to. be set as part of the `appState` when
```
await logIn({
appState: { targetUrl: searchParams.get('redirectTo') },
})
```
* @peterp suggested
> What if we added it as a query part to the url? http://localhost:8910/login/?redirectTo=/admin/ (escaped)
* so, have added `redirectTo` to the Router and PrivatePageLoader
Now using Auth0:
1. As a not logged in user
2. Visit private route, say `/profile`
3. Get redirected to the `unauthenticatedRoute`: `http://localhost:8910/` (aka `home`)
4. This appends the denied route into the search component of the url querystring
`http://localhost:8910/?redirectTo=/profile`
5. Login and set the `targetUrl`
```js
<Button
onClick={async () => {
if (isAuthenticated) {
await logOut({ returnTo: process.env.AUTH0_REDIRECT_URI })
} else {
const searchParams = new URLSearchParams(window.location.search)
await logIn({
appState: { targetUrl: searchParams.get('redirectTo') },
})
}
}}
>
{isAuthenticated ? 'Log out' : 'Log in'}
</Button>
```
5. On successful login, now directed to the /profile route/page (not the default set in client config, aka the callback)
# Considerations
* I want to add test(s)
* `<Redirect to={`${unauthenticatedRoute()}?redirectTo=${redirectTo}`} />` is a little ugly
* Not sure how will/can be implemented with other clients than Auth0, but probably `fetch path` and `navigate(redirectUrl)`
Looking for feedback. Thanks.
I didn’t quite understand how to use it, and don’t know if it could be used with the ‘dbAuth’ setup
I’d welcome any tips!
Al;
What you’re after should be set up by default. If you go to a private page, and have your login page setup as the unauthenticated page, it should add a redirectTo
query parameter with the route of that private page. Once you login, RW will take care of sending you to that page.
I’m using the scaffolded login page, which routes the user to home on authentication
So I adapted it to use the search by pulling it with useLocation
scaffolded:
const { isAuthenticated, logIn } = useAuth()
useEffect(() => {
if (isAuthenticated) {
navigate(routes.home())
}
}, [isAuthenticated])
adapted:
const { search } = useLocation()
const { isAuthenticated, logIn } = useAuth()
useEffect(() => {
if (isAuthenticated) {
if (/redirectTo/.test(search)) {
const newPath = search.split('=').slice(-1).join()
navigate(newPath)
} else {
navigate(routes.home())
}
}
}, [isAuthenticated])
2 Likes
Could you share the full component where this is used?
The redirectTo is being added nicely to the search string when my users get redirected because they are not authorized. That does allow me to make things work the way I need them to work.
I’m considering it Works As Designed
My users can try for one of two registration pages, if someone arrives at my home page with a redirectTo in their search string I save that in their localStorage. When someone arrives at my post login page with a localStorage item of redirect, then I route them to the page they had originally intended to visit.
I use the local storage because my login is spread over two pages and I use the search string during the login process.
If I am still able to help you please do reply, otherwise I do consider this issue solved.
I might be missing something so I’ll play with it a bit more. The redirectTo is appearing in the url but I’m not being redirected on login. I think I need to explicitly pull the redirect and put it in the navigate function
Tobbe
December 6, 2021, 2:34pm
7
Yes, you have to do it yourself. It’s not supposed to do it for you
2 Likes
I used this in my login page
useEffect(() => {
if (isAuthenticated) {
if (/redirectTo/.test(search)) {
const continueYourJourney = search.replace('redirectTo=','')
navigate(continueYourJourney)
}
}
}, [isAuthenticated])
awesome, this inspired me to write a custom hook useAuthWithRedirectTo()
that wraps useAuth
and can be used on any page that needs access to redirect
// useAuthWithRedirectTo.ts
import { useEffect } from 'react'
import { navigate, routes, useLocation } from '@redwoodjs/router'
import { useAuth } from '@redwoodjs/auth'
export const useAuthWithRedirectTo = () => {
const { search } = useLocation()
const { isAuthenticated, ...rest } = useAuth()
const hasRedirectTo = /redirectTo/.test(search)
const redirectTo = search
.replace('?redirectTo=', '')
.replace(/&\S+=\S[&^]/g, '') // get rid of any other query params
useEffect(() => {
if (isAuthenticated) {
if (hasRedirectTo) {
navigate(redirectTo)
} else {
navigate(routes.home())
}
}
}, [isAuthenticated, hasRedirectTo, redirectTo, search])
return { ...rest, isAuthenticated, redirectTo }
}
I’m using it in both my signup and login pages like this, so i can pass the redirect onto login or signup page, respectively:
// LoginPage.tsx
import { useAuthWithRedirectTo } from '../../hooks/useAuthWithRedirectTo'
const LoginPage = () => {
const { redirectTo, logIn } = useAuthWithRedirectTo()
//...
return (
{/*...*/}
<Link
to={routes.signup(redirectTo ? { redirectTo } : undefined)}
>
Sign up
</Link>
{/*...*/}
)
4 Likes
Tobbe
March 20, 2025, 9:13am
10
Super old thread, but the best way to do this now, three years later, is to use URLSearchParams
export const useAuthWithRedirectTo = () => {
const { search } = useLocation()
const { isAuthenticated, ...rest } = useAuth()
const redirectTo = new URLSearchParams(search).get('redirectTo')
useEffect(() => {
if (isAuthenticated) {
navigate(redirectTo || routes.home())
}
}, [isAuthenticated, redirectTo])
return { ...rest, isAuthenticated, redirectTo }
}