Created
June 15, 2023 19:53
-
-
Save 7iomka/53fb757e7d2993b5e5dee82e0f25e4df to your computer and use it in GitHub Desktop.
next.js middleware
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { NextResponse } from 'next/server'; | |
import type { NextRequest } from 'next/server'; | |
import { appConfig } from '@appns/config/app'; | |
import { routes, isAuthRoute, isProtectedRoute, isAdminRoute } from '@/shared/routes'; | |
const redirectTo = ( | |
request: NextRequest, | |
to: string, | |
includeFrom = false, | |
includeReset = false, | |
) => { | |
const toUrl = new URL(to, request.url); | |
if (includeFrom) { | |
toUrl.searchParams.set('from', request.nextUrl.pathname); | |
} | |
if (includeReset) { | |
toUrl.searchParams.set('reset', 'true'); | |
} | |
return NextResponse.redirect(toUrl); | |
}; | |
type ResponsePartial = { isAdming?: true; [key: string]: any }; | |
export function parseJwt(token: string): ResponsePartial | null { | |
try { | |
return JSON.parse(atob(token.split('.')[1])); | |
} catch (e) { | |
return null; | |
} | |
} | |
export async function middleware(request: NextRequest) { | |
// Setting cookies on the response | |
const response = NextResponse.next(); | |
const pth = request.nextUrl.pathname; | |
const isProtectedPath = isProtectedRoute(pth); | |
const isAuthPath = isAuthRoute(pth); | |
const isAdminPath = isAdminRoute(pth); | |
// skip public routes, except auth routes | |
if (!isProtectedPath && !isAuthPath) { | |
return response; | |
} | |
// Getting cookies from the request | |
const token = request.cookies.get(appConfig.authKeys.token); | |
// If user is authorized - disallow public auth pages | |
if (!!token && isAuthPath) { | |
return redirectTo(request, routes.account.main); | |
} | |
// If token isn't present, redirect to login | |
if (!token && isProtectedPath) { | |
return redirectTo(request, routes.login, true, true); | |
} | |
const parsedToken = token ? (parseJwt(token.value) as ResponsePartial) : null; | |
// Hanlde paths allowed only for admin (isAdmin flag from token) | |
if (isAdminPath && !parsedToken?.isAdmin) { | |
return redirectTo(request, token ? routes.account.main : routes.login, !token, !token); | |
} | |
return response; | |
} | |
export const config = { | |
matcher: [ | |
/** | |
* Match all request paths except for the ones starting with: | |
* - api (API routes) | |
* - _next/static (static generated files) | |
* - _next/image (image optimization files) | |
* - favicon.ico (favicon file) | |
* - static (static files in public folder) | |
*/ | |
'/((?!api|_next/static|_next/image|favicon.ico|static|shapes).*)', | |
], | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment