NestJS:使用JWT向AuthGuard添加验证选项 [英] NestJS: Adding verification options to AuthGuard with JWT

查看:1798
本文介绍了NestJS:使用JWT向AuthGuard添加验证选项的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正试图在 AuthGuard 装饰器和护照JWT策略技术/认证rel =nofollow noreferrer>文档

I am trying to make use of the AuthGuard decorator, and the passport JWT strategy, following the documentation.

文档中的所有内容都很有效。但我现在想要保护一个包含在JWT中的范围的路线。所以这是我的应用程序生成的基本jwt有效负载:

Everything in the documentation works great. But I now want to protect a route with a scope contained in the JWT. So here is a basic jwt payload generated by my application:

{
  "user": {
    "id": "20189c4f-1183-4216-8b48-333ddb825de8",
    "username": "user.test@gmail.com"
  },
  "scope": [
    "manage_server"
  ],
  "iat": 1534766258,
  "exp": 1534771258,
  "iss": "15f2463d-8810-44f9-a908-801872ded159",
  "sub": "20189c4f-1183-4216-8b48-333ddb825de8",
  "jti": "078047bc-fc1f-4c35-8abe-72834f7bcc44"
}

这是受 AuthGuard保护的基本受保护路线装饰者:

@Get('protected')
@UseGuards(AuthGuard('jwt'))
async protected(): Promise<string> {
    return 'Hello Protected World';
}

我想添加选项并限制该路线对人们的访问将 manager_server 范围纳入其JWT。所以在阅读了一些 AuthGuard 代码之后,我认为我能写出如下内容:

I would like to add options and restrict the access of that route to the people having the manager_server scope into their JWT. So after reading a little bit of the AuthGuard code, I thought that I was able to write something like:

@Get('protected')
@UseGuards(AuthGuard('jwt', {
    scope: 'manage_server'
}))
async protected(): Promise<string> {
    return 'Hello Protected World';
}

但是,我无法在文档中看到我可以使用这个选项。

我认为在验证函数中添加一个选项参数 JWTStrategy 可以成功,但事实并非如此。这是我的验证函数(包含在 jwt.strategy.ts 文件中):

I thought that adding an option argument to the validate function of the JWTStrategy could make the trick, but it does not. Here is my validate function (contained in the jwt.strategy.ts file):

async validate(payload: JwtPayload, done: ((err: any, value: any) => void)) {
    const user = await this.authService.validateUser(payload);
    if (!user) {
        return done(new UnauthorizedException(), false);
    }
    done(null, user);
}

非常感谢你的帮助,不要犹豫,问我如果你需要,可以在评论中添加更多信息。

Thank you very much for your help and don't hesitate to ask me for more informations in the comments if you need so.

推荐答案

当你看到代码,好像是 options.callback 函数是唯一可能的自定义。

When you look at the code of the AuthGuard, it seems like the options.callback function is the only possible customization.

我认为不是编写自己支持的 AuthGuard 范围检查,有一个 ScopesGuard (或 RolesGuard )和它自己的decorater如 @Scopes('manage_server')代替。为此,您可以按照 docs中的 RolesGuard 示例进行操作,它还只检查请求中用户属性下JWT有效负载的属性。

I think instead of writing your own AuthGuard that supports scope checks, it is cleaner to have a ScopesGuard (or RolesGuard) with its own decorater like @Scopes('manage_server') instead. For this, you can just follow the RolesGuard example in the docs, which also just checks an attribute of the JWT payload under the user property in the request.

创建 @Scopes()装饰者:

export const Scopes = (...scopes: string[]) => ReflectMetadata('scopes', scopes);

创建 ScopesGuard

@Injectable()
export class ScopesGuard implements CanActivate {
  constructor(private readonly reflector: Reflector) {}

  canActivate(context: ExecutionContext): boolean {
    const scopes = this.reflector.get<string[]>('scopes', context.getHandler());
    if (!scopes) {
      return true;
    }
    const request = context.switchToHttp().getRequest();
    const user = request.user;
    const hasScope = () => user.scopes.some((scope) => scopes.includes(scope));
    return user && user.scopes && hasScope();
  }
}

使用ScopesGuard作为所有路线的全球守卫(当没有给出范围时返回true):

Use the ScopesGuard as a global guard for all routes (returns true when no scopes are given):

@Module({
  providers: [
    {
      provide: APP_GUARD,
      useClass: ScopesGuard,
    },
  ],
})
export class ApplicationModule {}

然后在端点上使用它:

@Get('protected')
@UseGuards(AuthGuard('jwt'))
@Scopes('manage_server')
async protected(): Promise<string> {
    return 'Hello Protected World';
}

这篇关于NestJS:使用JWT向AuthGuard添加验证选项的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