javascript - Firebase:如果currentUser为null,如何在http请求上刷新idToken
问题描述
我目前正在使用带有 Firebase 的 React JS 来处理登录操作。
我和团队决定使用自定义身份验证系统方式进行登录。因此,我们从后端生成自定义令牌,然后前端通过 signInWithCustomToken 执行登录。
直到这里,一切都像魅力一样工作,但是一旦我登录,如果我刷新页面,currentUser 对象将变为 null,因此我无法在其上调用方法 getIdToken(true) 来刷新令牌。每次我使用 axios 发出 http 请求时都会调用 firebase.auth().currentUser.getIdToken(true) 方法(使用拦截器将 Authorization 字段添加到请求中)。如果我登录并在不重新加载的情况下发出 http 请求,它可以正常工作,但如果我刷新我会收到错误,因为 currentUser 对象会丢失其内容并变为空。
我花了或多或少 8 个小时在 Internet 上冲浪寻找解决方案。我已经看到有人说解决方案是将用户带入 onAuthStateChanged观察者,但问题是我在发出 http 请求时无法进入观察者以获取用户的值,因为观察者不是函数我可以在我需要的时候打电话。
我还尝试将 onAuthStateChanged 观察者在触发时(在登录或注销期间)返回的用户对象保存在 localStorage 上,但是用户对象与返回的用户对象不同,并且它在原型中没有getIdToken 函数。所以对我来说没用。
我也尝试使用 firebase.auth().setPersistence(firebase.auth.Auth.Persistence.SESSION),将 onAuthStateChanged 观察者返回的用户对象传递给它,但没有任何改变。
这是我的项目的代码:
****** AXIOS 请求拦截器 ******
instanceAXIOS.interceptors.request.use(
async config => {
const { refreshedToken } = await refreshUserTokenTEST()
config.headers.Authorization = `Bearer ${ refreshedToken }`
return config
},
error => Promise.reject(error)
)
****** 刷新令牌 ******
const refreshUserTokenTEST = () => {
try {
return firebase
.auth()
.currentUser
.getIdToken(true)
.then(token => {
return { status: 200, refreshedToken: token }
})
.catch(err => {
console.error(err)
return { status: 500, refreshedToken: null }
})
} catch (exc) {
console.error("ERROR DURING TOKEN REFRESH")
return { status: 404, refreshedToken: null }
}
}
****** firebasePersistenceOption 函数 ******
const firebasePersistenceOption = async (userObject) => {
return firebase
.auth()
.setPersistence(firebase.auth.Auth.Persistence.SESSION)
.then(function() {
return userObject
})
.catch(function(error) {
// Handle Errors here.
var errorCode = error.code;
var errorMessage = error.message;
})
}
****** onAuthStateChanged 观察者 ******
firebase.auth().onAuthStateChanged(async function(user) {
if (user) {
console.log("LOGGED IN")
await firebasePersistenceOption(user)
} else {
console.log("LOGGED OUT")
}
})
就像我说的那样,无需重新加载页面,一切正常,因此代码中没有错误(我几乎希望是这样)。
解决方案
我终于找到了解决问题的方法。感谢@DougStevenson 的建议和GitHub 上的讨论,我能够编写一个函数来获取刷新的 id 令牌。
这是基本代码:
// get the current user inside the observer
// then refresh the token
// and finally unsubscribe the observer
const getIdTokenRefreshed = async () => {
return new Promise(async (resolve, reject) => {
const unsubscribe = firebase
.auth
.onAuthStateChanged(user => {
unsubscribe()
const refreshedToken = await user
.getIdToken(true)
.catch(err => console.error(err))
resolve(refreshedToken)
}, reject)
})
}
推荐阅读
- apache-spark - 运行总和/累积总和与地板和天花板 Py Spark
- scala - 如何在火花中将数据集 [行] 保存为文本文件?
- python - 使用 Numpy Array 遍历 .txt 文件中的时间序列数据
- maven - 运行 wildfly:run 目标后,有没有办法使用 maven build 进行处理?
- php - Polylang 翻译网址 slug 无法正常工作
- python - 如何将嵌套字典列表转换为 pandas 数据框?
- python - 如何在熊猫中滚动非重叠窗口
- c# - 避免对具有可为空类型/字段的泛型发出警告的最佳方法?
- c++ - 循环内的局部对象的析构函数是否保证在下一次迭代之前被调用?
- amazon-web-services - EKS / AWS 中的 Hazelcast 主节点选举是可能的吗?