Я разрабатываю веб-приложение, используя Node.js / Express.js для бэкэнда, и использую 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Идентификационный токен, который я отправляю конечной точке на сервере, чтобы обменять его на cookie-файл сеанса, который требует идентичный токен идентификатора, поскольку срок действия последнего истекает через 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')
});
}
}
Чтобы отобразить информацию пользователя наview Я устанавливаю декодированные заявки на переменную res.locals.user
и передаю ее следующему промежуточному программному обеспечению, где я отображаю представление и передаю эту переменную следующим образом.
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
});
});
}
Теперь представление обновляется, когда пользователь отправляет форму, потому что я установил переменную res.locals.user
в новое userRecord
, но как только он обновил страницу,Представление показывает старые учетные данные, потому что перед любым запросом get для защищенного содержимого выполняется промежуточное программное обеспечение isAuthenticated
, а последующее получает информацию о пользователе из cookie-файла сеанса, который содержит старые пользовательские учетные данные, прежде чем он обновил их.
ИтакПока это выводы, к которым я пришел и что я пытался сделать:
Если я хочу, чтобы представление правильно отображалось, я должен выйти и войти снова, чтобы получить новый идентификатор Firebase IDтокен для создания нового файла cookie сеанса, который не является опцией.
Я попытался обновитьcookie сеанса путем создания нового ID-токена из Admin SDK, но, похоже, эта опция недоступна, и я не могу сделать это через клиентский SDK, поскольку пользователь уже вошел в систему.
Сохранение идентификатора токена для использования в дальнейшем при создании файлов cookie сеанса не является вариантом, так как срок их действия истекает через 1 час.
Я, черт возьми, решил эту проблему, прежде чем опубликовать ее здесь, поэтомулюбая помощь очень ценится.