gpt4 book ai didi

javascript - 如何刷新 Firebase session Cookie

转载 作者:搜寻专家 更新时间:2023-10-31 23:57:07 24 4
gpt4 key购买 nike

我正在开发一个使用 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 token ,我将其发送到服务器上的端点以将其交换为具有以下内容的 session cookie由于后者在 1 小时后过期,因此同样要求 ID token 。

// 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!');
});
});

我创建了一个中间件来验证用户 session cookie,然后再让他访问 protected 内容,如下所示:

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')
});
}
}

为了在 View 上显示用户信息,我在 res.locals.user 变量上设置了解码声明,并将其传递给下一个中间件,我在其中呈现 View 并像这样传递该变量。

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

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

// 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
});
});
}

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

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

  • 如果我希望 View 正确呈现,我应该注销并重新登录以获取新的 Firebase ID token 来创建新的 session cookie,这不是一个选项。

  • 我试图通过从 Admin SDK 创建一个新的 ID token 来刷新 session cookie,但它似乎没有此选项可用,而且我无法通过客户端 SDK 执行此操作,因为用户已经已登录。

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

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

最佳答案

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

来自 Firebase docs

Firebase Auth provides server-side session cookie management for traditional websites that rely on session cookies. This solution has several advantages over client-side short-lived ID tokens, which may require a redirect mechanism each time to update the session cookie on expiration:

所以他们在这里暗示您要管理 session 及其来自服务器的生命周期。

第二条线索在 docs

Assuming an application is using httpOnly server side cookies, sign in a user on the login page using the client SDKs. A Firebase ID token is generated, and the ID token is then sent via HTTP POST to a session login endpoint where, using the Admin SDK, a session cookie is generated. On success, the state should be cleared from the client side storage.

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

所以他们打算在客户端上没有超出初始身份验证的状态。他们明确清除该状态并期望一个 httponly cookie,这样客户端就无法获取 cookie(实际上只是 ID token )并使用它来获取新的。

奇怪的是,没有明确的方法刷新 token 客户端,但确实存在。你只能真正创建一个超长生命周期的 session cookie,并由服务器决定何时删除cookie或撤销刷新 token 等。

因此剩下另一个选择:在客户端管理状态。一些examples and tutorials只需将 ID token 从客户端发送到 cookie 中的服务器即可。 satte 位于客户端上,客户端可以使用 ID token 来使用所有 firebase 功能。服务器可以验证用户身份并使用token等。

这种情况应该会更好。如果服务器需要用户,那么它可以删除 cookie 撤销刷新 token (诚然有点苛刻)。

希望对您有所帮助。另一种方案是构建自定义 token ,然后您就拥有了完全的控制权。

关于javascript - 如何刷新 Firebase session Cookie,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52684631/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com