【问题标题】:How do I use a Firebase refresh token to persist authentication?如何使用 Firebase 刷新令牌来保持身份验证?
【发布时间】:2021-06-09 00:40:13
【问题描述】:

我数周以来一直试图弄清楚这一点,但似乎无法理解文档,或者其他什么。感谢您提供的任何帮助。

我正在使用 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 已经保留了用户的登录状态,并在您重新加载页面时尝试恢复它。你不应该为此做任何事情。这不适合你吗?
  • @FrankvanPuffelen 它不起作用,我的令牌在 1 小时后过期,然后我必须注销并重新登录。
  • 所有内置提供程序的 ID 令牌在一小时后过期,所以这是有道理的。但是 SDK 会在此之前自动刷新令牌,因此您应该能够始终获得有效的令牌:firebase.google.com/docs/reference/js/firebase.User#getidtoken 您是否将这个令牌缓存在某个地方?
  • @FrankvanPuffelen 我只相信上面的函数。然后在调用我刚刚编辑到帖子中的登录功能时将其返回到前面。
  • @FrankvanPuffelen 谢谢,还在习惯堆叠。感谢您的帮助和指导。

标签: reactjs firebase authentication firebase-authentication refresh-token


【解决方案1】:

如果您在客户端代码中使用 Firebase 身份验证 JavaScript SDK 登录,它已经保留了用户的登录状态,并在您重新加载页面时尝试恢复它。你不应该为此做任何事情。

您似乎在服务器端环境中使用了相同的 SDK,这很不寻常。如果您想在服务器端环境中自己铸造令牌,则应使用 Firebase Admin SDK 来执行此操作。然后,您可以将该令牌发送回客户端,并使用它在那里登录 Firebase 身份验证。

但对于绝大多数用例,我建议在您的客户端代码中使用 Firebase 身份验证 SDK,以便 SDK 为您管理令牌的刷新。如果您想将令牌传递给服务器,您可以像现在一样使用getIdToken()。您还可以monitor ID token generation,或者更常见地监控用户的登录会话是否已恢复,如detecting the current user 上文档的第一个示例所示。

【讨论】:

    猜你喜欢
    • 2019-12-25
    • 2020-02-16
    • 2017-11-08
    • 2020-08-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-30
    • 2019-08-30
    相关资源
    最近更新 更多