Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JS: How to pass url through redirect function to login function

In my React/nextJS application I'm checking for a valid token in the getInitialProps static function. I'm using this as a HOC - but this should not matter in this case.

If the the token is invalid (or missing) the user gets redirected to the login page. This is done by the redirect function as shown below. So far, so good.

How can I pass the url of the page from which the user gets redirected to the login component?

If the user is not logged in and is calling something like http://my-server.com/any-page, he gets redirected to the index page (http://my-server.com): There will be a login form. If the login is successful, I would like to redirect him back to the first called page: http://my-server.com/any-page

  1. Call a restricted page as not logged in user
  2. Redirect to index login page
  3. After login redirect back to the page of 1.

I don't have a clue how to pass this information to the login function...

with-server-props.js

export default WrappedComponent =>
  class extends Component {
    static async getInitialProps (context) {
      const { req, pathname } = context
      let isValid = false

      if (req && req.headers) {
        const cookies = req.headers.cookie
        if (typeof cookies === 'string') {
          const cookiesJSON = jsHttpCookie.parse(cookies)
          initProps.token = cookiesJSON['auth-token']
          if (cookiesJSON['auth-token']) {
            jwt.verify(cookiesJSON['auth-token'], secret, (error, decoded) => {
              if (error) {
                console.error(error)
              } else {
                isValid = true
              }
            })
          }
        }
      }

      // Redirect to index (=login) page if isValid is false
      if (!isValid && pathname && pathname !== '/') {
        redirect(context, pathname ? '/?ref=' + pathname : '/')
      }

      return initProps
    }
    render () {
      return <WrappedComponent {...this.props} />
    }
  }

redirect.js

import Router from 'next/router'

export default (context, target) => {
  if (context.res) {
    // server
    context.res.writeHead(303, { Location: target })
    context.res.end()
  } else {
    // In the browser, we just pretend like this never even happened ;)
    Router.replace(target)
  }
}

pages/index.js

On index.js there is the submit function to login the user. There the user should be redirected to the initial page:

_onSubmit (event) {
  this.props.loginMutation({
    variables: { username, password }
  }).then(response => {
    const token = response.data.token
    if (token) {
      Cookies.set('auth-token', token, { expires: 1 })
      this.props.client.resetStore().then(() => {
        window.location.assign('/') // <-- Redirect to initial called page
      })
    }
  })
}
like image 218
user3142695 Avatar asked Nov 17 '18 21:11

user3142695


1 Answers

In your with-server-props.js replace the path with an URL object

redirect(context, {
    pathname: '/',
    query: { redirect: req.url } // req.url should give you the current url on server side
  })

this will add a redirect param to the url https://example.com/?redirect=/about

then you can get the url params on any page using the getInitialProps:

this.redirectUrl = (req && req.query['redirect']) ? decodeURIComponent(req.query['redirect']) : '/'

finally

window.location.assign(this.redirectUrl)

hope it helps, let me know.

like image 132
Laszlo Avatar answered Nov 15 '22 13:11

Laszlo