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

Vue Apollo Client配置Bearer Token失败:auth0.getAccessTokenSilently返回空对象

问题分析与解决方案

核心问题

  1. 异步函数处理错误:auth0.getAccessTokenSilently()是异步函数,直接赋值会返回Promise对象而非实际token,导致Authorization头格式错误(Bearer [object Promise])。
  2. 静态配置时机过早:初始化HttpLink/WebSocketLink时直接设置headers,此时Auth0可能未完成登录流程,token尚未生成。
  3. WebSocket连接参数无法动态更新:静态的connectionParams无法在token过期或刷新后重新获取有效token。

修复步骤

1. 安装依赖(若未安装)

确保安装apollo-link-context用于动态设置请求头:

npm install apollo-link-context

2. 修改main.js代码

import { createApp, provide, h } from 'vue'
import './tailwind.css'
import App from './App.vue'
import { routes } from './routes.js'
import { createRouter, createWebHistory } from 'vue-router'
import { ApolloClient, InMemoryCache } from '@apollo/client/core'
import { DefaultApolloClient } from '@vue/apollo-composable'
import { createAuth0 } from '@auth0/auth0-vue';
import { split } from 'apollo-link'
import { WebSocketLink } from 'apollo-link-ws'
import { getMainDefinition } from 'apollo-utilities'
import { HttpLink } from 'apollo-link-http'
// 新增导入setContext
import { setContext } from 'apollo-link-context';

const auth0 = createAuth0({
  domain: import.meta.env.VITE_AUTH0_DOMAIN,
  client_id: import.meta.env.VITE_AUTH0_CLIENT_ID,
  redirect_uri: window.location.origin
})

// 改为异步函数,正确获取token
async function getToken(){
  try {
    const token = await auth0.getAccessTokenSilently()
    console.log("token=", token)
    return token
  } catch (err) {
    console.error('获取token失败:', err)
    return null
  }
}

// 创建动态授权链接,每次请求时获取最新token
const authLink = setContext(async (_, { headers }) => {
  const token = await getToken()
  return {
    headers: {
      ...headers,
      'content-type': 'application/json',
      ...(token ? { Authorization: `Bearer ${token}` } : {})
    }
  }
})

// 基础HTTP链接,仅保留固定配置
const httpLink = new HttpLink({
  uri: import.meta.env.VITE_API_URI,
})

// 合并授权链接与HTTP链接
const authenticatedHttpLink = authLink.concat(httpLink)

// WebSocket链接改为异步connectionParams
const wsLink = new WebSocketLink({
  uri: import.meta.env.VITE_API_WS,
  options: {
    reconnect: true,
    timeout: 30000,
    inactivityTimeout: 30000,
    lazy: true,
    // 改为异步函数,动态获取token
    connectionParams: async () => {
      const token = await getToken()
      return {
        headers: {
          'content-type': 'application/json',
          ...(token ? { Authorization: `Bearer ${token}` } : {})
        }
      }
    }
  },
})

const link = split(
  ({ query }) => {
    const definition = getMainDefinition(query)
    return definition.kind === 'OperationDefinition' &&
      definition.operation === 'subscription'
  },
  wsLink,
  authenticatedHttpLink // 使用合并后的HTTP链接
)

const cache = new InMemoryCache({
  typePolicies: {
    Subscription: {
      goal: {
        goals: {
          fields: {
            merge(existing, incoming) {
              return incoming;
            }
          }
        }
      }
    }
  }
})

const apolloClient = new ApolloClient({
  link,
  cache,
  connectToDevTools: true,
})

const app = createApp({
  setup () {
    provide(DefaultApolloClient, apolloClient)
  },
  render: () => h(App),
})

const router = createRouter({
  history: createWebHistory(),
  routes,
})

app.use(router)
app.use(auth0);
app.mount('#app')

关键修改说明

  • 异步token获取:getToken改为async函数,用await等待getAccessTokenSilently()返回实际token。
  • 动态请求头:通过setContext创建authLink,每次发起请求时都会重新获取token,确保头信息是最新的。
  • WebSocket动态参数:将connectionParams设为异步函数,在建立WebSocket连接时动态获取token,避免token过期导致连接失败。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 05:08:09