Is there a way to pass my middleware.ts const that checks if user is logged in to other api, domain logic or page.tsx?

clock icon

asked 2 months ago

message

0 Answers

eye

5 Views

I'm trying to build an authentication feature for my web app following this online tutorial.

I created the middleware.ts for my web app, and saw that there is a const isLoggedIn so i thought i can use this boolean in every other pages to constantly authenticate if user is logged in.

so i abstracted it out like this

export const checkIsLoggedIn = (req: any): boolean => {
    return !!req.auth;
};

since this is the middleware which is server action, and my components are all client actions, i decided to create an api such that checkisloggedin will be passed from middleware.ts -> check-auth.ts (the api) -> main-nav.tsx (the component i want to use to check if user is logged in).

but when i console.log to see if my api is working, my browser's inspect element console returned this error

[main-nav-tsx][checkAuthStatus]: Error fetching auth status 
SyntaxError: Unexpected token '<', "<!DOCTYPE "... is not valid JSON
window.console.error    @   app-index.js:33

Apparently it meant that my api route wasnt found.

The issue: Im not sure how else i can pass checkisloggedin boolean to my components as every method i tried to check if user is logged in isn't working. all my directories seemed correct too.

Expected outcome: I just need a way to check if user is logged in, and show the signout button as needed.

Im also open to new solutions involving sessions and tokens, but i have no idea how to use any of them.

These are my codes. Since NextJS is particular about file directories, I commented where each file is stored at, at the very top.

// src/middleware.ts

// import { auth } from "./auth"
import authConfig from "./auth.config"
import NextAuth from "next-auth"
import {
    DEFAULT_LOGIN_REDIRECT,
    apiAuthPrefix,
    authRoutes,
    publicRoutes,
} from "@/routes"
import { NextResponse } from "next/server";

const { auth } = NextAuth(authConfig);

export const checkIsLoggedIn = (req: any): boolean => {
    return !!req.auth;
};

export default auth((req) => {
    const { nextUrl } = req;
    const isLoggedIn = !!req.auth;
    console.log('[middleware-ts][checkisloggedin]: ', checkIsLoggedIn(req));
    console.log('[middleware-ts][isloggedin]: ', isLoggedIn);
    const isApiAuthRoute = nextUrl.pathname.startsWith(apiAuthPrefix);
    const isPublicRoute = publicRoutes.includes(nextUrl.pathname);
    const isAuthRoute = authRoutes.includes(nextUrl.pathname);

    if (isApiAuthRoute) {
        return NextResponse.next();
    }

    if (isAuthRoute) {
        if (isLoggedIn) {
            return NextResponse.redirect(new URL(DEFAULT_LOGIN_REDIRECT, nextUrl))
        }
        return NextResponse.next();
    }

    if (!isLoggedIn && !isPublicRoute) {
        return NextResponse.redirect(new URL("/auth/login", nextUrl));
    }
    return NextResponse.next();
})

export const config = {
    // matcher: ["/((?!api|_next/static|_next/image|favicon.ico).*)"],
    // matcher: ["/auth/login", "/auth/register"],
    matcher: ['/((?!.*\\..*|_next).*)', '/', '/(api|trpc)(.*)'],
} 
// src/components/main-nav.tsx

"use client"

import * as React from "react"
import Link from "next/link"
import { usePathname } from "next/navigation"
import { docsConfig } from "@/config/docs"
import { siteConfig } from "@/config/site"
import { cn } from "@/lib/utils"
import { Icons } from "@/components/icons"
import { signOut } from "@/auth"

export function MainNav() {
    const pathname = usePathname()

    const [isLoggedIn, setIsLoggedIn] = React.useState(false);

    React.useEffect(() => {
        const checkAuthStatus = async () => {
            console.log('[main-nav-tsx][checkAuthStatus]: Checking auth status...');
            try {
                const response = await fetch('/app/api/authentication/check-auth');
                if (response.ok) {
                    const data = await response.json();
                    console.log('[main-nav-tsx][checkAuthStatus]: Auth status response:', data);
                    setIsLoggedIn(data.isLoggedIn);
                } else {
                    console.error('[main-nav-tsx][checkAuthStatus]: Error fetching auth status', response.status);
                }
            } catch (error) {
                console.error('[main-nav-tsx][checkAuthStatus]: Error fetching auth status', error);
            }
        }

        checkAuthStatus();
    }, []);

    /**
     * handleSignOut is a server side action to check for log in 
     * main-nav is a client side action 
     * even though the method is post, we cannot use server action for checking if logged in is true or false
     * hence a POST api is needed
     */
    const handleSignOut = async () => {
        const response = await fetch('/app/api/authentication/signout', {
            method: 'POST',
        });
        if (response.ok) {
            // Handle successful sign-out, e.g., redirect or update state
            setIsLoggedIn(false);
        } else {
            // Handle error
            console.error('Error signing out');
        }
    };

    return (
        <div className="mr-4 hidden md:flex">
            <Link href="/" className="mr-6 flex items-center space-x-2">
                <Icons.logo className="h-6 w-6" />
                <span className="hidden font-bold sm:inline-block">
                    {siteConfig.name}
                </span>
            </Link>
            <nav className="flex items-center gap-4 text-sm lg:gap-6">
                {docsConfig.mainNav?.map(item => (
                    item.href && (
                        <Link
                            key={item.href}
                            href={item.href}
                            className={cn(
                                "transition-colors hover:text-foreground/80",
                                pathname === item.href ? "text-foreground" : "text-foreground/60"
                            )}
                        >
                            {item.title}
                        </Link>
                    )
                ))}

                {/* change this button else where */}
                {isLoggedIn && (
                    <button onClick={handleSignOut}>Sign Out</button>
                )}

            </nav>
        </div>
    )
}
// src/app/api/authentication/check-auth.ts

import { NextApiRequest, NextApiResponse } from 'next'
import { checkIsLoggedIn } from '../../../middleware'

export default function handler(req: NextApiRequest, res: NextApiResponse) {
    const isLoggedIn = checkIsLoggedIn(req);
    // console.log("[check-auth-ts]: ", isLoggedIn)
    res.status(200).json({ isLoggedIn });
}

0 Answers

Top Questions