io2015-codelabs
io2015-codelabs copied to clipboard
Firebase codelab oauth does not trigger child_added
Was going through this codelab: https://codelabs.developers.google.com/codelabs/cloud-firebase-chat/index.html#5
It stopped working once I added the security rules (".read": "auth != null").
The reason why seems to be that it tries to run all the child_added events on page load or soon after, and fails since auth is not present. Then the user authenticates using the popup, but the child_added events are not retried and the page remains empty of new 'messages'.
If the auth 'remember' is switched to 'sessionOnly', then I can reload the page and it works - the auth is already present when those child_added events come in and it all works. However, the code as presented in the codelab does not work.
If the child_added callback is added after auth, then it works.
<script>
var myFirebase = new Firebase('https://____________.firebaseio.com/');
var username = null;
var loginButton = document.querySelector('#login');
var textInput = document.querySelector('#text');
var postButton = document.querySelector('#post');
postButton.style.display = "none";
textInput.style.display = "none";
var startListening = function() { // <------------------------- Do not add listener yet!!
myFirebase.on('child_added', function(snapshot) {
var msg = snapshot.val();
var msgUsernameElement = document.createElement("b");
msgUsernameElement.textContent = msg.username;
var msgTextElement = document.createElement("p");
msgTextElement.textContent = msg.text;
var msgElement = document.createElement("div");
msgElement.appendChild(msgUsernameElement);
msgElement.appendChild(msgTextElement);
msgElement.className = "msg";
document.getElementById("results").appendChild(msgElement);
});
};
postButton.addEventListener("click", function() {
var msgUser = username;
var msgText = textInput.value;
myFirebase.push({username:msgUser, text:msgText});
textInput.value = "";
});
loginButton.addEventListener("click", function() {
myFirebase.authWithOAuthPopup("google", function(error, authData) {
if (error) {
console.log(error);
} else {
console.log(authData);
}
}, {remember: "none"}); // will end authentication on page close/reload
});
myFirebase.onAuth(function (authData) {
if (authData) {
username = authData.google.displayName;
loginButton.textContent = "Logged in as " + username;
loginButton.disabled = true;
postButton.style.display = "block";
textInput.style.display = "block";
startListening(); // <-------------------------------------- Add listener now
}
});
</script>
@wgittoes thank you for the detailed report. I believe you are correct that there is a bug in this codelab. Firebase listeners only check auth state once: when they are created. So if you create a listener to an authenticated path when you are unauthenticated it will never return data, even if you later authenticate.