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

OAuth应用中如何将Express服务端的访问令牌传递给React应用

方案1:最优安全方案 - 前端请求全部走Express代理(无需传递token到前端)

该方案Intuit的access token全程只存储在服务端,完全避免前端泄露风险,不需要改动现有OAuth核心逻辑,适配成本最低,是生产环境首选方案。

  • 你现有代码里的/getCompanyInfo就是标准的代理接口逻辑,所有需要调用Intuit API的能力都按这个格式封装成Express接口即可,React侧直接调用你自己的服务端接口,不需要感知Intuit access token的存在
  • 你现有代码里用全局变量存储oauthClient和oauth2_token_json只能支持单用户使用,多用户访问会出现数据串用问题,建议引入express-session把用户token存在各自的会话里:
    1. 先安装依赖:npm install express-session
    2. 增加session配置:
    const session = require('express-session');
    app.use(session({
      secret: '自定义加密字符串',
      resave: false,
      saveUninitialized: true,
      cookie: { secure: false } // 生产环境需要改为true
    }))
    
    1. 修改callback接口逻辑:
    app.get('/callback', function(req, res) {
      // 每个用户请求单独实例化oauthClient,不要用全局变量
      const oauthClient = new OAuthClient({
          clientId: '*****',
          clientSecret: '*****',
          environment: 'sandbox',
          redirectUri: 'http://localhost:8000/callback'
      });
      oauthClient.createToken(req.url)
         .then(function(authResponse) {
               // 把token存在当前用户的session里,多用户互不干扰
               req.session.oauthToken = authResponse.getJson();
               req.session.oauthClient = oauthClient;
           })
          .catch(function(e) {
               console.error(e);
           });
      res.redirect('http://localhost:3000')
    });
    
    1. 可以加一个状态接口给前端判断授权状态:
    app.get('/auth/status', (req, res) => {
      res.send({ isAuthenticated: !!req.session.oauthToken })
    })
    
  • React侧因为已经配置了代理到8000端口,直接调用fetch('/getCompanyInfo')这类自定义接口即可,不需要处理任何token逻辑。

方案2:需要把token传到前端的实现

如果确实有前端直接调用Intuit API的需求,可按以下步骤实现:

步骤1:服务端加密token为JWT传递给前端

  1. 安装JWT依赖:npm install jsonwebtoken
  2. 修改callback接口,跳转时附带加密后的JWT参数:
const jwt = require('jsonwebtoken');
app.get('/callback', function(req, res) {
  const oauthClient = new OAuthClient({
      clientId: '*****',
      clientSecret: '*****',
      environment: 'sandbox',
      redirectUri: 'http://localhost:8000/callback'
  });
  oauthClient.createToken(req.url)
    .then(function(authResponse) {
      const tokenData = authResponse.getJson();
      // 生成JWT,过期时间和Intuit原生token保持一致
      const frontToken = jwt.sign(tokenData, 'JWT加密密钥', { expiresIn: tokenData.expires_in });
      // 跳转时把JWT带到前端
      res.redirect(`http://localhost:3000?token=${frontToken}`)
    })
    .catch(function(e) {
      console.error(e);
      res.redirect('http://localhost:3000?error=auth_failed')
    });
});

步骤2:React侧接收存储token

在React入口文件的初始化逻辑里获取并存储token:

// App.js的useEffect钩子中添加
useEffect(() => {
  const urlParams = new URLSearchParams(window.location.search);
  const token = urlParams.get('token');
  if (token) {
    // 存储到localStorage
    localStorage.setItem('intuit_jwt', token);
    // 清除URL里的token参数,避免用户分享链接泄露凭证
    window.history.replaceState({}, document.title, window.location.pathname);
  }
}, [])

步骤3:前端使用token

调用Intuit API前解密JWT获取原始凭证即可:

import jwtDecode from 'jwt-decode';

const getIntuitToken = () => {
  const jwt = localStorage.getItem('intuit_jwt');
  return jwt ? jwtDecode(jwt) : null;
}

注意:该方案token存在前端有XSS攻击泄露风险,处理敏感数据的生产环境不建议使用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 07:45:03