如何刷新 Firebase 会话 Cookie

2024-02-12

我正在开发一个使用 Node.js/Express.js 作为后端的 Web 应用程序,我使用 Firebase 进行用户身份验证,并使用 Firebase Admin SDK 管理用户注册等。

当用户想要登录时,我使用 Firebase Client SDK 登录他,如下所示:

// Handling User SignIn
$('#signin').on('click', function(e){
    e.preventDefault();

    let form = $('#signin-form'),
        email = form.find('#email').val(),
        pass = form.find('#password').val(),
        errorWrapper = form.find('.error-wrapper');

    if(email && pass){
        firebase.auth().signInWithEmailAndPassword(email, pass)
            .catch(err => {
                showError(errorWrapper, err.code)
            });
    }else {
        showError(errorWrapper, 'auth/required');
    }
});

在这段代码下面,我设置了一个观察者来监视用户何时成功登录,成功登录后,我获得了一个 Firebase ID 令牌,我将其发送到服务器上的端点,以将其交换为具有相同声明的会话 cookie ID 令牌,因为后者会在 1 小时后过期。

// POST to session login endpoint.
let postIdTokenToSessionLogin = function(url, idToken, csrfToken) {
    return $.ajax({
        type: 'POST',
        url: url,
        data: {
            idToken: idToken,
            csrfToken: csrfToken
        },
        contentType: 'application/x-www-form-urlencoded'
    });
};

// Handling SignedIn Users 
firebase.auth().onAuthStateChanged(function(user) {
    if (user) {
        user.getIdToken().then(function(idToken) {
            let csrfToken = getCookie('csrfToken');
            return postIdTokenToSessionLogin('/auth/signin', idToken, csrfToken)
                .then(() => {
                        location.href = '/dashboard';
                    }).catch(err => {
                        location.href = '/signin';
                    });
                });
        });
    } else {
        // No user is signed in.
    }
});

服务器上的登录端点如下所示:

// Session signin endpoint.
router.post('/auth/signin', (req, res) => {
    // Omitted Code...
    firebase.auth().verifyIdToken(idToken).then(decodedClaims => {
        return firebase.auth().createSessionCookie(idToken, {
            expiresIn
        });
    }).then(sessionCookie => {
        // Omitted Code...
        res.cookie('session', sessionCookie, options);
        res.end(JSON.stringify({
            status: 'success'
        }));
    }).catch(err => {
        res.status(401).send('UNAUTHORIZED REQUEST!');
    });
});

我创建了一个中间件来验证用户会话 cookie,然后再让他访问受保护的内容,如下所示:

function isAuthenticated(auth) {
    return (req, res, next) => {
        let sessionCookie = req.cookies.session || '';
        firebase.auth().verifySessionCookie(sessionCookie, true).then(decodedClaims => {
            if (auth) {
                return res.redirect('/dashboard')
            } else {
                res.locals.user = decodedClaims;
                next();
            }
        }).catch(err => {
            if (auth) next();
            else return res.redirect('/signin')
        });
    }
}

为了在视图上显示用户信息,我将解码的声明设置为res.locals.user变量并将其传递到下一个中​​间件,我在其中渲染视图并像这样传递该变量。

router.get('/', (req, res) => {
    res.render('dashboard/settings', {
        user: res.locals.user
    });
});

到目前为止,一切都很好,现在问题出现在用户转到仪表板更改他的信息(姓名和电子邮件)之后,当他将包含他的姓名和电子邮件的表单提交到服务器上的端点时,我使用 Firebase 更新他的凭据管理软件开发工具包

// Handling User Profile Update
function settingsRouter(req, res) {
    // Validate User Information ...
    // Update User Info
    let displayName = req.body.fullName,
        email = req.body.email
    let userRecord = {
        email,
        displayName
    }
    return updateUser(res.locals.user.sub, userRecord).then(userRecord => {
        res.locals.user = userRecord;
        return res.render('dashboard/settings', {
            user: res.locals.user
        });
    }).catch(err => {
        return res.status(422).render('dashboard/settings', {
            user: res.locals.user
        });
    });
}

现在,当用户提交表单时,视图会更新,因为我设置了res.locals.user变量为新的userRecord但是一旦他刷新页面,视图就会显示旧的凭据,因为在对受保护内容进行任何获取请求之前,中间件isAuthenticated被执行,后者从会话 cookie 中获取用户信息,其中包含更新之前的旧用户凭据。

