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

升级Apollo Server 4后遇JsonWebTokenError: jwt malformed问题求助

Auth0 + Apollo Server 4 验证Bearer Token时出现JsonWebTokenError: jwt malformed错误

升级到Apollo Server 4后,使用Auth0验证Bearer Token时持续触发错误:JsonWebTokenError: jwt malformed。根据文档说明,该错误是因为Token缺少.分隔的三个组件之一,检查提供的Token确实存在连续的..,结构不符合标准JWT要求。

提供的Bearer Token:

eyJhbGciOiJkaXIiLCJlbmMiOiJBMjU2R0NNIiwiaXNzIjoiaHR0cHM6Ly9kZXYteWpkczdzMHcudXMuYXV0aDAuY29tLyJ9..ra0kpvVLjOY5SXNL.QcHMSTrOB1gewFkjwJdg3MHCr0UfdS0tKA2XdskUKp8_10puH_oq6meSs9x6f_LDZHeYfJso8QaofxDhNvlpWU2zQFbmPD_tJtTui4jCqNFpYM6Aapw6d7ADeckl0vjsBVs9AdJHUF_6tlBtI6s8Qk6r4UtufKSGfpm5ucb2FeCz-9DREH19QGCBzundoi5goSKK4Br8VhZTrP89KZDwQYSYWR-SXXrAUSz3mhDPbYQjrPeyVZtt4WCHwgCweF-iLHkMI6g82zKYbNUHImfcSZcmNgYS3sTL6MkKLKr9oOkgLyR0KDA2r22vKracFdoZB0g.Lk0ClIc1usAEXFaGzO-hDg

服务器代码

import { ApolloServer } from '@apollo/server';
import { startStandaloneServer } from '@apollo/server/standalone';
import resolvers from './graphql/Resolvers.js';
import { typeDefs } from './graphql/gqlSchema.js';
import verifyToken from './verifyToken.js';
import config from './config.cjs';
import startMongo from './Mongo/StartMongo.js';

const server = new ApolloServer({
  cors: { origin: 'https://www.timerwise.com' },
  typeDefs,
  resolvers,
});
const { url } = await startStandaloneServer(server, {
  context: async ({ req }) => {
    let isAuthenticated = false;
    let token;

    try {
      const authHeader = req.headers.authorization || '';

      if (authHeader) {
        const token = authHeader.split(' ')[1];

        const payload = await verifyToken(token);
        isAuthenticated = payload && payload.sub ? true : false;
      }
    } catch (error) {
      console.error(error);
    }

    return { req, auth: { token, isAuthenticated } };
  },
  listen: { port: config.PORT },
});

startMongo();

console.log(`🚀 Server ready at ${url}`);

Token验证代码

import jwt from 'jsonwebtoken';

import jwksClient from 'jwks-rsa';
import config from './config.cjs';

const verifyToken = async (bearerToken) => {
  const client = jwksClient({ jwksUri: `https://${config.AUTH0_DOMAIN}/.well-known/jwks.json` });

  function getJwksClientKey(header, callback) {
    client.getSigningKey(header.kid, function (error, key) {
      const signingKey = key.publicKey || key.rsaPublicKey;
      callback(null, signingKey);
    });
  }

  return new Promise((resolve, reject) => {
    jwt.verify(
      bearerToken,
      getJwksClientKey,
      {
        audience: config.AUDIENCE,
        issuer: `https://${config.AUTH0_DOMAIN}/`,
        algorithms: ['RS256'],
      },
      function (err, decoded) {
        console.log(bearerToken);
        if (err) reject(err);
        resolve(decoded);
      }
    );
  });
};

export default verifyToken;

问题原因与解决方案

核心原因

你提供的Token是加密JWT(JWE),而非标准的签名JWT(JWS)。jsonwebtoken库仅支持JWS格式,无法解析JWE,因此会判定Token格式错误。另外,服务器代码中存在变量作用域问题:context里的const token会覆盖外层的let token,导致返回的auth.token始终为undefined,不过这不是触发格式错误的直接原因。

解决方案

  1. 确认Token类型:检查Auth0应用配置,确保前端获取的是JWS格式的Token(比如ID Token或Access Token),而非加密的JWE。如果是前端请求时参数错误导致获取到JWE,调整请求参数即可。
  2. 替换为支持JWE的库:如果确实需要处理JWE,弃用不再维护的jsonwebtoken,改用jose库(支持JWS和JWE)。示例验证代码如下:
import { createRemoteJWKSet, jwtVerify } from 'jose';
import config from './config.cjs';

const verifyToken = async (bearerToken) => {
  const jwks = createRemoteJWKSet(new URL(`https://${config.AUTH0_DOMAIN}/.well-known/jwks.json`));
  const { payload } = await jwtVerify(bearerToken, jwks, {
    audience: config.AUDIENCE,
    issuer: `https://${config.AUTH0_DOMAIN}/`,
  });
  return payload;
};

export default verifyToken;
  1. 修复变量作用域问题:将服务器代码中const token = authHeader.split(' ')[1];改为token = authHeader.split(' ')[1];,避免变量覆盖导致的逻辑异常。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 17:03:10