[solved] dbAuth & login redirect

I am trying to preserve the originally requested route after authentication

While searching for ‘prior art’ I see that this may be in .38 ?

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

Yes, you have to do it yourself. It’s not supposed to do it for you :slight_smile:

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