4

I have laravel as backend and next.js as frontend of my website. I use laravel sanctum for authentication.

My laravel app and next.js app are in the same host, then I can use session-base sanctum for authentication without use token.

After login there is no problem when I want to access the routes that are protected with middleware aute:sanctum in client side of next.js but in the server side always get error unauthenticated.

This is my axios config and my function for fetch data in next.js:

// axios instance
const axiosInstance = axios.create({
  baseURL: 'localhost:8000',
  withCredentials: true,
  headers: {
    'X-Requested-With': 'XMLHttpRequest',
  },
});

const onRequest = (config) => {
  if ((
    config.method == 'post' ||
    config.method == 'put' ||
    config.method == 'delete'
    /* other methods you want to add here */
  ) &&
    !Cookies.get('XSRF-TOKEN')) {
    return setCSRFToken()
      .then(response => config);
  }
  return config;
}

const setCSRFToken = () => {
  return axiosInstance.get('api/v1/csrf-cookie');
}

// attach your interceptor
axiosInstance.interceptors.request.use(onRequest, null);

// fetch data:

export async function getServerSideProps(context) {

    const { query, req } = context;

    const {
        page,
        search_term,
        nip,
        tableName
    } = query;

    try {
        const response = await ax.post(`api/v1/admin/${tableName}`, { page: page, search_term: search_term, nip: nip || 10 }, {
            withCredentials: true,
            headers: {
                Cookie: req.headers.cookie,
            }
        });

        return {
            props: {
                initItems: response.data.data,
                initMeta: response.data.meta,
                initSearchTerm: search_term || '',
                iniNip: nip || 10
            }
        }
    } catch (err) {
        console.log(err);
        return {
            notFound: true,
        }
    }
}
marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Esmaeil Soomari
  • 130
  • 2
  • 9

1 Answers1

0

I have implemented middleware in nextjs to check if the user logged in and allowed further requests:

Install npm i isomorphic-unfetch

import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';
import fetch from 'isomorphic-unfetch';

export async function middleware(request: NextRequest) {
  const authCookie = request.cookies.get('laravel_session');
  const base = `${request.nextUrl.protocol}//${request.nextUrl.hostname}:${request.nextUrl.port}`;

  const csrfResponse = await fetch(`${process.env.NEXT_PUBLIC_BACKEND_NAMED_URL}/sanctum/csrf-cookie`, {
    method: 'GET',
    headers: {
      'X-Requested-With': 'XMLHttpRequest',
      'Content-Type': 'application/json',
      'Accept': 'application/json',
    },
  });

  if (!csrfResponse.ok || ! authCookie?.value) {
    return NextResponse.redirect(`${base}/login`);
  }

  const response = await fetch(`${base}/api/user`, {
    method: 'GET',
    headers: {
      'X-Requested-With': 'XMLHttpRequest',
      'Content-Type': 'application/json',
      'Accept': 'application/json',
      'Authorization': authCookie.value,
    },
    credentials: 'include',
  });

  if (response.status === 401) {
    return NextResponse.redirect(`${base}/login`);
  }
}

export const config = {
  matcher: ["/((?!register|api|login|manifest|_next|styles|scripts).*)"],
}

There are a couple of nuances here like NEXT_PUBLIC_BACKEND_NAMED_URL and base URL you may not need it it depends on your local dev setup. You can read more about this approach here: https://dev.to/romkecodesome/nextjs-13-app-dir-with-laravel-sanctum-valet-2ih4

RomkaLTU
  • 3,683
  • 8
  • 40
  • 63