Next.js How to protect my website routes to authenticated users with NextAuth

Issue

I want to protect all routes from my NextJs website to authenticated users with NextAuth except the login route that can be accessed with being authenticated, I tried making a middleware that checks for user token, and redirect them to the login route if it was unavailable. but a general middleware for that would stop the website from getting public files so i came up with this:

// middleware.js

import { NextResponse } from 'next/server';
import { getToken } from 'next-auth/jwt'


export default async function middlware(req) {
    // ignoring file system and public folder
    if (req.nextUrl.pathname.startsWith('/_next/') ||
        req.nextUrl.pathname.startsWith('/icons/') ||
        req.nextUrl.pathname.startsWith('/fonts/')) {
        return;
    }

    // igonring api/auth
    if (req.nextUrl.pathname.startsWith('/api/auth')) {
        return;
    }

    // user session
    const session = await getToken({ req })

    // redirecting to homepage if a logged in user tries to access the login page
    if (req.nextUrl.pathname.startsWith('/auth/login')) {
        if (session) {
            const url = req.nextUrl.clone()
            url.pathname = '/'
            return NextResponse.redirect(url)
        }
    }

    // // redirecting to login page if not logged in
    if (!req.nextUrl.pathname.startsWith('/auth/login')) {
        if (!session && session == null) {
            const url = req.nextUrl.clone()
            url.pathname = '/auth/login'
            return NextResponse.redirect(url)
        }
    }
}

this works for general routes, but when I try to fetch some data in other pages from other API routes I get this error:

FetchError: invalid json response body at http://localhost:3000/auth/login reason: Unexpected token < in JSON at position 0
    at E:\0 - WEB\xwendkaran-admin\node_modules\next\dist\compiled\node-fetch\index.js:1:51227   
    at processTicksAndRejections (node:internal/process/task_queues:96:5)
    at async getServerSideProps (webpack-internal:///./src/pages/departments-marking.js:70:22)   
    at async Object.renderToHTML (E:\0 - WEB\xwendkaran-admin\node_modules\next\dist\server\render.js:490:20)
    at async doRender (E:\0 - WEB\xwendkaran-admin\node_modules\next\dist\server\base-server.js:908:38)
    at async cacheEntry.responseCache.get.isManualRevalidate.isManualRevalidate (E:\0 - WEB\xwendkaran-admin\node_modules\next\dist\server\base-server.js:1013:28)
    at async E:\0 - WEB\xwendkaran-admin\node_modules\next\dist\server\response-cache.js:69:36 { 
  type: 'invalid-json'
}

this error only occurs because of the middleware and if i remove the middle everything works but that means anyone can access the website and also post data to the server

Solution

The problem occurred because when I was trying to fetch data from an API route there was no cookie with the request headers, and !session && session == null would stop it because it showed as not authenticated, so I fixed it with adding user cookies with request headers while fetching the data, like this:

export async function getServerSideProps({ req }) {

    try {
        // fetching centers
        const data = await fetch(`${server}/api/API-ROUTE`, {
            method: 'GET',
            headers: {
                'cookie': req.headers.cookie, // this is where I parsed the cookies
                'Content-Type': 'application/json',
                'Accept': 'application/json'
            },
        }).then(res => res.json())

        return {
            props: {
                data
            }
        }
    }
    catch (error) {
        console.log(error.message)
        return {
            props: {}
        }
    }
}

Answered By – Rawand

This Answer collected from stackoverflow, is licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply

(*) Required, Your email will not be published