Nest js 护照 AuthGuard 未验证有效令牌 - 返回“401 未经授权”或“无效签名”

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

使用本地策略生成令牌有效,并且令牌可以使用 JwtService 进行验证

validate(token)
但在使用
@UseGuards(AuthGuard('jwt'))

时则不行

这有效:

// auth.controller.ts
// ...
  @Post(`/verify`)
  async verify(@Request() req, @Headers() headers) {
    const authHeader = headers['authorization'] // manually get the Authorization header value
    const token = authHeader.substring('Bearer '.length) // This will remove the Bearer prefix
    return this.jwtService.verify(token)
  }

这不是:

// auth.controller.ts
// ...
  @UseGuards(AuthGuard('jwt'))
  @Post(`/verify`)
  async verify(@Request() req, @Headers() headers) {
    return(req.user)
  }

秘密已在 jwt 策略配置中正确设置

import { Injectable } from '@nestjs/common'
import { PassportStrategy } from '@nestjs/passport'
import { ExtractJwt, Strategy } from 'passport-jwt'

@Injectable()
export class JwtStrategy extends PassportStrategy(Strategy) {
  constructor() {
    super({
      jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
      ignoreExpiration: false,
      secretOrKey: `${process.env.JWT_SECRET}`,
    })
  }

  async validate(username: string, password: string) {
    return { username, password }
  }
}

以及模块中

// auth.module.ts
// ...

@Module({
  imports: [
    PassportModule.register({ defaultStrategy: 'jwt' }),
    MongooseModule.forFeature([
      {
        name: User.name,
        schema: UserSchema,
      },
    ]),
    JwtModule.register({
      secret: `${process.env.JWT_SECRET}`,
      signOptions: {
        expiresIn: '60d',
      },
    }),
  ],
  controllers: [AuthController],
  providers: [
    AuthService,
    UserService,
    HashService,
    LocalStrategy,
    JwtStrategy,
  ],
})
export class AuthModule {}

最后,当尝试使用自定义

@UseGuards(JwtAuthGuard)
而不是
@UseGuards(AuthGuard('jwt'))
进行处理时,我可以在
canActivate()
中正确读取令牌,但
handleRequest()
(仍然)返回授权并在日志中显示“Jsonwebtokenerror:无效签名”

// jwt-gaurd.ts
import { ExecutionContext, Injectable } from '@nestjs/common'
import { AuthGuard } from '@nestjs/passport'
import { JwtService } from '@nestjs/jwt'

@Injectable()
export class JwtAuthGuard extends AuthGuard('jwt') {
  constructor(private jwtService: JwtService) {
    super({
      secret: `${process.env.JWT_SECRET}`,
      signOptions: {
        expiresIn: '60d',
      },
    })
  }

  async canActivate(context: ExecutionContext) {
    const request = context.switchToHttp().getRequest()
    const token = request.headers.authorization.split(' ')[1]
    try {
      const payload = await this.jwtService.verify(token)
      console.log(payload) // logs correctly
      super.canActivate(context)
      return true
    } catch (error) {
      return false
    }
  }

  async validate(payload: any) {
    return payload
  }

  handleRequest(err, user, info) {
    console.log(err, user, info)
    if (err || !user) {
      return err
    }
    return user
  }
}

如上所示,我尝试在多个位置提取令牌,它正确验证并获取有效负载。

我确保我的导入与有关错误的现有线程保持一致,并记录了秘密以确保它在任何地方都是正确的。

不知道为什么除了守卫装饰器之外,一切都可以按预期工作。任何帮助对我的理智都非常有价值。

authentication jwt nestjs authorization passport.js
2个回答
1
投票

这最终对我有用,Nest 文档现在建议扩展 CanActivate 而不是 AuthGuard('jwt') 来保护端点


0
投票

我遇到了同样的问题,并找到了适合我的具体情况的解决方案。 问题是

jwt.sign(token)
没有使用模块提供的秘密进行签名。 尝试首先在 jwt.io 中创建 jwt 令牌(使用您的 SECRET_TOKEN)进行验证,然后在您的服务中进行验证。如果有效 -> 您的
jwt.verify()
至少可以正常工作。 然后尝试通过调用
jwt.sign(token, {secret: SECRET_TOKEN})
从您的服务生成 jwt 令牌。在 jwt.io 中并通过您的服务验证签名令牌。

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