passport.js - Nest.JS 使用 AuthGuard 作为 GraphQL 的中间件

标签 passport.js graphql nestjs

我正在尝试使用 passportJS 确保我的 GraphQL 端点的安全,以便每次调用此端点都使用 AuthGuard 来验证 token 并在 request.user 上设置用户,就像它在使用以下代码的 Controller 中所做的那样:

@Get('findAll')
@UseGuards(AuthGuard('jwt'))
findAll(@Req() request): Promise<Array<Thing>> {
    return this.thingService.findByUser(request.user.email);
}

问题是我想在 graphQL 端点中使用它,它是这样创建的:
consumer
    .apply(graphiqlExpress({ endpointURL: '/graphql' }))
    .forRoutes('/graphiql')
    .apply(
        graphqlExpress(req => ({ schema, rootValue: req })),
        ¿?,
    )
    .forRoutes('/graphql');

我想我可以在graphqlExpress函数之后将它设置为中间件函数,但我没有成功。有什么想法吗?

先感谢您!

编辑

作为一种解决方法,我已经实现了 Nest Docs 上提出的解决方案。它在必须保护的每个查询/突变中使用@UseGuard。

但是,我想保护整个端点,这样就不会为每个 protected 解析器调用 guard ,而只会在主请求上调用一次。这甚至可能吗?

最佳答案

这在技术上是可行的,但是写起来很草率,而且绝对不能保证它可以与 Fastify 一起使用,所以请注意。功能的核心来自实现中间件的模块。我最终用 AppModule 完成了这一切。我不建议这样做(至少不是 所有 的代码),但它仍然有效。
您需要将 guard 设为 custom provider所以它可以被注入(inject)到任何上下文中。
然后你需要模拟 ExecutionContext使用 req, res, next .如果你想要类型安全,这说起来容易做起来难,但如果你不关心那个(我不关心这个)然后拍下 as any并收工。
之后,在中间件使用者中运行 apply并利用 this.guard.canActivate用那个模拟ExecutionContext你创造的。制作这个中间件asyncawait canActivate称呼。检查它是否返回为 true如果没有,那么 throw new <ErrorOfYourChoice>()和繁荣。设置好了。代码看起来(模糊地)像这样:

import {
  BadRequestException,
  CanActivate,
  Inject,
  MiddlewareConsumer,
  Module,
  NestModule,
} from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { AppResolver } from './app.resolver';
import { GraphQLModule } from '@nestjs/graphql';
import { JwtModule } from '@nestjs/jwt';
import { AuthGuard, PassportModule } from '@nestjs/passport';
import { JwtStrategy } from './jwt.strategy';

@Module({
  imports: [
    GraphQLModule.forRoot({
      autoSchemaFile: true,
    }),
    JwtModule.register({ secret: 'secret' }),
    PassportModule.register({ defaultStrategy: 'jwt' }),
  ],
  controllers: [AppController],
  providers: [
    AppService,
    AppResolver,
    JwtStrategy,
    { provide: 'CustomGuard', useClass: AuthGuard() },
  ],
})
export class AppModule implements NestModule {
  constructor(@Inject('CustomGuard') private readonly guard: CanActivate) {}

  configure(consumer: MiddlewareConsumer) {
    consumer
      .apply(async (req, res, next) => {
        const canActivate = await this.guard.canActivate({
          switchToHttp: () => ({
            getRequest: () => req,
            getResponse: () => res,
            getNext: () => next,
          }),
        } as any);
        if (canActivate) {
          next();
        } else {
          throw new BadRequestException();
        }
      })
      .forRoutes('graphql');
  }
}
您可以查看this repository一切都已连接并正常工作。使用 POST /login -d 'username=test1&password=changeme' 登录,获取 JWT 并随心所欲地使用它。

关于passport.js - Nest.JS 使用 AuthGuard 作为 GraphQL 的中间件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51944801/

相关文章:

javascript - NestJs:有没有办法生成已经连接到 TypeOrm 实体的资源?

typescript - NestJS - 避免返回用户密码

node.js - 使用范围保护 API(oauth2orize、passport、express、Nodejs)

javascript - 设置 bcrypt 以与 Passport 和 async-await Node.js 库配合使用

node.js - 使用 @AuthGuard、Passport 在 NestJS 中进行社交登录

graphql - 自动重新加载网关以在联合服务 apollo GraphQL 中更改架构

NestJs - 如何获取处理程序的 url?

node.js - 提交表单时, Node js Passport js用户名字段错误和密码字段错误不显示

reactjs - react-hooks 查询和 setState 导致 500 错误

javascript - 使用 Relay 更新 React 状态