[英]Valid JWT is invalid for nestJS guard
我通過憑據 header 從我的客戶端應用程序(帶有 nextAuth 的nextJS )將 JWT 傳遞給我的后端nestJS 應用程序(使用graphQL)。 在我的nestJS后端應用程序中,我試圖實現一個身份驗證保護,所以我在我的jwt.strategy.ts中使用自定義function提取JWT 。
但是 JwtStrategy 不接受我的有效簽名令牌。 為了證明 JWT 是有效的,我放了一些控制台 output 作為令牌。 但是validate()
function 永遠不會被調用。 我不明白為什么,因為可以使用jwt.verify
驗證令牌:
這是我的 output - 它由jwt.verify()
解碼:
JWT: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyIjp7InVzZXJJZCI6MTIzLCJ1c2VybmFtZSI6InVzZXJuYW1lIiwiaXNBZG1pbiI6dHJ1ZX0sImlhdCI6MTYwOTY3NTc4Nn0.LQy4QSesxJR91PyGGb_0mGZjpw9hlC4q7elIDs2CkLo
Secret: uGEFpuMDDdDQA3vCtZXPKgBYAriWWGrk
Decoded: {
user: { userId: 123, username: 'username', isAdmin: true },
iat: 1609675786
}
我沒有看到,我缺少什么,我什至看不到如何調試它,因為我的 jwt.strategy.ts 中沒有 output 並且根本沒有調用驗證函數。
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' })
我從您的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 function。
所以或者改變你的
const cookieExtractor = async (req) => {
至
const cookieExtractor = (req) => {
或 - 在您調用它時添加等待
jwtFromRequest: await cookieExtractor(),
通過JwtStrategy 構造函數中的文檔示例,他們調用提取器而不是像你一樣傳遞它
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
所以嘗試在你的JwtStrategy 構造函數中調用它
jwtFromRequest: cookieExtractor(), // (again - take care of sync / async)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.