2

I understand in the page component I can do something like

if(!isAuthenticated){
    router.replace("/login")
  }

But if 95% of my routes require a login, what's the best way to DRY this up, so I don't have to put this if statement on all my pages. I looked into middleware but because that runs on the server-side, I can't access the app state.

I'm new to React and Nextjs. I come from an angular background where this would be solved with a route guard, is there anything like this in Nextjs?

Deekor
  • 9,144
  • 16
  • 69
  • 121
  • Maybe a `MustBeAuthenticated` [layout](https://nextjs.org/docs/basic-features/layouts) component. – Brian Thompson Jan 31 '22 at 17:47
  • look into the concept of reconciliation in react -- try using a root layout component as Brian suggested. You can access data from the serverside on the client in a strongly typed way (assuming you're using typescript if coming from angular). Import `GetStaticPropsContext` or `GetServerSidePropsContext` as well as `GetStaticPropsResult` or `GetServerSidePropsResult` from next. Then, in the default export of any non _* page, you can infer server props by using another next import `InferGetStaticPropsType` or `InferGetServerSidePropsType` – Andrew Ross Jan 31 '22 at 19:11
  • Does this answer your question (check the client-side solution): [How to create HOC for auth in Next.js?](https://stackoverflow.com/a/70659746/1870780)? – juliomalves Feb 02 '22 at 09:53

2 Answers2

4

You should use Middleware

If your Middleware is created in /pages/_middleware.js, it will run on all routes within the /pages directory.

For more info read the official page

Solution for js

import { NextResponse } from 'next/server'

export async function middleware(req, ev) {
    // req: contains request information

    if (!isAuthenticated()) {
        return NextResponse.redirect('/login');
    }
    return NextResponse.next();
}

Solution for ts

import type { NextFetchEvent, NextRequest } from 'next/server'
import { NextResponse } from 'next/server'

export function middleware(req: NextRequest, ev: NextFetchEvent) {
    if (!isAuthenticated()) {
        return NextResponse.redirect('/login');
    }
    return NextResponse.next();
}
YuryDG
  • 425
  • 3
  • 7
1

You can put your auth code in Higher order component and wrap all your components using this component. You can find complete details here - https://reactjs.org/docs/higher-order-components.html.

A higher-order component (HOC) is an advanced technique in React for reusing component logic. HOCs are not part of the React API, per se. They are a pattern that emerges from React’s compositional nature.

Using HOC for auth sample - https://www.codementor.io/@sahilmittal/using-higher-order-components-for-authenticated-routing-i1hcp6pc6

<Route path="">
    <Route path="/signin" component={SignIn} />
    ...
    <Route path="/app" component={requiresAuth(App)}>
      <Route name="dashboard" path="dashboard" component={Dashboard} />
      <Route name="profile" path="user-profile" component={UserProfile} />
    </Route>
    ...
  </Route>
Santosh Karanam
  • 1,077
  • 11
  • 23