有效的 JWT 对 NestJS 守卫无效
Posted
技术标签:
【中文标题】有效的 JWT 对 NestJS 守卫无效【英文标题】:Valid JWT is invalid for nestJS guard 【发布时间】:2021-04-08 01:54:45 【问题描述】:我通过凭据标头从我的客户端应用程序(带有nextAuth 的nextJS)向我的后端nestJS 应用程序(使用graphQL)传递一个JWT。在我的 nestJS 后端应用程序中,我正在尝试实现身份验证保护,因此我在 jwt.strategy.ts
中使用自定义函数提取 JWT但是 JwtStrategy 不接受我的有效签名令牌。为了证明 JWT 是有效的,我为令牌放置了一些控制台输出。但是永远不会调用 validate()
函数。我不明白为什么,因为可以使用jwt.verify
验证令牌:
这是我的输出 - 它被jwt.verify()
解码:
JWT: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyIjp7InVzZXJJZCI6MTIzLCJ1c2VybmFtZSI6InVzZXJuYW1lIiwiaXNBZG1pbiI6dHJ1ZX0sImlhdCI6MTYwOTY3NTc4Nn0.LQy4QSesxJR91PyGGb_0mGZjpw9hlC4q7elIDs2CkLo
Secret: uGEFpuMDDdDQA3vCtZXPKgBYAriWWGrk
Decoded:
user: userId: 123, username: 'username', isAdmin: true ,
iat: 1609675786
我没有看到,我缺少什么,我什至看不到如何调试它,因为我的 jwt.strategy.ts 中没有输出,并且根本没有调用 validate-function。
jwt.strategy.ts
import jwt from 'jsonwebtoken'
// import JwtService from '@nestjs/jwt'
import Strategy from 'passport-jwt'
import PassportStrategy from '@nestjs/passport'
import Injectable from '@nestjs/common'
import cookie from 'cookie'
import getConfig from '@myapp/config'
const secret = getConfig()
const parseCookie = (cookies) => cookie.parse(cookies || '')
const cookieExtractor = async (req) =>
let token = null
if (req?.headers?.cookie)
token = parseCookie(req.headers.cookie)['next-auth.session-token']
// output as shown above
console.log('JWT:', token)
console.log('Secret:', secret)
const decoded = await jwt.verify(token, secret, algorithms: ['HS256'] )
console.log('Decoded: ', decoded)
return token
@Injectable()
export class JwtStrategy extends PassportStrategy(Strategy)
constructor()
super(
jwtFromRequest: cookieExtractor,
ignoreExpiration: true,
secretOrKey: secret
)
async validate(payload: any)
console.log('payload:', payload) // is never called
return userId: payload.sub, username: payload.username
jwt-auth.guard.ts
import Injectable, ExecutionContext from '@nestjs/common'
import AuthGuard from '@nestjs/passport'
import GqlExecutionContext from '@nestjs/graphql'
@Injectable()
export class GqlAuthGuard extends AuthGuard('jwt')
getRequest(context: GqlExecutionContext)
const ctx = GqlExecutionContext.create(context)
return ctx.getContext().req
在这个解析器中使用了守卫:
editor.resolver.ts
import Query, Resolver from '@nestjs/graphql'
import UseGuards from '@nestjs/common'
import GqlAuthGuard from '../auth/jwt-auth.guard'
@Resolver('Editor')
export class EditorResolvers
constructor(private readonly editorService: EditorService)
@UseGuards(GqlAuthGuard)
@Query(() => [File])
async getFiles()
return this.editorService.getFiles()
auth.module.ts
import Module from '@nestjs/common'
import AuthController from './auth.controller'
import AuthService from './auth.service'
import PassportModule from '@nestjs/passport'
import LocalStrategy from './local.strategy'
import JwtStrategy from './jwt.strategy'
import UsersModule from '../users/users.module'
import JwtModule from '@nestjs/jwt'
import getConfig from '@myApp/config'
const secret = getConfig()
@Module(
imports: [
UsersModule,
PassportModule.register( defaultStrategy: 'jwt' ),
JwtModule.register(
secret,
verifyOptions: algorithms: ['HS256'] ,
signOptions: expiresIn: '1d'
)
],
controllers: [AuthController],
providers: [AuthService, JwtStrategy, LocalStrategy],
exports: [AuthService]
)
export class AuthModule
令牌是在服务器端(nextJS api 页面)创建的:
const encode = async ( secret, token ) => jwt.sign(token, secret, algorithm: 'HS256' )
【问题讨论】:
【参考方案1】:我从您的 jwt.strategy.ts 文件中看到与 nestJS 文档示例的 2 个不同之处,您可以更改并试一试。
https://docs.nestjs.com/security/authentication#implementing-passport-jwt
-
同步提取器而非异步
默认情况下,passport-jwt 提取器我们可以看到这是一个同步而不是异步,因此您可以尝试更改您的提取器并删除异步,或者在调用它时添加等待。
https://github.com/mikenicholson/passport-jwt/blob/master/lib/extract_jwt.js , 寻找 fromAuthHeaderAsBearerToken 函数。
所以或改变你的
const cookieExtractor = async (req) =>
到
const cookieExtractor = (req) =>
或者 - 当你调用它时添加等待
jwtFromRequest: await cookieExtractor(),
-
调用提取器而不只是传递它
通过 JwtStrategy 构造函数中的文档示例,他们调用了提取器,而不是像你那样传递它
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
所以尝试在你的 JwtStrategy 构造函数中调用它
jwtFromRequest: cookieExtractor(), // (again - take care of sync / async)
【讨论】:
哇,谢谢。前几天没看到谢谢你的好收获。只是第一点做到了。传递函数是可以的,你不必调用它。我只需要删除async
以上是关于有效的 JWT 对 NestJS 守卫无效的主要内容,如果未能解决你的问题,请参考以下文章
我需要帮助来验证 jwt 是不是有效或以其他方式创建一个新的,如果发送的令牌不正确,则在 nestjs 中间件中返回错误
我在我的 nestJS 应用程序(使用 authGuard)中使用了 passport-jwt 身份验证策略,如何访问我的控制器中的令牌有效负载?