Nextjs redirect in _app.js 'The page isn’t redirecting properly'

Viewed 2143

I am building out the user auth portion of a nextjs app. I have most of it completed save for the protected routes. I am attempting to handle the auth portion in _app.js. Here is the file:

import App from 'next/app'
import '../styles/globals.css'
import { parseCookies } from 'nookies'
import { redirectUser } from '../utils/auth'
import jwt from 'jsonwebtoken'

class MyApp extends App {
  static async getInitialProps({ Component, ctx }) {
    const { token } = parseCookies(ctx)
    
    let pageProps = {}

    if (Component.getInitialProps) {
      pageProps = await Component.getInitialProps(ctx)
    }

    if (!token) {
      const isProtectedRoute = ctx.pathname === '/account'
      if (isProtectedRoute) {
        redirectUser(ctx, '/login')
      }
    } else {
      try {
        const verified = jwt.verify(token, process.env.JWT_SECRET)
      } catch(err) {
        console.error(err)
        redirectUser(ctx, '/login')
      }
    }
    
    return { pageProps }
  }

  render() {
    const { Component, pageProps } = this.props;
    return (
      <Component {...pageProps} />
    )
  }
}

export default MyApp

And my redirectUser file:

import cookie from 'js-cookie';
import Router from 'next/router';

export function handleLogin(token) {
    cookie.set('token', token)
    Router.push('/account');
}

export function redirectUser(ctx, location) {
    if (ctx.req) {
        ctx.res.writeHead(302, { Location: location })
        ctx.res.end()
    } else {
        Router.push(location)
    }
}

The auth portion correctly redirects when a user doesn't have a token but if that token is altered to be invalid I get a redirect error:

The page isn’t redirecting properly

Firefox has detected that the server is redirecting the request for this address in a way that will never complete.

I've confirmed that it is the second redirectUser call that is causing this error. Even if I place it outside of the else conditional at the bottom of the getInitialProps function I get the same result.

1 Answers

You're getting that error because you end up triggering an infinite redirect cycle to the /login page.

Landing on any page with an invalid token will redirect to the /login page. When this redirect happens it will trigger another App.getInitialProps call which will end up causing yet another redirect to the /login page since the token is still invalid, and so on.

You could prevent this behaviour by adding checks when the current page is the /login page. This can be handled in several ways, but I'll leave an example here.

if (!token) {
    const isProtectedRoute = ctx.pathname === '/account'
    if (isProtectedRoute) {
        redirectUser(ctx, '/login')
    }
} else if (ctx.pathname !== "/login") { // To avoid redirect loop
    try {
        const verified = jwt.verify(token, process.env.JWT_SECRET)
    } catch(err) {
        console.error(err)
        redirectUser(ctx, '/login')
    }
}
Related