到目前为止,这些是我得出的结论以及我尝试做的事情:

  • 如果我希望视图正确呈现,我应该退出并再次登录以获取新的 Firebase ID 令牌来创建新的会话 cookie,这不是一个选项。

  • 我尝试通过从 Admin SDK 创建新的 ID 令牌来刷新会话 cookie,但似乎没有可用的此选项,并且我无法通过客户端 SDK 执行此操作,因为用户已经登录。

  • 存储 ID 令牌以便稍后在创建会话 cookie 时使用并不是一种选择,因为它们会在 1 小时后过期。

在在这里发帖之前,我用谷歌搜索了这个问题,所以非常感谢任何帮助。


我的一个应用程序面临着非常相似的情况。我想答案就在这些线索之中。

From Firebase 文档 https://firebase.google.com/docs/auth/admin/manage-cookies

Firebase Auth 为依赖会话 cookie 的传统网站提供服务器端会话 cookie 管理。与客户端短期 ID 令牌相比,此解决方案具有多个优点,客户端短期 ID 令牌可能需要每次都需要重定向机制来在过期时更新会话 cookie:

因此,他们在这里暗示您想要从服务器管理会话及其生命周期。

第二条线索在docs https://firebase.google.com/docs/auth/admin/manage-cookies#sign_in

假设一个应用程序是使用 httpOnly 服务器端 cookie,使用客户端 SDK 在登录页面上登录用户。生成 Firebase ID 令牌,然后通过 HTTP POST 将 ID 令牌发送到会话登录端点,在该端点中使用 Admin SDK 生成会话 cookie。论成功,应从客户端存储中清除状态.

如果您查看示例代码,甚至可以使用以下命令将持久性显式设置为 None 以从客户端清除状态firebase.auth().setPersistence(firebase.auth.Auth.Persistence.NONE);

因此,他们打算在初始身份验证之外客户端上不存在任何状态。他们明确明确了该状态并期望httponlycookie,这样客户端就无法获取 cookie(实际上只是 ID 令牌)并使用它来获取新的 cookie。

奇怪的是没有明确的方法清爽令牌客户端但它就在那里。你只能真正创建一个具有超长生命周期的会话cookie,并由服务器决定何时删除cookie或撤销刷新令牌等。

因此剩下另一个选择:管理客户端状态。一些示例和教程 https://cloud.google.com/appengine/docs/standard/python3/building-app/authenticating-users只需将 ID 令牌通过 cookie 从客户端发送到服务器即可。 satte 位于客户端,客户端可以使用 ID 令牌来使用所有 Firebase 功能。服务器可以验证用户身份并使用token等。

这个场景应该效果更好。如果服务器需要kick然后用户可以删除 cookie 撤销刷新令牌(诚然有点苛刻)。

希望有帮助。另一种方案是构建自定义令牌,然后您就可以完全控制。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何刷新 Firebase 会话 Cookie 的相关文章

