Christos Gkoutzis
Christos Gkoutzis

Reputation: 1

Using decryption with jose in middleware authentication (NextJS14)

I am using middleware to provide authentication/authorization in my NextJS14 app. When I don't have a session the middleware runs properly. However, as soon as I log in I come up with the following error:

Server Error
JWSSignatureVerificationFailed: signature verification failed

This error happened while generating the page. Any console logs will be displayed in the terminal window.
Source
src/session.ts (24:22) @ async decrypt

  22 | export async function decrypt(input: string): Promise<any> {
  23 | console.log('decrypt input:', input)
> 24 | const { payload } = await jwtVerify(input, key, {
     |                    ^
  25 |   algorithms: ["HS256"],
  26 | });
  27 | return payload;

My middleware.ts file:

import { NextRequest, NextResponse } from 'next/server'
import { cookies } from 'next/headers'
import { decrypt } from './session'

// Specify protected and public routes
const sessionProtectedRoutes = ['/verified']
const noSessionProtectedRoutes = ['/login', '/register']
 
export default async function middleware(req: NextRequest) {
  // Check if the current route is protected or public
  const path = req.nextUrl.pathname
  const isSessionProtectedRoute = sessionProtectedRoutes.includes(path)
  const isNoSessionProtectedRoute = noSessionProtectedRoutes.includes(path)
 
  // Decrypt the session from the cookie
  const cookie = cookies().get('session')?.value
  console.log('cookie:', cookie)
  if (cookie){
    const decrypted = await decrypt(cookie);
    const session = JSON.parse(decrypted);
    // Redirect to /login if the user is not authenticated-verified and tries to access a session protected route
    if (isSessionProtectedRoute && session?.role !== 'subscriber') {
      return NextResponse.redirect(new URL('/login', req.nextUrl));
    }
    // Redirect to index route if the user is authenticated and tries to access a no-session protected route
    if (isNoSessionProtectedRoute && session.username) {
      return NextResponse.redirect(new URL('/', req.nextUrl));
    }
  }
  else {
    if (isSessionProtectedRoute){
      return NextResponse.redirect(new URL('/login', req.nextUrl));
    }
  }
  return NextResponse.next()
}
 
// Routes Middleware should not run on
export const config = {
  matcher: ['/((?!api|_next/static|_next/image|favicon.ico|.*\\.png$).*)'],
} 

The decrypt function from jose library that causes the error:

export async function decrypt(input: string): Promise<any> {
  console.log('decrypt input:', input)
  const { payload } = await jwtVerify(input, key, {
    algorithms: ["HS256"],
  });
  return payload;
} 

It's worth noting that I have already checked the authentication flow for passing the expected encrypted/decrypted values when needed and I have already done Postman HTTP requests for proper responses from the headless CMS. So, there is nothing wrong with fetching the token.

Upvotes: 0

Views: 125

Answers (0)

Related Questions