[NestJS/GraphQL] 在Federation配置中处理身份验证标头.

概要 –

如果在NestJS中構建ApolloFederation配置,存在一个问题是,客户端请求头中包含的信息在从网关到各个服务获取数据的请求中不会反映出来。(省略了有关Federation配置和Microservice的详细信息)

这次的认证是使用Firebase Auth来进行的,在网关下的服务中,本想用由Firebase生成的Bearer令牌进行用户认证,但正如前面提到的那样,由于网关和服务之间的头部会被重新构建,导致认证信息丢失。

@Injectable()
export class UsersGuard implements CanActivate {
  constructor(private readonly usersService: UsersService) {}
    return new Promise((res) => {
      const ctx = GqlExecutionContext.create(context);
      const { req } = ctx.getContext();
      const authToken = req.headers.authorization as string; <- ここが取れない

本文意在于实现从网关将包含在客户端请求头中的信息传递给其下属的服务。

前提 tí)

只提取相关软件包的版本。

"@apollo/gateway": "^0.48.1",
"@nestjs/apollo": "^10.0.5",
"@nestjs/common": "^8.0.0",
"@nestjs/core": "^8.0.0",
"@nestjs/graphql": "^10.0.5",

@nestjs/graphql使用10系。与9系有很大的写法差异,需注意。
(若要升级版本,请参考9系到10系的迁移指南)
https://docs.nestjs.com/graphql/federation

结论

只需要一个选项:

只要在传递给Gateway的GraphQLModule.forRoot的配置中重新构建标头即可。

import { IntrospectAndCompose, RemoteGraphQLDataSource } from '@apollo/gateway';
import { Module } from '@nestjs/common';
import { GraphQLModule } from '@nestjs/graphql';
import { ApolloGatewayDriver, ApolloGatewayDriverConfig } from '@nestjs/apollo';

@Module({
  imports: [
    GraphQLModule.forRoot<ApolloGatewayDriverConfig>({
      driver: ApolloGatewayDriver,
      server: {
        cors: true,
      },
      gateway: {
        supergraphSdl: new IntrospectAndCompose({
          subgraphs: [
            { name: 'users', url: `${process.env.USERS_URL}/graphql` },
          ],
        }),
	// ここから -----------
        buildService: ({ name, url }) => {
          return new RemoteGraphQLDataSource({
            url,
            willSendRequest({ request, context }) {
              if (Object.keys(context).length > 0) {
                request.http.headers.set(
                  'Authorization',
                  context['req']['headers']['authorization'],
                );
              }
            },
          });
	 // ----------- ここまで
        },
      },
    }),
  ],
})
export class AppModule {}

在传递给buildService的函数参数中有名为name和url的参数,
在这种情况下,
name为”users”,url为${process.env.USERS_URL}/graphql。
如果想要根据访问数据的服务来改变处理方式,可以使用这些信息进行分支判断。

总之

我想要实现Apollo Federation,但在网关上不进行认证
如果我想在每个子服务上都进行认证,
我介绍了一种将请求头传递给服务的方法。

如果对正在使用NestJS+GraphQL技术栈进行开发的ApolloFederation用户有所帮助,那我就很高兴。

如果有任何问题或指出的事项,欢迎提出,因为我为了简洁起见写了少量信息。

请参考以下链接

阿波罗/网关的文件-阿波罗/网关文档

尽管不是NestJS,但我参考了一篇文章。

bannerAds