I’m not able to send an ID token to my server to establish a session in a Node,js web app with express-session.
I’m able to get the ID token from Firebase Auth after submitting a verification code, but I get an error, TypeError: Cannot read properties of undefined (reading 'token')
, when the /set-token
endpoint request is made in sendTokenToServer()
.
app.js
import express from 'express';
import session from 'express-session';
import admin from 'firebase-admin';
import { dirname, join } from 'path';
import { fileURLToPath } from 'url';
import serviceAccount from "../config/serviceAccount.js";
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
const app = express();
const port = 3000;
// Firebase Admin SDK setup
admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
});
// Middleware
app.use(session({
secret: 'your-secret-key',
resave: false,
saveUninitialized: true,
// cookie: { secure: false } // Set to true if using HTTPS
cookie: { secure: false, httpOnly: true, maxAge: 24 * 60 * 60 * 1000 } // 1 day
}));
app.use(express.static(join(__dirname, 'public')));
// Set view engine
app.set('view engine', 'ejs');
app.set('views', join(__dirname, 'views'));
// Auth middleware
const checkAuth = async (req, res, next) => {
const token = req.body.token;
if (!token) {
console.log('No Session token:');
return res.redirect('/');
}
try {
const decodedToken = await admin.auth().verifyIdToken(token);
console.log('Decoded token:', decodedToken); // Add logging here
req.user = decodedToken;
next();
} catch (error) {
console.error('Error verifying token:', error);
res.redirect('/');
}
};
app.post('/set-token', (req, res) => {
// TODO token is undefined here <--------------------------------------------------------<<<
const token = req.session.token;
req.session.token = token;
res.sendStatus(200);
});
// Routes
app.get('/', (req, res) => {
res.render('login');
});
app.get('/feed', checkAuth, (req, res) => {
res.render('feed');
});
app.get('/dashboard', checkAuth, (req, res) => {
res.render('dashboard');
});
app.get('/post/:id', checkAuth, (req, res) => {
res.render('post', { id: req.params.id });
});
app.listen(port, () => {
console.log(`Server is running on http://localhost:${port}`);
});
login.js
const countryCode = '+1';
document.getElementById('send-code').addEventListener('click', handleSendCode);
document.getElementById('verify-code').addEventListener('click', handleVerifyCode);
function handleSendCode() {
const phoneNumber = getPhoneNumber();
const recaptchaVerifier = createRecaptchaVerifier();
signInWithPhoneNumber(phoneNumber, recaptchaVerifier)
.then(handleConfirmationResult)
.catch(handleSendCodeError);
}
function getPhoneNumber() {
return countryCode + document.getElementById('phone-number').value;
}
function createRecaptchaVerifier() {
return new firebase.auth.RecaptchaVerifier('recaptcha-container');
}
function signInWithPhoneNumber(phoneNumber, recaptchaVerifier) {
return firebase.auth().signInWithPhoneNumber(phoneNumber, recaptchaVerifier);
}
function handleConfirmationResult(confirmationResult) {
window.confirmationResult = confirmationResult;
toggleLoginSteps();
}
function toggleLoginSteps() {
document.getElementById('login-step-1').style.display = 'none';
document.getElementById('login-step-2').style.display = 'block';
}
function handleSendCodeError(error) {
console.error('Error sending verification code:', error);
}
function handleVerifyCode() {
const verificationCode = getVerificationCode();
confirmVerificationCode(verificationCode)
.then(handleVerificationSuccess)
.catch(handleVerificationError);
}
function getVerificationCode() {
return document.getElementById('verification-code').value;
}
function confirmVerificationCode(verificationCode) {
return window.confirmationResult.confirm(verificationCode);
}
async function handleVerificationSuccess(result) {
const user = result.user;
const idToken = await user.getIdToken();
sendTokenToServer(idToken)
.then(handleTokenResponse)
.catch(handleTokenError);
}
function sendTokenToServer(idToken) {
return fetch('/set-token', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ token: idToken }) // <---------------------------------------------<<<
});
}
function handleTokenResponse(response) {
if (response.ok) {
window.location.href = '/feed';
} else {
console.error('Failed to set token');
}
}
function handleTokenError(error) {
console.error('Error sending token:', error);
}
function handleVerificationError(error) {
console.error('Error verifying code:', error);
}
I tried to copy the ID token after the user.getIdToken()
call and sending the ID token to the /set-token
endpoint with Postman and get the same error — TypeError: Cannot read properties of undefined
.
Bianco is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.