Next.js Discord

Discord Forum

Middleware auth

Answered
MarkMiklos posted this in #help-forum
Open in Discord
Avatar
I am totally new in this middleware part, so basically my app is multi language using next-intl.
mydomain.hu/hu/admin and everything beyond that should be a protected route.
I managed to match /admin and whenever my session is not available it does redirect to mydomain.hu, but for the other pages such as /admin/profile it doesn't.

Is my middleware even correct, or I'm completely on a wrong path here?

Here's my code:

middleware.ts
import createIntlMiddleware from 'next-intl/middleware';
import { locales } from "@/navigation";
import {NextRequest, NextResponse} from "next/server";
import {getSession} from "@/auth";

const intlMiddleware = createIntlMiddleware({
    locales,
    defaultLocale: 'hu',
});

const protectedRoutes = ['/admin']

export default async function middleware(req: NextRequest) {
    const session = await getSession();
    const protectedPathnameRegex = RegExp(
        `^(/(${locales.join('|')}))?(${protectedRoutes
            .flatMap((p) => (p === '/' ? ['', '/'] : p))
            .join('|')})/?$`,
        'i'
    );

    console.log(protectedPathnameRegex)
    const isProtectedPage = protectedPathnameRegex.test(req.nextUrl.pathname);

    if (!session && isProtectedPage) {
        const absoluteURL = new URL("/", req.nextUrl.origin);
        return NextResponse.redirect(absoluteURL.toString());
    } else {
        return intlMiddleware(req);
    }
}

export const config = {
    // Match only internationalized pathnames
    matcher: ['/', '/admin', '/client', '/(hu|en)/:path*']
};

My auth.ts is just a basic login that sets a token in cookies and the getSession that is called in middleware is checking the cookies for a token and returns a boolean

Any good and bad criticism accepted about my workaround
Image
Answered by MarkMiklos
I have removed the protectedRoutes array and the protectedPathnameRegex and added a pathname split, and then if that array contains 'admin' then it is a protectedPage.

Not the most beautiful approach, but works, should I do some workaround, or it shuld do the job?

import createIntlMiddleware from 'next-intl/middleware';
import { locales } from "@/navigation";
import {NextRequest, NextResponse} from "next/server";
import {getSession} from "@/auth";

const intlMiddleware = createIntlMiddleware({
    locales,
    defaultLocale: 'hu',
});

export default async function middleware(req: NextRequest) {
    const session = await getSession();

    const isProtectedPage = req.nextUrl.pathname.split('/').includes('admin')

    if (!session && isProtectedPage) {
        const absoluteURL = new URL("/", req.nextUrl.origin);
        return NextResponse.redirect(absoluteURL.toString());
    } else {
        return intlMiddleware(req);
    }
}

export const config = {
    // Match only internationalized pathnames
    matcher: ['/', '/admin', '/client', '/(hu|en)/:path*', '/admin/:path*']
};
View full answer

9 Replies

Avatar
🆙
Avatar
hi try to add this to the matcher array
export const config = {
    // Match only internationalized pathnames
    matcher: ['/', '/admin', '/client', '/(hu|en)/:path*', '/admin/:path*']
};
Avatar
it didn't solve the issue, how exactly the matcher works? i have defined a protected route /admin and checking with regexp for locale also, does the matcher checks for the routes here as well ? In my understanding the matcher is because of the internationalization? Correct me out please because I'm confused now 😄
Avatar
I think you need to change this too
const isProtectedPage = protectedRoutes.some(route => route.startWith(req.nextUrl.pathname); 
Avatar
I have to use the regex also
const protectedPathnameRegex = RegExp(
        `^(/(${locales.join('|')}))?(${protectedRoutes
            .flatMap((p) => (p === '/' ? ['', '/'] : p))
            .join('|')})/?$`,
        'i'
    );


because this matches my locale, and without the locale it doesn't work, and also this "startWith" isn't a valid function
Avatar
oh it should be startsWith()
Avatar
I have removed the protectedRoutes array and the protectedPathnameRegex and added a pathname split, and then if that array contains 'admin' then it is a protectedPage.

Not the most beautiful approach, but works, should I do some workaround, or it shuld do the job?

import createIntlMiddleware from 'next-intl/middleware';
import { locales } from "@/navigation";
import {NextRequest, NextResponse} from "next/server";
import {getSession} from "@/auth";

const intlMiddleware = createIntlMiddleware({
    locales,
    defaultLocale: 'hu',
});

export default async function middleware(req: NextRequest) {
    const session = await getSession();

    const isProtectedPage = req.nextUrl.pathname.split('/').includes('admin')

    if (!session && isProtectedPage) {
        const absoluteURL = new URL("/", req.nextUrl.origin);
        return NextResponse.redirect(absoluteURL.toString());
    } else {
        return intlMiddleware(req);
    }
}

export const config = {
    // Match only internationalized pathnames
    matcher: ['/', '/admin', '/client', '/(hu|en)/:path*', '/admin/:path*']
};
Answer
Avatar
look good
Avatar
lovely, thanks for your time.