javascript - 使用 'nestjs/jwt' 签名动态/用户相关的 secret

标签 javascript node.js typescript jwt nestjs

我正在尝试根据尝试登录的用户的 secret 创建用户 token 。但是,我不想使用来自环境的 secret ,而是想使用分配给数据库内用户对象的 secret 。

import { Injectable } from '@nestjs/common';
import { JwtService } from '@nestjs/jwt';
import { UserService } from '@src/modules/user/services';

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

  public async createToken(email: string): Promise<JwtReply> {
    const expiresIn = 60 * 60 * 24;
    const user = await this.userService.user({ where: { email } });
    const accessToken = await this.jwtService.signAsync({ email: user.email },
                                                        /* user.secret ,*/
                                                        { expiresIn });

    return {
      accessToken,
      expiresIn,
    };
  }
}

我是 Nestjs 的新手,也许我遗漏了什么。 node-jsonwebtoken确实在 sign(...) 函数中提供了必要的参数。 nestjs/jwt 缺少此参数(参见代码)。如果不使用 node-jsonwebtoken 或更抽象的问题,您将如何解决它:我处理用户 secret 的方式在这里有意义吗?谢谢。

最佳答案

这还不能单独使用 nest 的 JwtModule,但您可以轻松地自己实现缺少的部分。

现场演示

Edit Nest Dynamic JWT Secrets

您可以通过调用以下路由创建 token :

user1( secret :'123'):https://yw7wz99zv1.sse.codesandbox.io/login/1
user2( secret :'456'):https://yw7wz99zv1.sse.codesandbox.io/login/2

然后使用您的 token 调用 protected 路由 '/' 并接收您的用户:

curl -X GET https://yw7wz99zv1.sse.codesandbox.io/ \
      -H 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiIxIiwiaWF0IjoxNTUzNjQwMjc5fQ.E5o3djesqWVHNGe-Hi3KODp0aTiQU9X_H3Murht1R5U'

它是如何工作的?

AuthService 中,我只是使用标准的 jsonwebtoken 库来创建 token 。然后您可以从您的登录路由调用 createToken:

import * as jwt from 'jsonwebtoken';

export class AuthService {
  constructor(private readonly userService: UserService) {}

  createToken(userId: string) {
    const user = this.userService.getUser(userId);
    return jwt.sign({ userId: user.userId }, user.secret, { expiresIn: 3600 });
  }

  // ...
}

JwtStrategy 中,您使用 secretOrKeyProvider 而不是 secretOrKey 可以异步访问 UserService 来获取用户动态 secret :

export class JwtStrategy extends PassportStrategy(Strategy) {
  constructor(
    private readonly authService: AuthService,
    private readonly userService: UserService,
  ) {
    super({
      jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
      secretOrKeyProvider: (request, jwtToken, done) => {
        const decodedToken: any = jwt.decode(jwtToken);
        const user = this.userService.getUser(decodedToken.userId);
        done(null, user.secret);
      },
    });
  }

  // ...
}

请注意,您传递给 JwtModule 的选项(如 expiresIn)将不会被使用,而是直接传递给 AuthService 中的选项。不带任何选项导入 JwtModule:

JwtModule.register({})

一般

Does my way of handling user secret make sense here?

如果不知道您的确切要求,这很难回答。我想 jwt 有一些使用动态 secret 的用例,但是有了它你就失去了 jwt 的一个重要属性:它们是无状态的。这意味着您的 AuthService 可以发布一个 jwt token ,而一些需要身份验证的 ProductService 可以只信任 jwt(它知道 secret )而无需调用其他服务(即UserService 必须查询数据库)。

如果与用户相关的 key 不是硬性要求,请考虑频繁轮换 key ,而不是使用 jwt 的 kid 属性。

关于javascript - 使用 'nestjs/jwt' 签名动态/用户相关的 secret ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55354102/

相关文章:

javascript - 你为什么要 try-catch around 一个 promise?这会捕获 promise 的错误吗?

javascript - 如何解决NodeJs中的嵌套promise?

javascript - Angular Material 2 - 在单元测试的 md-checkbox 中触发更改事件

c# - 类型 null 不可分配给类型 IJobDetails(这是我的接口(interface))

typescript - 在 typescript 中 Jest mock express 和 Mongoose

javascript - 如何将函数内的捕获错误传递给父级

javascript - Google 折线图稍后开始系列

javascript - 如何执行find中的函数或将数据保存在变量中?

node.js - 在node js中读取图像数据并裁剪图像的某些部分

node.js - 默认值Nodejs