随机推荐

  • 如何防止在暂停场景(取消暂停后)上运行 SKAction,暂停/取消暂停场景后节点纹理不改变

    我在暂停和取消暂停场景时遇到两个问题 我有按钮 playPause SKSpriteNode imageNamed buttPause png playPause name pause playPause setScale 0 65 pla
  • Javascript - 仅当我执行警报()时才有效

    我正在尝试在 iframe 中处理可内容编辑的正文 以防止浏览器添加br p or div按 Enter 键时自行执行 但是当尝试重置焦点时会发生一些奇怪的事情 并且在处理其余代码之前发出alert 时它确实起作用 我认为这是因为javas
  • PHP CLI 上的新行

    我有一个 php CLI 脚本 无法让输出换行 我愿意 echo this is my text r n echo next line 这给出了 this is my text r nnext line 关于如何在不同线路上获得输出有什么想
  • 获取资源编号值时出现错误无包标识符

    两项活动都在同一个包中 第二个活动使用第二个布局文件 setContentView R layout main2 Second Activity 中的这一行有错误 EditText text1 EditText findViewById R
  • MPDF整页背景

    我在这上面花了太多时间 但找不到一个好的 21 世纪解决方案 简而言之 我必须生成带有背景图像的 PDF 名片 但 MPDF 不是很有帮助 默认情况下我有 page sheet size 90mm 55mm margin 0 我尝试过了 使
  • 如何从 Angular 8 中 primeng p-editor 的工具栏中删除选项卡?

    这是m代码 tabIndex 1 适用于大多数情况 但不适用于选择标签和 ql image 我想从中删除所有选项卡 并希望焦点直接位于编辑器框中而不是工具中
  • EAS 构建找不到 aws-exports

    我有一个使用 AWS Amplify 的 Expo 项目 我目前正在使用 Expo 的 EAS 在移动设备上进行部署 我经常遇到这个错误 Metro encountered an error Unable to resolve module
  • 如何使用react-native-firebase从Firebase动态链接接收查询参数?

    我已经关注了说明 https rnfirebase io dynamic links usage来自官方react native firebase文档和一切 按照说明 工作正常 据我了解 我应该能够在 Firebase 动态链接控制台中创建
  • 如何将excel内部编码的小时数转换为R中的小时数? [复制]

    这个问题在这里已经有答案了 我有一个小时变量存储为 R 中的 Excel 内部编码 参见 https www ablebits com office addins blog 2015 06 23 excel time format now
  • 使用 vba 翻译文本

    可能是一个罕见的请愿书 但问题是这样的 我正在将第三方的 Excel 调整到我的组织中 Excel 是用英语开发的 而我组织的人员只会说西班牙语 我想使用与原始工作表完全相同的代码 我不想碰它 尽管我可以做到 所以我想使用每次出现 msgb
  • 如何使用kso​​ap2设置soap标题 - android

    我需要将肥皂头信息设置为 Web 方法身份验证的一部分 我在用着ksoap2用于调用 NET Web 服务的 API 这是带有请求的肥皂头
  • 用引号将文本包裹在 UILabel 中?

    默认情况下 UILabels 会截断文本 然后在末尾添加省略号 如何将所有文本 包括椭圆 用双引号引起来 Use two UILables 第一个保存文本 加上左引号 第二个仅保存右引号 text that is lon
  • 从基本矩阵估计 T 和 R

    我创建了一个简单的测试应用程序来执行翻译 T 和旋转 R 从基本矩阵进行估计 生成 50 个随机数Points 计算投影点集1 转换Points通过矩阵 R T 计算新的投影点集2 然后计算基础矩阵F 提取必要的矩阵 如E K2 T F K
  • 在 RecyclerView 中隐藏视图

    我有这样的代码 public static class MyViewHolder extends RecyclerView ViewHolder InjectView R id text TextView label public MyVi
  • Double 到 Byte 类型转换错误

    当执行转换时byte to double通过数学运算我得到了预期的结果 执行相同的数学运算来反转值的变化 只要我保持不变 就会得到正确的值double类型 但当最后我转变时double结果返回到bytevalue 转换结果不正确 1 这只是
  • 如果 SQL Server 中另一列不存在值,则按日期季度获取行数和总和组

    我有一些样本数据 Date Status OfferNum Amount 2016 10 30 1 2000 1000 00 2016 08 25 0 2000 1100 00 2016 07 12 0 2001 1200 00 2016
  • 如何为listview设置一个简单的适配器?

    我在将 arraylist 添加到列表视图时遇到问题 将在这里解释我的问题 告诉我这里出了什么问题 我有三个线性布局 在中间布局中我有列表视图 如下面的 xml 文件所示
  • 删除 Flex 中的所有事件侦听器

    如何一次删除所有组件上的所有事件侦听器 特别是当不知道每个组件附加了哪些侦听器时 您可以重写 UIComponent 继承的 mx core FlexSprite 并生成创建的侦听器数组 Doug McCune 发布源代码here http
  • 何时使用查询参数与矩阵参数?

    查询参数 http example com apples order random color blue 矩阵参数 http example com apples order random color blue 什么时候应该使用查询参数而不
  • 如何刷新 Firebase 会话 Cookie

    我正在开发一个使用 Node js Express js 作为后端的 Web 应用程序 我使用 Firebase 进行用户身份验证 并使用 Firebase Admin SDK 管理用户注册等 当用户想要登录时 我使用 Firebase C