在中间件身份验证中使用 jose 解密(NextJS14)

问题描述 投票:0回答:1

我正在使用中间件在我的 NextJS14 应用程序中提供身份验证/授权。当我没有会话时,中间件可以正常运行。然而,我一登录就出现以下错误:

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;

我的

middleware.ts
文件:

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$).*)'],
} 

jose 库中的

decrypt
函数导致错误:

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

值得注意的是,我已经检查了身份验证流程,以便在需要时传递预期的加密/解密值,并且我已经完成了 Postman HTTP 请求,以获得无头 CMS 的正确响应。所以,获取令牌没有任何问题。

typescript authentication next.js middleware jose
1个回答
0
投票

¡你好!有一些不便和解决方案,可以使用 Next 14.2、打字稿和“jose”。 Tengo mi 功能“解密” de la siguiente manera:

import { jwtVerify } from "jose"

const secretKey = 'tu llave secreta'
const encodedKey = new TextEncoder().encode(secretKey)

export async function decrypt(session: string | undefined = '') {
    try {
      const { payload } = await jwtVerify(session, encodedKey, {
        algorithms: ['HS256'],
      })
      return payload
    } catch (error) {
      console.log('Failed to verify session')
    }
  }

我可以使用 utilizarlo en un dal(数据访问层)和 todo está corriendo bien,pero en el archivo middleware me aparece el siguiente 错误:边缘运行时不支持 node.js 'crypto' 模块。

在档案中间件中实现的解决方案:

import { NextRequest, NextResponse } from "next/server";
import { cookies } from "next/headers";
import { jwtVerify } from "jose";

const protectedRoutes = ['/admin']
const publicRoutes = ['/','/galeria','/cuenta']

async function decrypt (jwt : string | undefined = '') {
    const keyEncode =  new TextEncoder().encode(process.env.SESSION_SECRET)
    try {
        const { payload } = await jwtVerify(jwt, keyEncode, {
          algorithms: ['HS256'],
        })
        console.log('middleware', payload)
        return payload
      } catch (error) {
        console.log('Failed to verify session')
      }
}

export async function middleware (req: NextRequest){
    const cookie = cookies().get('tu cookie')?.value
    const path = req.nextUrl.pathname
    const isProtectedRoute = protectedRoutes.includes(path)
    const isPublicRoute = publicRoutes.includes(path)

    const dataSession = await decrypt(cookie)
    
    //AQUÍ HACES TUS VALIDACIONES CON LA VARIABLE 'dataSession'
}

在中间件中可以使用其他功能“解密”。 A cerca de buenaspracticas no creo que sea lo mejor pero fue la única forma en la que me Sirvió.

Espero te Sirva,un saludo。

© www.soinside.com 2019 - 2024. All rights reserved.