NestJs JWT 身份验证返回 401

Posted

技术标签:

【中文标题】NestJs JWT 身份验证返回 401【英文标题】:NestJs JWT Authentication returns 401 【发布时间】:2019-09-13 04:37:02 【问题描述】:

我已经在 nestJs 中实现了 jwt 身份验证。但是,每当我尝试使用以下授权标头进行身份验证时:

Bearer <token> or JWT <token>

我得到了 401。这些是我的身份验证文件

@Injectable()
export class JwtStrategy extends PassportStrategy(Strategy, 'jwt') 
  constructor(private readonly authService: AuthService) 
    super(
      jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
      secretOrKey: `$process.env.SECRET`,
    );
  

  async validate(payload: Credentials) 
    const user: Account = await this.authService.validateAccount(payload);
    if (!user) 
      throw new UnauthorizedException();
    
    return user;
  



@Injectable()
export class JwtAuthGuard extends AuthGuard('jwt') 
  canActivate(context: ExecutionContext) 
    return super.canActivate(context);
  

  handleRequest(err, user, info) 
    if (err || !user) 
      throw err || new UnauthorizedException();
    
    return user;
  

这是我的身份验证模块

@Module(
  imports: [
    PassportModule.register( defaultStrategy: 'jwt' ),
    JwtModule.register(
      secretOrPrivateKey: `$process.env.SECRET`,
    ),
    AccountModule,
  ],
  providers: [AuthService, JwtStrategy],
  controllers: [AuthController],
  exports: [PassportModule, AuthService],
)
export class AuthModule 


【问题讨论】:

您能在authService.validateAccount 中添加console.log 吗?它被称为?它是否返回一个真实的值? 令我惊讶的是它没有被调用。 @Arsene 这对你有用吗,我遇到了同样的问题,registerAsync 由于某种原因不起作用。但是 register 方法有效 【参考方案1】:

validate 只会在您传递有效的 jwt 令牌时被调用。当令牌使用不同的秘密签名或过期时,validate 将永远不会被调用。确保您拥有有效的令牌。例如,您可以使用jwt debugger 检查您的令牌。

【讨论】:

令牌有效。但是我仍然收到 401。我怎么知道 Nestjs 管道中的问题在哪里? 您已经扩展了AuthGuard,因此您可以将console.log 语句添加到它的方法中。您还可以在库代码中设置断点并进行调试。 由于您似乎使用的几乎都是标准设置,我不这么认为,不。正如您所说,您的令牌没有过期并且使用正确的秘密签名,它仍然可能是错误的标头格式,版本冲突,...... 您好 NestJs 极客,请帮我解决这个问题。我已经和这个斗争了一段时间了。没有解决方案。 您必须提供更多信息,例如日志等或在codesandbox.io上创建可重现的版本【参考方案2】:

我遇到了类似的问题,nestjs 护照 jwt 模块在我的本地机器上运行良好,但在实时服务器上无法运行。经过半天的研究,我发现我的令牌头没有到达实时服务器,原因是我在实时服务器上使用了 nginx(proxy_pass)并且我的头字段名称是“access_token”所以出于某种原因 nginx 删除了它.

制作一个简单的全局中间件并检查您是否在标头中接收到令牌。

希望对某人有所帮助。

【讨论】:

【参考方案3】:

我遇到了同样的问题。这是我的代码(工作)供您比较:

src/auth/auth.module.ts

import  Module  from '@nestjs/common';
import  JwtModule  from '@nestjs/jwt';
import  AuthService  from './auth.service';
import  JwtStrategy  from './jwt.strategy';
import  UserModule  from 'src/user/user.module';
import  PassportModule  from '@nestjs/passport';

@Module(
  imports: [
    PassportModule.register( defaultStrategy: 'jwt' ),
    JwtModule.register(
      secretOrPrivateKey: 'secretKey',
      signOptions: 
        expiresIn: '1d',
      ,
    ),
    UserModule,
  ],
  providers: [AuthService, JwtStrategy],
  exports: [PassportModule, AuthService],
)
export class AuthModule 

src/auth/auth.service.ts

import  Injectable  from '@nestjs/common';
import  JwtService  from '@nestjs/jwt';
import  JwtPayload  from './interfaces/jwt-payload.interface';
import  UserService  from 'src/user/user.service';

@Injectable()
export class AuthService 
  constructor(
    private readonly jwtService: JwtService,
    private readonly userService: UserService,
  ) 

  makeToken(payload: JwtPayload) 
    const  email  = payload;
    return this.jwtService.sign( email );
  

  checkToken(token: string) 
    return this.jwtService.verify(token);
  

  async validateUser(payload: JwtPayload) 
    return await this.userService.read(payload.email);
  

src/auth/jwt.strategy.ts

import  Strategy, ExtractJwt, VerifiedCallback  from 'passport-jwt';
import  AuthService  from './auth.service';
import  PassportStrategy  from '@nestjs/passport';
import  Injectable, UnauthorizedException  from '@nestjs/common';
import  JwtPayload  from './interfaces/jwt-payload.interface';

@Injectable()
export class JwtStrategy extends PassportStrategy(Strategy) 
  constructor(private readonly authService: AuthService) 
    super(
      jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
      secretOrKey: 'secretKey',
    );
  

  async validate(payload: JwtPayload, done: VerifiedCallback) 
    const user = await this.authService.validateUser(payload);
    if (!user) 
      done(new UnauthorizedException(), false);
    
    return done(null, user);
  

src/auth/interfaces/jwt-payload.interface.ts

export interface JwtPayload 
  email: string;

src/account/account.module.ts

import  Module  from '@nestjs/common';
import  AccountController  from './account.controller';
import  PassportModule  from '@nestjs/passport';
import  AuthModule  from 'src/auth/auth.module';

@Module(
  imports: [AuthModule],
  controllers: [AccountController],
)
export class AccountModule 

src/account/account.controller.ts

import  Controller, UseGuards, Post  from '@nestjs/common';
import  AuthGuard  from '@nestjs/passport';

@Controller('account')
export class AccountController 
  @Post('skills')
  @UseGuards(AuthGuard())
  updateSkills() 
    return console.log('something');
  

P.S.:我没有做 JwtAuthGuard。

希望对你有所帮助:)

【讨论】:

我不确定发生了什么,但它不起作用。【参考方案4】:

您可以查看带有护照和 NestJS 的最小工作示例

https://github.com/leosuncin/nest-auth-example

与您的代码的主要区别:

@Module(
  imports: [
    PassportModule.register( defaultStrategy: 'jwt' ), // I don't do this because I explicity call every stratategy
    JwtModule.register(
      secretOrPrivateKey: 'secretKey',
      signOptions: 
        expiresIn: '1d',
      ,
    ),
    UserModule,
  ],
  providers: [AuthService, JwtStrategy],
  exports: [PassportModule, AuthService], // I don't do this
)

我不使用任何JwtAuthGuard,只使用默认的。

【讨论】:

【参考方案5】:

我遇到了这个问题,我解决了。 只需删除 $procces.env.JWT_SECRET 并执行其他操作,例如异步注册,我不知道为什么,但它可以工作。

【讨论】:

以上是关于NestJs JWT 身份验证返回 401的主要内容,如果未能解决你的问题,请参考以下文章

JWT 身份验证始终返回 401 HTTP 错误 asp.net core

Nest.js Auth Guard JWT 身份验证不断返回 401 未授权

使用 JWT 处理 401(未授权)angularjs 身份验证

NestJS jwt-passport 身份验证

NestJs 使用 jwt 和私钥和公钥进行身份验证

nestjs 中的可选身份验证