Next.js中使用授权码模式获取认证令牌的CORS错误解决
问题分析与解决方案
问题根源
- CORS限制:DocuSign的
/oauth/token接口未配置允许http://localhost:3000的跨域请求,浏览器会拦截前端发起的直接请求。 - 安全风险:你将
client_secret通过NEXT_PUBLIC_前缀的环境变量暴露在前端代码中,这严重违反OAuth 2.0安全规范——client_secret必须仅在后端环境中保密存储。
推荐解决方案:通过Next.js API路由代理请求
利用Next.js的后端API路由作为中间层,由后端发起DocuSign的token请求(后端请求不受浏览器CORS限制,同时能保护敏感凭证)。
步骤1:创建后端API路由
在项目中新建pages/api/docusign-token.js(App Router对应路径为app/api/docusign-token/route.js),写入以下代码:
// pages/api/docusign-token.js export default async function handler(req, res) { if (req.method !== 'POST') { return res.status(405).json({ error: 'Method not allowed' }); } const { code } = req.body; if (!code) { return res.status(400).json({ error: 'Authorization code is required' }); } try { const tokenUrl = "https://account-d.docusign.com/oauth/token"; // 注意:不要用NEXT_PUBLIC_前缀,确保凭证仅在后端加载 const integrationKey = process.env.DOCUSIGN_INTEGRATION_KEY; const clientSecret = process.env.DOCUSIGN_CLIENT_SECRET; const encodedSecret = btoa(`${integrationKey}:${clientSecret}`); const headers = { "Authorization": `Basic ${encodedSecret}`, "Content-Type": "application/x-www-form-urlencoded", }; const body = new URLSearchParams({ grant_type: "authorization_code", code: code, }); const response = await fetch(tokenUrl, { method: "POST", headers: headers, body: body, }); if (!response.ok) { const errorData = await response.json().catch(() => null); throw new Error(`Failed to fetch token: ${response.status} ${errorData?.error || response.statusText}`); } const data = await response.json(); res.status(200).json(data); } catch (error) { res.status(500).json({ error: error.message }); } }
步骤2:修改前端请求代码
将原有的前端直接调用DocuSign接口的代码,改为调用自己的API路由:
useEffect(() => { const getAuthToken = async () => { if (!oAuthCode) return; try { const response = await fetch('/api/docusign-token', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ code: oAuthCode }), }); if (!response.ok) { throw new Error(`Failed to get access token: ${response.status} ${response.statusText}`); } const data = await response.json(); setAuthToken(data.access_token); } catch (error) { console.error(error); } }; getAuthToken(); }, [oAuthCode]);
本地临时测试方案(仅用于开发,禁止生产使用)
如果只是本地开发临时验证流程,可以使用CORS代理工具绕过限制,但绝对不能用于生产环境(会暴露敏感凭证):
// 仅本地测试用,生产环境删除 const tokenUrl = "https://cors-anywhere.herokuapp.com/https://account-d.docusign.com/oauth/token";
核心注意事项
- 必须移除环境变量的
NEXT_PUBLIC_前缀,确保DOCUSIGN_CLIENT_SECRET仅在后端环境中加载,不暴露给前端用户。 - DocuSign的OAuth 2.0规范明确要求:授权码模式的token请求必须由后端发起,前端直接调用不符合安全要求,这也是该接口不允许跨域的根本原因。
内容的提问来源于stack exchange,提问作者Duncan Findlay
相关产品推荐
相关产品推荐

