如何使用 Firebase 刷新令牌来保持身份验证?
How do I use a Firebase refresh token to persist authentication?
几周来我一直在努力解决这个问题,但似乎无法理解文档或其他内容。感谢您提供的任何帮助。
我正在使用 Firebase SDK
我有我的服务器端路由,我可以在其中访问令牌并将其发送到前端:
const admin = require("firebase-admin")
admin.initializeApp()
exports.loginRoute = (req, res) => {
const user = {
email: req.body.email,
password: req.body.password
}
const { valid, errors } = validateLoginData(user)
if (!valid) {
return res.status(400).json(errors)
}
admin
.auth()
.signInWithEmailAndPassword(user.email, user.password)
.then((data) => {
console.log(data.user.refreshToken, "refresh token")
return data.user.getIdToken(true)
})
.then((token) => {
return res.json({ token })
})
.catch((err) => {
console.error(err)
if (err.code === "auth/user-not-found") {
return res.status(400).json({ general: "User not found" })
} else if (err.code === "auth/wrong-password") {
return res
.status(400)
.json({ password: "User credentials don't match" })
} else {
res.status(500).json({
error: "Something went wrong, please try again."
})
}
})
}
在这里我可以使用刷新令牌(在前端)获取新的身份验证令牌,但我不知道如何创建路由来执行此操作:
if (token) {
const decodedToken = jwtDecode(token)
if (decodedToken.exp * 1000 < Date.now()) {
localStorage.setItem("Authentication", false)
//axios request to persist authentication would go here
}
}
有没有人有可行的路线,或者关于如何做的建议?
编辑
const login = async (credentials) => {
let token
await axios
.post("/api/login", credentials)
.then((res) => {
token = res.data.token
const FBIdToken = `Bearer ${token}`
localStorage.setItem("token", token)
localStorage.setItem("FBIdToken", FBIdToken)
localStorage.setItem("Authentication", true)
context.setAuthenticated((prev) => true)
})
.then(() => {
context.getUserData()
})
.then(() => {
context.setUserState((prevUserState) => ({
...prevUserState,
token
}))
})
.catch((err) => {
context.setUserErrors((prev) => ({
...prev,
errors: err.response.data
}))
})
history.push("/")
}
观察者(客户端):
firebase.auth().onAuthStateChanged((user) => {
if (user) {
firebase
.auth()
.currentUser.getIdToken(/* forceRefresh */ true)
.then((idToken) => {
const FBIdToken = `Bearer ${idToken}`
localStorage.setItem("FBIdToken", FBIdToken)
})
.catch((err) => {
console.log(err)
})
} else {
localStorage.removeItem("FBIdToken")
}
})
如果您在客户端代码中使用 Firebase 身份验证 JavaScript SDK 登录,它已经保留了用户的登录状态,并会在您重新加载页面时尝试恢复它。您不必为此做任何事情。
不过,您似乎在服务器端环境中使用了相同的 SDK,这很不寻常。如果您想在服务器端环境中自己创建令牌,您应该使用 Firebase Admin SDK 来实现。然后您可以将该令牌发送回客户端,并使用它在此处登录 Firebase 身份验证。
但对于绝大多数用例,我建议在您的客户端代码中使用 Firebase 身份验证 SDK,以便 SDK 为您管理令牌的刷新。如果您随后想将令牌传递给服务器,您可以像现在一样使用 getIdToken()
。您也可以 monitor ID token generation, or more commonly monitor if a user's sign-in session is restored as shown in the first example of the documentation on detecting the current user.
几周来我一直在努力解决这个问题,但似乎无法理解文档或其他内容。感谢您提供的任何帮助。
我正在使用 Firebase SDK
我有我的服务器端路由,我可以在其中访问令牌并将其发送到前端:
const admin = require("firebase-admin")
admin.initializeApp()
exports.loginRoute = (req, res) => {
const user = {
email: req.body.email,
password: req.body.password
}
const { valid, errors } = validateLoginData(user)
if (!valid) {
return res.status(400).json(errors)
}
admin
.auth()
.signInWithEmailAndPassword(user.email, user.password)
.then((data) => {
console.log(data.user.refreshToken, "refresh token")
return data.user.getIdToken(true)
})
.then((token) => {
return res.json({ token })
})
.catch((err) => {
console.error(err)
if (err.code === "auth/user-not-found") {
return res.status(400).json({ general: "User not found" })
} else if (err.code === "auth/wrong-password") {
return res
.status(400)
.json({ password: "User credentials don't match" })
} else {
res.status(500).json({
error: "Something went wrong, please try again."
})
}
})
}
在这里我可以使用刷新令牌(在前端)获取新的身份验证令牌,但我不知道如何创建路由来执行此操作:
if (token) {
const decodedToken = jwtDecode(token)
if (decodedToken.exp * 1000 < Date.now()) {
localStorage.setItem("Authentication", false)
//axios request to persist authentication would go here
}
}
有没有人有可行的路线,或者关于如何做的建议?
编辑
const login = async (credentials) => {
let token
await axios
.post("/api/login", credentials)
.then((res) => {
token = res.data.token
const FBIdToken = `Bearer ${token}`
localStorage.setItem("token", token)
localStorage.setItem("FBIdToken", FBIdToken)
localStorage.setItem("Authentication", true)
context.setAuthenticated((prev) => true)
})
.then(() => {
context.getUserData()
})
.then(() => {
context.setUserState((prevUserState) => ({
...prevUserState,
token
}))
})
.catch((err) => {
context.setUserErrors((prev) => ({
...prev,
errors: err.response.data
}))
})
history.push("/")
}
观察者(客户端):
firebase.auth().onAuthStateChanged((user) => {
if (user) {
firebase
.auth()
.currentUser.getIdToken(/* forceRefresh */ true)
.then((idToken) => {
const FBIdToken = `Bearer ${idToken}`
localStorage.setItem("FBIdToken", FBIdToken)
})
.catch((err) => {
console.log(err)
})
} else {
localStorage.removeItem("FBIdToken")
}
})
如果您在客户端代码中使用 Firebase 身份验证 JavaScript SDK 登录,它已经保留了用户的登录状态,并会在您重新加载页面时尝试恢复它。您不必为此做任何事情。
不过,您似乎在服务器端环境中使用了相同的 SDK,这很不寻常。如果您想在服务器端环境中自己创建令牌,您应该使用 Firebase Admin SDK 来实现。然后您可以将该令牌发送回客户端,并使用它在此处登录 Firebase 身份验证。
但对于绝大多数用例,我建议在您的客户端代码中使用 Firebase 身份验证 SDK,以便 SDK 为您管理令牌的刷新。如果您随后想将令牌传递给服务器,您可以像现在一样使用 getIdToken()
。您也可以 monitor ID token generation, or more commonly monitor if a user's sign-in session is restored as shown in the first example of the documentation on detecting the current user.