You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过Apollo Client将AWS Amplify(Cognito)异步获取的JWT访问令牌发送至Apollo服务器进行后端验证

如何用Apollo Client将AWS Amplify(Cognito)的JWT令牌发送到Apollo服务器做后端验证?

我之前刚好遇到这个问题,折腾了一阵终于搞定了,现在把完整的解决方案分享给大家,希望能帮到有同样需求的开发者~

核心思路

我们需要让Apollo Client在每次发起GraphQL请求时,异步从Amplify(Cognito)获取JWT访问令牌,然后将令牌添加到请求头中,传给后端Apollo服务器完成合法性验证。

具体实现步骤

1. 确保Amplify Auth初始化完成

首先要保证你已经正确配置并初始化了Amplify Auth,这是获取令牌的基础:

import Amplify from 'aws-amplify';
import awsconfig from './aws-exports';

// 初始化Amplify,使用你的AWS配置文件
Amplify.configure(awsconfig);

2. 自定义Apollo Link处理令牌与请求头

Apollo Client的setContext支持异步函数,我们可以利用这一点来动态获取令牌并添加到请求头:

import { ApolloClient, InMemoryCache, createHttpLink } from '@apollo/client';
import { setContext } from '@apollo/client/link/context';
import { Auth } from 'aws-amplify';

// 创建基础HTTP链接,指向你的Apollo服务器地址
const httpLink = createHttpLink({
  uri: 'https://your-apollo-server-url.com/graphql',
});

// 创建认证链接,负责获取令牌并设置请求头
const authLink = setContext(async (_, { headers }) => {
  try {
    // 从Amplify异步获取当前用户的会话信息
    const session = await Auth.currentSession();
    // 提取JWT访问令牌
    const accessToken = session.getAccessToken().getJwtToken();

    // 返回包含令牌的请求头,格式遵循Bearer认证规范
    return {
      headers: {
        ...headers,
        authorization: accessToken ? `Bearer ${accessToken}` : '',
      },
    };
  } catch (error) {
    // 如果获取令牌失败(比如用户未登录),返回原始请求头
    return { headers };
  }
});

// 组合认证链接与HTTP链接,初始化Apollo Client
const client = new ApolloClient({
  link: authLink.concat(httpLink),
  cache: new InMemoryCache(),
});

3. 后端Apollo Server验证令牌

后端需要验证令牌的合法性,这里以Node.js为例,使用jsonwebtoken和jwks-rsa库来验证Cognito签发的令牌:

const jwt = require('jsonwebtoken');
const jwksClient = require('jwks-rsa');
const { ApolloServer } = require('apollo-server');

// 配置Cognito的JWKS地址,用于获取公钥
const jwksClientInstance = jwksClient({
  jwksUri: 'https://cognito-idp.<你的AWS区域>.amazonaws.com/<你的用户池ID>/.well-known/jwks.json',
});

// 获取Cognito的公钥用于验证签名
function getSigningKey(header, callback) {
  jwksClientInstance.getSigningKey(header.kid, (err, key) => {
    const signingKey = key.getPublicKey();
    callback(null, signingKey);
  });
}

// 初始化Apollo Server,在context中验证令牌
const server = new ApolloServer({
  typeDefs: /* 你的GraphQL类型定义 */,
  resolvers: /* 你的解析器 */,
  context: async ({ req }) => {
    const authHeader = req.headers.authorization;
    if (authHeader) {
      const token = authHeader.split(' ')[1];
      // 验证令牌合法性
      return new Promise((resolve, reject) => {
        jwt.verify(token, getSigningKey, {
          audience: '<你的Cognito客户端ID>',
          issuer: `https://cognito-idp.<你的AWS区域>.amazonaws.com/<你的用户池ID>`,
        }, (err, decodedToken) => {
          if (err) {
            reject(new Error('Invalid token'));
          } else {
            // 把解码后的用户信息传到解析器中
            resolve({ user: decodedToken });
          }
        });
      });
    }
    return {};
  },
});

server.listen().then(({ url }) => {
  console.log(`🚀 Server ready at ${url}`);
});

关于未选用AppSync的说明

截至2021年9月11日,AppSync对GraphQL规范的实现程度无法满足我的业务需求,因此最终选择了自行搭建Apollo服务器配合Amplify Auth的方案。

内容的提问来源于stack exchange,提问作者Sigex

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.30 23:57:43