Chrome扩展中Vue调用fetch获取OAuth认证返回token失败如何解决?
Chrome扩展OAuth流程获取Token问题修复方案
一、父组件App.vue核心错误及修复
你父组件的代码存在4个明显问题,是导致token无法更新的直接原因:
- 事件绑定与方法名不匹配:你给
access-token事件绑定的处理函数是updateToken,但实际定义的方法名是updateStatus,事件触发后没有执行对应赋值逻辑 - 方法参数使用错误:
updateStatus的入参名是statut,但赋值时直接写this.token = token,这里的token属于未定义变量,无法拿到子组件传递的值 - 语法结构错误:
methods块被错误写在了props配置内部,属于语法错误,整段代码不会正常执行 - 赋值逻辑错误:
props是父组件传递给子组件的只读属性,不能在父组件内部给自身的props赋值,token应该定义为父组件自身的响应式状态。
修正后的父组件代码示例:
<template> <Login v-if="!isConnected" @access-token="updateToken($event)" /> <!-- 可以直接渲染token验证是否拿到值 --> <div v-else>Token: {{ token }}</div> </template> <script> export default { data() { return { isConnected: false, // token作为父组件自身的响应式状态,不要定义在props里 token: "By default" } }, methods: { updateToken(newToken) { this.token = newToken this.isConnected = true } } } </script>
二、子组件Login.vue核心错误及修复
子组件的代码有3个问题会导致你拿不到有效token:
- 死循环问题:解析回调地址参数的
for循环写的是i + 1,没有对i进行赋值递增,循环永远不会结束,code参数根本无法正常解析。建议直接用原生URLSearchParams解析参数,不需要手动写循环 - 登录地址参数错误:拼接登录地址时
&state = default中间多了空格,会导致参数被错误编码,可能触发后端state校验失败,返回错误响应 - 缺少错误捕获:
launchWebAuthFlow和fetch都没有加错误处理,任意一步报错都会导致后续代码终止,你无法感知到错误发生。
修正后的子组件login方法代码示例:
async login() { try { const CLIENT_SECRET = "***********************************"; const redirectURL = browser.identity.getRedirectURL(); const clientID = "*********"; const scopes = "openid"; // 拼接登录地址,去掉state参数的空格 let loginURL = `${urlAuth}/auth?client_id=${clientID}&response_type=code&state=default&redirect_uri=${encodeURIComponent(redirectURL)}&scope=${encodeURIComponent(scopes)}`; const callbackUrl = await browser.identity.launchWebAuthFlow({ interactive: true, url: loginURL, }); // 用原生API解析参数,避免手动写循环出错 const urlObj = new URL(callbackUrl); const code = urlObj.searchParams.get('code'); if (!code) throw new Error('未获取到授权code') const details = { redirect_uri: redirectURL, client_id: "********", grant_type: "authorization_code", code, client_secret: CLIENT_SECRET, scope: "openid", }; const detailsBody = new URLSearchParams(details).toString(); const res = await fetch(`${urlAuth}/token`, { method: "POST", headers: { "Content-Type": "application/x-www-form-urlencoded", }, body: detailsBody, }); const data = await res.json(); if (!data.access_token) throw new Error('未获取到access_token') this.user = data.access_token; this.$emit("access-token", this.user); } catch (err) { // 扩展环境可以把错误存在storage里,后续可以在扩展管理页的存储面板查看 browser.storage.local.set({ loginError: err.message, errorStack: err.stack }) } },
三、扩展环境调试方案
如果你无法直接打印控制台,可以把中间结果、错误信息都存在browser.storage.local中,打开扩展管理页面的「开发人员模式」,点击对应扩展的「检查视图」即可查看存储数据,也可以直接在组件模板中渲染中间变量验证执行结果。
内容的提问来源于stack exchange,提问作者AlanDev
相关产品推荐
相关产品推荐

