I am a hobby programmer, so absolute beginner level.
I am working on a node.js app on Firebase, that requires a user either create or join a group. I have two methods on the frontend that call a different endpoint for each.
joinGroup()
works without any issues.
createNewGroup()
however, has weird issues:
- On the first attempt after user authentication, a new group is created successfully in Firestore, however, the response is not processed after
.then(response => {
- On subsequent attempts, no Firebase auth token is obtained in
fetchWithAuth
Thanks all for your help figuring this out!
Frontend:
function createNewGroup() {
console.log("Attempting to create group...");
const groupId = document.getElementById('group').value;
fetchWithAuth(`${endpointBaseUrl}/create-new-group`, {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({ groupId })
})
.then(response => {
console.log("Received response from fetch request inside createNewGroup");
console.log(response);
if (response.success) {
console.log("Successfully created group:", response.groupId);
} else {
console.error('Failed to create group:', response.message);
throw new Error('Failed to join group: ' + response.message);
}
})
.catch(error => {
console.error('Error creating new group:', error);
});
}
function joinGroup() {
const groupId = document.getElementById('group').value;
if (!groupId) {
console.error('Group ID is required');
document.getElementById('response').textContent = 'Please enter a group ID.';
return;
}
console.log('Joining group with ID:', groupId);
fetchWithAuth(`${endpointBaseUrl}/join-group`, {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({ groupId })
})
.then(response => {
console.log("Received response from fetch request inside joinGroup");
console.log(response);
if (response.success) {
console.log("Successfully joined group:", response.groupId);
document.getElementById('response').textContent = "Successfully joined group: " + response.message;
} else {
console.error('Failed to join group:', response.message);
document.getElementById('response').textContent = "Error joining group: " + response.message;
throw new Error('Failed to join group: ' + response.message);
}
})
.catch(error => {
console.error('Error joining group:', error);
document.getElementById('response').textContent = 'Error joining group: ' + error.message;
});
}
// Helper function to perform fetch requests with Firebase authentication
function fetchWithAuth(url, options = {}) {
console.log("Starting fetchWithAuth for URL:", url);
console.log("Starting fetchWithAuth with options:", options);
if (!firebase.auth().currentUser) {
console.error('No authenticated user.');
return Promise.reject(new Error('No authenticated user.'));
}
// Ensure headers are initialized in options to avoid undefined issues
if (!options.headers) {
console.log("Headers are empty");
options.headers = {};
}
return firebase.auth().currentUser.getIdToken(true)
.then(token => {
console.log("Obtained Firebase ID token.");
// Safely append the Authorization header to the existing headers
options.headers['Authorization'] = `Bearer ${token}`;
console.log("Headers set for request:", options.headers);
// Perform the fetch inside the then block to ensure headers are set after token retrieval
return fetch(url, options);
})
.then(response => {
console.log("Received response from fetch request.");
if (!response.ok) {
console.error('Network response was not ok:', response);
throw new Error('Network response was not ok');
}
return response.json();
})
.then(data => {
console.log("Parsed JSON data from response:", data);
return data;
})
.catch(error => {
console.error('Fetching with auth failed:', error);
throw error;
});
}
Backend:
// Endpoint to create a new group
app.post("/create-new-group", authenticate, async (req, res) => {
const newGroupId = generateRandomGroupId();
console.log("Backend attempting to create group with ID:", newGroupId);
try {
await admin.firestore().collection('groups').doc(newGroupId).set({
members: [req.user.uid]
});
res.json({ success: true, groupId: newGroupId, message: "Created group successfully" });
console.log("Backend created group with ID:", newGroupId);
} catch (error) {
console.error("Error creating new group:", error);
console.log("Backend error when attempting to create group with ID:", newGroupId);
}
});
// Endpoint to join an existing group
app.post("/join-group", authenticate, async (req, res) => {
const { groupId } = req.body;
console.log("Backend attempting to join group with ID:", groupId);
const groupRef = admin.firestore().collection('groups').doc(groupId);
try {
const groupDoc = await groupRef.get();
if (groupDoc.exists) {
const members = groupDoc.data().members;
members.push(req.user.uid);
await groupRef.update({ members });
res.json({ success: true, groupId: groupId, message: "Joined group successfully" });
} else {
res.status(404).json({ message: "Group not found" });
}
} catch (error) {
console.error("Error joining group:", error);
res.status(500).json({ success: false, message: "Internal server error" });
}
});